summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile.am2
-rw-r--r--man/resolved.conf.xml14
-rw-r--r--src/resolve/resolved-conf.c84
-rw-r--r--src/resolve/resolved-conf.h7
-rw-r--r--src/resolve/resolved-dns-scope.c18
-rw-r--r--src/resolve/resolved-dns-scope.h4
-rw-r--r--src/resolve/resolved-dns-search-domain.c223
-rw-r--r--src/resolve/resolved-dns-search-domain.h71
-rw-r--r--src/resolve/resolved-gperf.gperf1
-rw-r--r--src/resolve/resolved-link.c46
-rw-r--r--src/resolve/resolved-link.h6
-rw-r--r--src/resolve/resolved-manager.c2
-rw-r--r--src/resolve/resolved-manager.h5
-rw-r--r--src/resolve/resolved-resolv-conf.c35
-rw-r--r--src/resolve/resolved.conf.in1
15 files changed, 488 insertions, 31 deletions
diff --git a/Makefile.am b/Makefile.am
index cac5c5e3c7..296f2c7e5f 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -5165,6 +5165,8 @@ systemd_resolved_SOURCES = \
src/resolve/resolved-dns-scope.c \
src/resolve/resolved-dns-server.h \
src/resolve/resolved-dns-server.c \
+ src/resolve/resolved-dns-search-domain.h \
+ src/resolve/resolved-dns-search-domain.c \
src/resolve/resolved-dns-cache.h \
src/resolve/resolved-dns-cache.c \
src/resolve/resolved-dns-zone.h \
diff --git a/man/resolved.conf.xml b/man/resolved.conf.xml
index c9034a979f..4680b6a4e5 100644
--- a/man/resolved.conf.xml
+++ b/man/resolved.conf.xml
@@ -1,4 +1,4 @@
-<?xml version='1.0'?> <!--*-nxml-*-->
+<?xml version='1.0'?> <!--*- Mode: nxml; nxml-child-indent: 2; indent-tabs-mode: nil -*-->
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
@@ -77,7 +77,7 @@
sent to one of the listed DNS servers in parallel to any
per-interface DNS servers acquired from
<citerefentry><refentrytitle>systemd-networkd.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>.
- For compatibility reasons, if this setting is not specified, ,
+ For compatibility reasons, if this setting is not specified,
the DNS servers listed in
<filename>/etc/resolv.conf</filename> are used instead, if
that file exists and any servers are configured in it. This
@@ -99,6 +99,16 @@
</varlistentry>
<varlistentry>
+ <term><varname>Domains=</varname></term>
+ <listitem><para>A space-separated list of search domains. For
+ compatibility reasons, if this setting is not specified, the
+ search domains listed in <filename>/etc/resolv.conf</filename>
+ are used instead, if that file exists and any domains are
+ configured in it. This setting defaults to the empty
+ list.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
<term><varname>LLMNR=</varname></term>
<listitem><para>Takes a boolean argument or
<literal>resolve</literal>. Controls Link-Local Multicast Name
diff --git a/src/resolve/resolved-conf.c b/src/resolve/resolved-conf.c
index c11a8badd9..dbac45170f 100644
--- a/src/resolve/resolved-conf.c
+++ b/src/resolve/resolved-conf.c
@@ -71,10 +71,49 @@ int manager_parse_dns_server_string_and_warn(Manager *m, DnsServerType type, con
break;
r = manager_add_dns_server_by_string(m, type, word);
- if (r < 0) {
+ if (r < 0)
log_warning_errno(r, "Failed to add DNS server address '%s', ignoring.", word);
- continue;
- }
+ }
+
+ return 0;
+}
+
+int manager_add_search_domain_by_string(Manager *m, const char *domain) {
+ DnsSearchDomain *d;
+ int r;
+
+ assert(m);
+ assert(domain);
+
+ r = dns_search_domain_find(m->search_domains, domain, &d);
+ if (r < 0)
+ return r;
+ if (r > 0) {
+ dns_search_domain_move_back_and_unmark(d);
+ return 0;
+ }
+
+ return dns_search_domain_new(m, NULL, DNS_SEARCH_DOMAIN_SYSTEM, NULL, domain);
+}
+
+int manager_parse_search_domains_and_warn(Manager *m, const char *string) {
+ int r;
+
+ assert(m);
+ assert(string);
+
+ for(;;) {
+ _cleanup_free_ char *word = NULL;
+
+ r = extract_first_word(&string, &word, NULL, EXTRACT_QUOTES);
+ if (r < 0)
+ return r;
+ if (r == 0)
+ break;
+
+ r = manager_add_search_domain_by_string(m, word);
+ if (r < 0)
+ log_warning_errno(r, "Failed to add search domain '%s', ignoring.", word);
}
return 0;
@@ -122,6 +161,45 @@ int config_parse_dns_servers(
return 0;
}
+int config_parse_search_domains(
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+
+ Manager *m = userdata;
+ int r;
+
+ assert(filename);
+ assert(lvalue);
+ assert(rvalue);
+ assert(m);
+
+ if (isempty(rvalue))
+ /* Empty assignment means clear the list */
+ dns_search_domain_unlink_all(m->search_domains);
+ else {
+ /* Otherwise, add to the list */
+ r = manager_parse_search_domains_and_warn(m, rvalue);
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse search domains string '%s'. Ignoring.", rvalue);
+ return 0;
+ }
+ }
+
+ /* If we have a manual setting, then we stop reading
+ * /etc/resolv.conf */
+ m->read_resolv_conf = false;
+
+ return 0;
+}
+
int config_parse_support(
const char *unit,
const char *filename,
diff --git a/src/resolve/resolved-conf.h b/src/resolve/resolved-conf.h
index 170f3e94aa..28d2549d35 100644
--- a/src/resolve/resolved-conf.h
+++ b/src/resolve/resolved-conf.h
@@ -23,13 +23,16 @@
#include "resolved-manager.h"
-int manager_parse_dns_server(Manager *m, DnsServerType type, const char *string);
int manager_parse_config_file(Manager *m);
-int manager_parse_dns_server_string_and_warn(Manager *m, DnsServerType type, const char *string);
+int manager_add_search_domain_by_string(Manager *m, const char *domain);
+int manager_parse_search_domains_and_warn(Manager *m, const char *string);
+
int manager_add_dns_server_by_string(Manager *m, DnsServerType type, const char *word);
+int manager_parse_dns_server_string_and_warn(Manager *m, DnsServerType type, const char *string);
const struct ConfigPerfItem* resolved_gperf_lookup(const char *key, unsigned length);
int config_parse_dns_servers(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
+int config_parse_search_domains(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
int config_parse_support(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
diff --git a/src/resolve/resolved-dns-scope.c b/src/resolve/resolved-dns-scope.c
index 5174502af0..2e47691c56 100644
--- a/src/resolve/resolved-dns-scope.c
+++ b/src/resolve/resolved-dns-scope.c
@@ -103,7 +103,6 @@ DnsScope* dns_scope_free(DnsScope *s) {
dns_zone_flush(&s->zone);
LIST_REMOVE(scopes, s->manager->dns_scopes, s);
- strv_free(s->domains);
free(s);
return NULL;
@@ -323,7 +322,7 @@ int dns_scope_tcp_socket(DnsScope *s, int family, const union in_addr_union *add
}
DnsScopeMatch dns_scope_good_domain(DnsScope *s, int ifindex, uint64_t flags, const char *domain) {
- char **i;
+ DnsSearchDomain *d;
assert(s);
assert(domain);
@@ -345,8 +344,8 @@ DnsScopeMatch dns_scope_good_domain(DnsScope *s, int ifindex, uint64_t flags, co
dns_name_equal(domain, "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa") > 0)
return DNS_SCOPE_NO;
- STRV_FOREACH(i, s->domains)
- if (dns_name_endswith(domain, *i) > 0)
+ LIST_FOREACH(domains, d, dns_scope_get_search_domains(s))
+ if (dns_name_endswith(domain, d->name) > 0)
return DNS_SCOPE_YES;
switch (s->protocol) {
@@ -850,3 +849,14 @@ void dns_scope_dump(DnsScope *s, FILE *f) {
dns_cache_dump(&s->cache, f);
}
}
+
+DnsSearchDomain *dns_scope_get_search_domains(DnsScope *s) {
+
+ if (s->protocol != DNS_PROTOCOL_DNS)
+ return NULL;
+
+ if (s->link)
+ return s->link->search_domains;
+
+ return NULL;
+}
diff --git a/src/resolve/resolved-dns-scope.h b/src/resolve/resolved-dns-scope.h
index f9b2bfda9d..f69d51b203 100644
--- a/src/resolve/resolved-dns-scope.h
+++ b/src/resolve/resolved-dns-scope.h
@@ -47,8 +47,6 @@ struct DnsScope {
Link *link;
- char **domains;
-
DnsCache cache;
DnsZone zone;
@@ -91,3 +89,5 @@ int dns_scope_notify_conflict(DnsScope *scope, DnsResourceRecord *rr);
void dns_scope_check_conflicts(DnsScope *scope, DnsPacket *p);
void dns_scope_dump(DnsScope *s, FILE *f);
+
+DnsSearchDomain *dns_scope_get_search_domains(DnsScope *s);
diff --git a/src/resolve/resolved-dns-search-domain.c b/src/resolve/resolved-dns-search-domain.c
new file mode 100644
index 0000000000..5d927bb2a1
--- /dev/null
+++ b/src/resolve/resolved-dns-search-domain.c
@@ -0,0 +1,223 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+ This file is part of systemd.
+
+ Copyright 2015 Lennart Poettering
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include "alloc-util.h"
+#include "dns-domain.h"
+#include "resolved-dns-search-domain.h"
+
+int dns_search_domain_new(
+ Manager *m,
+ DnsSearchDomain **ret,
+ DnsSearchDomainType type,
+ Link *l,
+ const char *name) {
+
+ _cleanup_free_ char *normalized = NULL;
+ DnsSearchDomain *d, *tail;
+ int r;
+
+ assert(m);
+ assert((type == DNS_SEARCH_DOMAIN_LINK) == !!l);
+ assert(name);
+
+ r = dns_name_normalize(name, &normalized);
+ if (r < 0)
+ return r;
+
+ r = dns_name_root(normalized);
+ if (r < 0)
+ return r;
+ if (r > 0)
+ return -EINVAL;
+
+ d = new0(DnsSearchDomain, 1);
+ if (!d)
+ return -ENOMEM;
+
+ d->n_ref = 1;
+ d->manager = m;
+ d->type = type;
+ d->name = normalized;
+ normalized = NULL;
+
+ switch (type) {
+
+ case DNS_SEARCH_DOMAIN_LINK:
+ d->link = l;
+ LIST_FIND_TAIL(domains, l->search_domains, tail);
+ LIST_INSERT_AFTER(domains, l->search_domains, tail, d);
+ break;
+
+ case DNS_SERVER_SYSTEM:
+ LIST_FIND_TAIL(domains, m->search_domains, tail);
+ LIST_INSERT_AFTER(domains, m->search_domains, tail, d);
+ break;
+
+ default:
+ assert_not_reached("Unknown search domain type");
+ }
+
+ d->linked = true;
+
+ if (ret)
+ *ret = d;
+
+ return 0;
+}
+
+DnsSearchDomain* dns_search_domain_ref(DnsSearchDomain *d) {
+ if (!d)
+ return NULL;
+
+ assert(d->n_ref > 0);
+ d->n_ref++;
+
+ return d;
+}
+
+DnsSearchDomain* dns_search_domain_unref(DnsSearchDomain *d) {
+ if (!d)
+ return NULL;
+
+ assert(d->n_ref > 0);
+ d->n_ref--;
+
+ if (d->n_ref > 0)
+ return NULL;
+
+ free(d->name);
+ free(d);
+
+ return NULL;
+}
+
+void dns_search_domain_unlink(DnsSearchDomain *d) {
+ assert(d);
+ assert(d->manager);
+
+ if (!d->linked)
+ return;
+
+ switch (d->type) {
+
+ case DNS_SEARCH_DOMAIN_LINK:
+ assert(d->link);
+ LIST_REMOVE(domains, d->link->search_domains, d);
+ break;
+
+ case DNS_SEARCH_DOMAIN_SYSTEM:
+ LIST_REMOVE(domains, d->manager->search_domains, d);
+ break;
+ }
+
+ d->linked = false;
+
+ dns_search_domain_unref(d);
+}
+
+void dns_search_domain_move_back_and_unmark(DnsSearchDomain *d) {
+ DnsSearchDomain *tail;
+
+ assert(d);
+
+ if (!d->marked)
+ return;
+
+ d->marked = false;
+
+ if (!d->linked || !d->domains_next)
+ return;
+
+ switch (d->type) {
+
+ case DNS_SEARCH_DOMAIN_LINK:
+ assert(d->link);
+ LIST_FIND_TAIL(domains, d, tail);
+ LIST_REMOVE(domains, d->link->search_domains, d);
+ LIST_INSERT_AFTER(domains, d->link->search_domains, tail, d);
+ break;
+
+ case DNS_SEARCH_DOMAIN_SYSTEM:
+ LIST_FIND_TAIL(domains, d, tail);
+ LIST_REMOVE(domains, d->manager->search_domains, d);
+ LIST_INSERT_AFTER(domains, d->manager->search_domains, tail, d);
+ break;
+
+ default:
+ assert_not_reached("Unknown search domain type");
+ }
+}
+
+void dns_search_domain_unlink_all(DnsSearchDomain *first) {
+ DnsSearchDomain *next;
+
+ if (!first)
+ return;
+
+ next = first->domains_next;
+ dns_search_domain_unlink(first);
+
+ dns_search_domain_unlink_all(next);
+}
+
+void dns_search_domain_unlink_marked(DnsSearchDomain *first) {
+ DnsSearchDomain *next;
+
+ if (!first)
+ return;
+
+ next = first->domains_next;
+
+ if (first->marked)
+ dns_search_domain_unlink(first);
+
+ dns_search_domain_unlink_marked(next);
+}
+
+void dns_search_domain_mark_all(DnsSearchDomain *first) {
+ if (!first)
+ return;
+
+ first->marked = true;
+ dns_search_domain_mark_all(first->domains_next);
+}
+
+int dns_search_domain_find(DnsSearchDomain *first, const char *name, DnsSearchDomain **ret) {
+ DnsSearchDomain *d;
+ int r;
+
+ assert(name);
+ assert(ret);
+
+ LIST_FOREACH(domains, d, first) {
+
+ r = dns_name_equal(name, d->name);
+ if (r < 0)
+ return r;
+ if (r > 0) {
+ *ret = d;
+ return 1;
+ }
+ }
+
+ *ret = NULL;
+ return 0;
+}
diff --git a/src/resolve/resolved-dns-search-domain.h b/src/resolve/resolved-dns-search-domain.h
new file mode 100644
index 0000000000..20b441206c
--- /dev/null
+++ b/src/resolve/resolved-dns-search-domain.h
@@ -0,0 +1,71 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+#pragma once
+
+/***
+ This file is part of systemd.
+
+ Copyright 2015 Lennart Poettering
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include "macro.h"
+
+typedef struct DnsSearchDomain DnsSearchDomain;
+
+typedef enum DnsSearchDomainType {
+ DNS_SEARCH_DOMAIN_SYSTEM,
+ DNS_SEARCH_DOMAIN_LINK,
+} DnsSearchDomainType;
+
+#include "resolved-link.h"
+#include "resolved-manager.h"
+
+struct DnsSearchDomain {
+ Manager *manager;
+
+ unsigned n_ref;
+
+ DnsSearchDomainType type;
+ Link *link;
+
+ char *name;
+
+ bool marked:1;
+
+ bool linked:1;
+ LIST_FIELDS(DnsSearchDomain, domains);
+};
+
+int dns_search_domain_new(
+ Manager *m,
+ DnsSearchDomain **ret,
+ DnsSearchDomainType type,
+ Link *link,
+ const char *name);
+
+DnsSearchDomain* dns_search_domain_ref(DnsSearchDomain *d);
+DnsSearchDomain* dns_search_domain_unref(DnsSearchDomain *d);
+
+void dns_search_domain_unlink(DnsSearchDomain *d);
+void dns_search_domain_move_back_and_unmark(DnsSearchDomain *d);
+
+void dns_search_domain_unlink_all(DnsSearchDomain *first);
+void dns_search_domain_unlink_marked(DnsSearchDomain *first);
+void dns_search_domain_mark_all(DnsSearchDomain *first);
+
+int dns_search_domain_find(DnsSearchDomain *first, const char *name, DnsSearchDomain **ret);
+
+DEFINE_TRIVIAL_CLEANUP_FUNC(DnsSearchDomain*, dns_search_domain_unref);
diff --git a/src/resolve/resolved-gperf.gperf b/src/resolve/resolved-gperf.gperf
index dc4ef74b8c..50662656d5 100644
--- a/src/resolve/resolved-gperf.gperf
+++ b/src/resolve/resolved-gperf.gperf
@@ -16,4 +16,5 @@ struct ConfigPerfItem;
%%
Resolve.DNS, config_parse_dns_servers, DNS_SERVER_SYSTEM, 0
Resolve.FallbackDNS, config_parse_dns_servers, DNS_SERVER_FALLBACK, 0
+Resolve.Domains, config_parse_search_domains, 0, 0
Resolve.LLMNR, config_parse_support, 0, offsetof(Manager, llmnr_support)
diff --git a/src/resolve/resolved-link.c b/src/resolve/resolved-link.c
index 4931fc9d3b..c367160d98 100644
--- a/src/resolve/resolved-link.c
+++ b/src/resolve/resolved-link.c
@@ -66,6 +66,7 @@ Link *link_free(Link *l) {
return NULL;
link_flush_dns_servers(l);
+ dns_search_domain_unlink_all(l->search_domains);
while (l->addresses)
link_address_free(l->addresses);
@@ -219,29 +220,56 @@ clear:
return r;
}
-static int link_update_domains(Link *l) {
+static int link_update_search_domains(Link *l) {
+ _cleanup_strv_free_ char **domains = NULL;
+ char **i;
int r;
- if (!l->unicast_scope)
- return 0;
-
- l->unicast_scope->domains = strv_free(l->unicast_scope->domains);
+ assert(l);
- r = sd_network_link_get_domains(l->ifindex,
- &l->unicast_scope->domains);
+ r = sd_network_link_get_domains(l->ifindex, &domains);
if (r < 0)
- return r;
+ goto clear;
+
+ dns_search_domain_mark_all(l->search_domains);
+
+ STRV_FOREACH(i, domains) {
+ DnsSearchDomain *d;
+ r = dns_search_domain_find(l->search_domains, *i, &d);
+ if (r < 0)
+ goto clear;
+
+ if (r > 0)
+ dns_search_domain_move_back_and_unmark(d);
+ else {
+ r = dns_search_domain_new(l->manager, NULL, DNS_SEARCH_DOMAIN_LINK, l, *i);
+ if (r < 0)
+ goto clear;
+ }
+ }
+
+ dns_search_domain_unlink_marked(l->search_domains);
return 0;
+
+clear:
+ dns_search_domain_unlink_all(l->search_domains);
+ return r;
}
int link_update_monitor(Link *l) {
+ int r;
+
assert(l);
link_update_dns_servers(l);
link_update_llmnr_support(l);
link_allocate_scopes(l);
- link_update_domains(l);
+
+ r = link_update_search_domains(l);
+ if (r < 0)
+ log_warning_errno(r, "Failed to read search domains for interface %s, ignoring: %m", l->name);
+
link_add_rrs(l, false);
return 0;
diff --git a/src/resolve/resolved-link.h b/src/resolve/resolved-link.h
index 76e96e733a..d72461de06 100644
--- a/src/resolve/resolved-link.h
+++ b/src/resolve/resolved-link.h
@@ -30,6 +30,8 @@ typedef struct Link Link;
typedef struct LinkAddress LinkAddress;
#include "resolved-dns-rr.h"
+#include "resolved-dns-search-domain.h"
+#include "resolved-dns-server.h"
#include "resolved-manager.h"
struct LinkAddress {
@@ -57,6 +59,8 @@ struct Link {
LIST_HEAD(DnsServer, dns_servers);
DnsServer *current_dns_server;
+ LIST_HEAD(DnsSearchDomain, search_domains);
+
Support llmnr_support;
DnsScope *unicast_scope;
@@ -84,6 +88,8 @@ DnsServer* link_find_dns_server(Link *l, int family, const union in_addr_union *
DnsServer* link_get_dns_server(Link *l);
void link_next_dns_server(Link *l);
+void link_flush_search_domains(Link *l);
+
int link_address_new(Link *l, LinkAddress **ret, int family, const union in_addr_union *in_addr);
LinkAddress *link_address_free(LinkAddress *a);
int link_address_update_rtnl(LinkAddress *a, sd_netlink_message *m);
diff --git a/src/resolve/resolved-manager.c b/src/resolve/resolved-manager.c
index c3c61a0893..0771ac840f 100644
--- a/src/resolve/resolved-manager.c
+++ b/src/resolve/resolved-manager.c
@@ -536,6 +536,8 @@ Manager *manager_free(Manager *m) {
manager_flush_dns_servers(m, DNS_SERVER_SYSTEM);
manager_flush_dns_servers(m, DNS_SERVER_FALLBACK);
+ dns_search_domain_unlink_all(m->search_domains);
+
while ((l = hashmap_first(m->links)))
link_free(l);
diff --git a/src/resolve/resolved-manager.h b/src/resolve/resolved-manager.h
index 8a716b3ceb..0683e23f6c 100644
--- a/src/resolve/resolved-manager.h
+++ b/src/resolve/resolved-manager.h
@@ -40,6 +40,8 @@ enum Support {
};
#include "resolved-dns-query.h"
+#include "resolved-dns-search-domain.h"
+#include "resolved-dns-server.h"
#include "resolved-dns-stream.h"
#include "resolved-link.h"
@@ -70,7 +72,10 @@ struct Manager {
LIST_HEAD(DnsServer, fallback_dns_servers);
DnsServer *current_dns_server;
+ LIST_HEAD(DnsSearchDomain, search_domains);
+
bool need_builtin_fallbacks:1;
+
bool read_resolv_conf:1;
usec_t resolv_conf_mtime;
diff --git a/src/resolve/resolved-resolv-conf.c b/src/resolve/resolved-resolv-conf.c
index 98c1720f0f..2ab0008fce 100644
--- a/src/resolve/resolved-resolv-conf.c
+++ b/src/resolve/resolved-resolv-conf.c
@@ -86,13 +86,12 @@ int manager_read_resolv_conf(Manager *m) {
}
manager_mark_dns_servers(m, DNS_SERVER_SYSTEM);
+ dns_search_domain_mark_all(m->search_domains);
FOREACH_LINE(line, f, r = -errno; goto clear) {
const char *a;
char *l;
- truncate_nl(line);
-
l = strstrip(line);
if (*l == '#' || *l == ';')
continue;
@@ -105,9 +104,22 @@ int manager_read_resolv_conf(Manager *m) {
continue;
}
+
+ a = first_word(l, "domain");
+ if (!a) /* We treat "domain" lines, and "search" lines as equivalent, and add both to our list. */
+ a = first_word(l, "search");
+ if (a) {
+ r = manager_parse_search_domains_and_warn(m, a);
+ if (r < 0)
+ log_warning_errno(r, "Failed to parse search domain string '%s', ignoring.", a);
+ }
}
+ /* Flush out all servers and search domains that are still
+ * marked. Those are then ones that didn't appear in the new
+ * /etc/resolv.conf */
manager_flush_marked_dns_servers(m, DNS_SERVER_SYSTEM);
+ dns_search_domain_unlink_marked(m->search_domains);
/* Whenever /etc/resolv.conf changes, start using the first
* DNS server of it. This is useful to deal with broken
@@ -123,6 +135,7 @@ int manager_read_resolv_conf(Manager *m) {
clear:
manager_flush_dns_servers(m, DNS_SERVER_SYSTEM);
+ dns_search_domain_unlink_all(m->search_domains);
return r;
}
@@ -211,6 +224,7 @@ int manager_write_resolv_conf(Manager *m) {
_cleanup_free_ char *temp_path = NULL;
_cleanup_fclose_ FILE *f = NULL;
_cleanup_ordered_set_free_ OrderedSet *dns = NULL, *domains = NULL;
+ DnsSearchDomain *d;
DnsServer *s;
Iterator i;
Link *l;
@@ -239,10 +253,16 @@ int manager_write_resolv_conf(Manager *m) {
return r;
}
+ LIST_FOREACH(domains, d, m->search_domains) {
+ r = ordered_set_put(domains, d->name);
+ if (r == -EEXIST)
+ continue;
+ if (r < 0)
+ return r;
+ }
+
/* Then, add the per-link servers and domains */
HASHMAP_FOREACH(l, m->links, i) {
- char **domain;
-
LIST_FOREACH(servers, s, l->dns_servers) {
r = ordered_set_put(dns, s);
if (r == -EEXIST)
@@ -251,11 +271,8 @@ int manager_write_resolv_conf(Manager *m) {
return r;
}
- if (!l->unicast_scope)
- continue;
-
- STRV_FOREACH(domain, l->unicast_scope->domains) {
- r = ordered_set_put(domains, *domain);
+ LIST_FOREACH(domains, d, l->search_domains) {
+ r = ordered_set_put(domains, d->name);
if (r == -EEXIST)
continue;
if (r < 0)
diff --git a/src/resolve/resolved.conf.in b/src/resolve/resolved.conf.in
index 3eb19e42b7..39ecf83217 100644
--- a/src/resolve/resolved.conf.in
+++ b/src/resolve/resolved.conf.in
@@ -14,4 +14,5 @@
[Resolve]
#DNS=
#FallbackDNS=@DNS_SERVERS@
+#Domains=
#LLMNR=yes