diff options
Diffstat (limited to 'src/resolve/resolved-conf.c')
-rw-r--r-- | src/resolve/resolved-conf.c | 196 |
1 files changed, 147 insertions, 49 deletions
diff --git a/src/resolve/resolved-conf.c b/src/resolve/resolved-conf.c index 7af63b0a82..abf3263178 100644 --- a/src/resolve/resolved-conf.c +++ b/src/resolve/resolved-conf.c @@ -1,5 +1,3 @@ -/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ - /*** This file is part of systemd. @@ -19,56 +17,136 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ +#include "alloc-util.h" #include "conf-parser.h" - +#include "def.h" +#include "extract-word.h" +#include "parse-util.h" #include "resolved-conf.h" +#include "string-table.h" +#include "string-util.h" + +DEFINE_CONFIG_PARSE_ENUM(config_parse_dns_stub_listener_mode, dns_stub_listener_mode, DnsStubListenerMode, "Failed to parse DNS stub listener mode setting"); + +static const char* const dns_stub_listener_mode_table[_DNS_STUB_LISTENER_MODE_MAX] = { + [DNS_STUB_LISTENER_NO] = "no", + [DNS_STUB_LISTENER_UDP] = "udp", + [DNS_STUB_LISTENER_TCP] = "tcp", + [DNS_STUB_LISTENER_YES] = "yes", +}; +DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(dns_stub_listener_mode, DnsStubListenerMode, DNS_STUB_LISTENER_YES); + +int manager_add_dns_server_by_string(Manager *m, DnsServerType type, const char *word) { + union in_addr_union address; + int family, r, ifindex = 0; + DnsServer *s; + + assert(m); + assert(word); + + r = in_addr_ifindex_from_string_auto(word, &family, &address, &ifindex); + if (r < 0) + return r; + + /* Silently filter out 0.0.0.0 and 127.0.0.53 (our own stub DNS listener) */ + if (!dns_server_address_valid(family, &address)) + return 0; + + /* Filter out duplicates */ + s = dns_server_find(manager_get_first_dns_server(m, type), family, &address, ifindex); + if (s) { + /* + * Drop the marker. This is used to find the servers + * that ceased to exist, see + * manager_mark_dns_servers() and + * manager_flush_marked_dns_servers(). + */ + dns_server_move_back_and_unmark(s); + return 0; + } -int manager_parse_dns_server(Manager *m, DnsServerType type, const char *string) { - const char *word, *state; - size_t length; - DnsServer *first; + return dns_server_new(m, NULL, type, NULL, family, &address, ifindex); +} + +int manager_parse_dns_server_string_and_warn(Manager *m, DnsServerType type, const char *string) { int r; assert(m); assert(string); - first = type == DNS_SERVER_FALLBACK ? m->fallback_dns_servers : m->dns_servers; + for (;;) { + _cleanup_free_ char *word = NULL; - FOREACH_WORD_QUOTED(word, length, string, state) { - char buffer[length+1]; - int family; - union in_addr_union addr; - bool found = false; - DnsServer *s; + r = extract_first_word(&string, &word, NULL, 0); + if (r < 0) + return r; + if (r == 0) + break; - memcpy(buffer, word, length); - buffer[length] = 0; + r = manager_add_dns_server_by_string(m, type, word); + if (r < 0) + log_warning_errno(r, "Failed to add DNS server address '%s', ignoring: %m", word); + } - r = in_addr_from_string_auto(buffer, &family, &addr); - if (r < 0) { - log_warning("Ignoring invalid DNS address '%s'", buffer); - continue; - } + return 0; +} + +int manager_add_search_domain_by_string(Manager *m, const char *domain) { + DnsSearchDomain *d; + bool route_only; + int r; + + assert(m); + assert(domain); - /* Filter out duplicates */ - LIST_FOREACH(servers, s, first) - if (s->family == family && in_addr_equal(family, &s->address, &addr)) { - found = true; - break; - } + route_only = *domain == '~'; + if (route_only) + domain++; - if (found) - continue; + if (dns_name_is_root(domain) || streq(domain, "*")) { + route_only = true; + domain = "."; + } - r = dns_server_new(m, NULL, type, NULL, family, &addr); + 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); + else { + r = dns_search_domain_new(m, &d, DNS_SEARCH_DOMAIN_SYSTEM, NULL, domain); if (r < 0) return r; } + d->route_only = route_only; return 0; } -int config_parse_dnsv( +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: %m", word); + } + + return 0; +} + +int config_parse_dns_servers( const char *unit, const char *filename, unsigned line, @@ -90,12 +168,12 @@ int config_parse_dnsv( if (isempty(rvalue)) /* Empty assignment means clear the list */ - manager_flush_dns_servers(m, ltype); + dns_server_unlink_all(manager_get_first_dns_server(m, ltype)); else { - /* Otherwise add to the list */ - r = manager_parse_dns_server(m, ltype, rvalue); + /* Otherwise, add to the list */ + r = manager_parse_dns_server_string_and_warn(m, ltype, rvalue); if (r < 0) { - log_syntax(unit, LOG_ERR, filename, line, -r, "Failed to parse DNS server string '%s'. Ignoring.", rvalue); + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse DNS server string '%s'. Ignoring.", rvalue); return 0; } } @@ -104,11 +182,13 @@ int config_parse_dnsv( * /etc/resolv.conf */ if (ltype == DNS_SERVER_SYSTEM) m->read_resolv_conf = false; + if (ltype == DNS_SERVER_FALLBACK) + m->need_builtin_fallbacks = false; return 0; } -int config_parse_support( +int config_parse_search_domains( const char *unit, const char *filename, unsigned line, @@ -120,34 +200,52 @@ int config_parse_support( void *data, void *userdata) { - Support support, *v = data; + Manager *m = userdata; int r; assert(filename); assert(lvalue); assert(rvalue); + assert(m); - support = support_from_string(rvalue); - if (support < 0) { - r = parse_boolean(rvalue); + 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 support level '%s'. Ignoring.", rvalue); + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse search domains string '%s'. Ignoring.", rvalue); return 0; } - - support = r ? SUPPORT_YES : SUPPORT_NO; } - *v = support; + /* If we have a manual setting, then we stop reading + * /etc/resolv.conf */ + m->read_resolv_conf = false; + return 0; } int manager_parse_config_file(Manager *m) { + int r; + assert(m); - return config_parse_many("/etc/systemd/resolved.conf", - CONF_DIRS_NULSTR("systemd/resolved.conf"), - "Resolve\0", - config_item_perf_lookup, resolved_gperf_lookup, - false, m); + r = config_parse_many_nulstr(PKGSYSCONFDIR "/resolved.conf", + CONF_PATHS_NULSTR("systemd/resolved.conf.d"), + "Resolve\0", + config_item_perf_lookup, resolved_gperf_lookup, + false, m); + if (r < 0) + return r; + + if (m->need_builtin_fallbacks) { + r = manager_parse_dns_server_string_and_warn(m, DNS_SERVER_FALLBACK, DNS_SERVERS); + if (r < 0) + return r; + } + + return 0; + } |