diff options
Diffstat (limited to 'src/resolve/resolved-conf.c')
-rw-r--r-- | src/resolve/resolved-conf.c | 165 |
1 files changed, 118 insertions, 47 deletions
diff --git a/src/resolve/resolved-conf.c b/src/resolve/resolved-conf.c index 7af63b0a82..88df7534c4 100644 --- a/src/resolve/resolved-conf.c +++ b/src/resolve/resolved-conf.c @@ -19,56 +19,107 @@ 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-util.h" + +int manager_add_dns_server_by_string(Manager *m, DnsServerType type, const char *word) { + union in_addr_union address; + int family, r; + DnsServer *s; + + assert(m); + assert(word); + + r = in_addr_from_string_auto(word, &family, &address); + if (r < 0) + return r; + + /* Filter out duplicates */ + s = dns_server_find(manager_get_first_dns_server(m, type), family, &address); + 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; + } + + return dns_server_new(m, NULL, type, NULL, family, &address); +} -int manager_parse_dns_server(Manager *m, DnsServerType type, const char *string) { - const char *word, *state; - size_t length; - DnsServer *first; +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.", 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; + 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; - /* Filter out duplicates */ - LIST_FOREACH(servers, s, first) - if (s->family == family && in_addr_equal(family, &s->address, &addr)) { - found = true; - break; - } + assert(m); + assert(string); - if (found) - continue; + for(;;) { + _cleanup_free_ char *word = NULL; - r = dns_server_new(m, NULL, type, NULL, family, &addr); + 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; } -int config_parse_dnsv( +int config_parse_dns_servers( const char *unit, const char *filename, unsigned line, @@ -90,12 +141,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 +155,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 +173,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(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; + } |