f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering This file is part of systemd.
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering Copyright 2014 Tom Gundersen <teg@jklm.no>
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering systemd is free software; you can redistribute it and/or modify it
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering under the terms of the GNU Lesser General Public License as published by
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering (at your option) any later version.
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering systemd is distributed in the hope that it will be useful, but
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering Lesser General Public License for more details.
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering You should have received a copy of the GNU Lesser General Public License
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
f8dc7e343d903f053070d01f3273db819deee951Lennart Poetteringint manager_read_resolv_conf(Manager *m) {
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering /* Reads the system /etc/resolv.conf, if it exists and is not
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering * symlinked to our own resolv.conf instance */
bf7fabd6000fd95495904ed55db62caf361b3d8fLennart Poettering r = log_warning_errno(errno, "Failed to stat /etc/resolv.conf: %m");
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering /* Have we already seen the file? */
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering /* Is it symlinked to our own file? */
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering if (stat("/run/systemd/resolve/resolv.conf", &own) >= 0 &&
bf7fabd6000fd95495904ed55db62caf361b3d8fLennart Poettering r = log_warning_errno(errno, "Failed to open /etc/resolv.conf: %m");
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering r = log_error_errno(errno, "Failed to stat open file: %m");
a51c10485af349eb15faa4d1a63b9818bcf3e589Lennart Poettering dns_search_domain_mark_all(m->search_domains);
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering FOREACH_LINE(line, f, r = -errno; goto clear) {
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering const char *a;
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering r = manager_add_dns_server_by_string(m, DNS_SERVER_SYSTEM, a);
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering log_warning_errno(r, "Failed to parse DNS server address '%s', ignoring.", a);
a51c10485af349eb15faa4d1a63b9818bcf3e589Lennart Poettering if (!a) /* We treat "domain" lines, and "search" lines as equivalent, and add both to our list. */
a51c10485af349eb15faa4d1a63b9818bcf3e589Lennart Poettering r = manager_parse_search_domains_and_warn(m, a);
a51c10485af349eb15faa4d1a63b9818bcf3e589Lennart Poettering log_warning_errno(r, "Failed to parse search domain string '%s', ignoring.", a);
a51c10485af349eb15faa4d1a63b9818bcf3e589Lennart Poettering /* Flush out all servers and search domains that are still
a51c10485af349eb15faa4d1a63b9818bcf3e589Lennart Poettering * marked. Those are then ones that didn't appear in the new
4b95f1798f22c1bb75295f448188560cb6ec9eceLennart Poettering dns_server_unlink_marked(m->dns_servers);
a51c10485af349eb15faa4d1a63b9818bcf3e589Lennart Poettering dns_search_domain_unlink_marked(m->search_domains);
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering /* Whenever /etc/resolv.conf changes, start using the first
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering * DNS server of it. This is useful to deal with broken
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering * network managing implementations (like NetworkManager),
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering * that when connecting to a VPN place both the VPN DNS
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering * servers and the local ones in /etc/resolv.conf. Without
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering * resetting the DNS server to use back to the first entry we
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering * will continue to use the local one thus being unable to
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering * resolve VPN domains. */
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering manager_set_dns_server(m, m->dns_servers);
452b4e327d23b9e468d3198f4c91e8efd0b52a71Lennart Poettering /* Unconditionally flush the cache when /etc/resolv.conf is
452b4e327d23b9e468d3198f4c91e8efd0b52a71Lennart Poettering * modified, even if the data it contained was completely
452b4e327d23b9e468d3198f4c91e8efd0b52a71Lennart Poettering * identical to the previous version we used. We do this
452b4e327d23b9e468d3198f4c91e8efd0b52a71Lennart Poettering * because altering /etc/resolv.conf is typically done when
452b4e327d23b9e468d3198f4c91e8efd0b52a71Lennart Poettering * the network configuration changes, and that should be
452b4e327d23b9e468d3198f4c91e8efd0b52a71Lennart Poettering * enough to flush the global unicast DNS cache. */
452b4e327d23b9e468d3198f4c91e8efd0b52a71Lennart Poettering dns_cache_flush(&m->unicast_scope->cache);
a51c10485af349eb15faa4d1a63b9818bcf3e589Lennart Poettering dns_search_domain_unlink_all(m->search_domains);
f8dc7e343d903f053070d01f3273db819deee951Lennart Poetteringstatic void write_resolv_conf_server(DnsServer *s, FILE *f, unsigned *count) {
6cb08a8930bdaca950b152b1e8b82466ed59511cLennart Poettering log_warning("Our of memory, or invalid DNS address. Ignoring server.");
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering fputs("# Too many DNS servers configured, the following entries may be ignored.\n", f);
6cb08a8930bdaca950b152b1e8b82466ed59511cLennart Poettering fprintf(f, "nameserver %s\n", s->server_string);
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering fputs(" # Too many search domains configured, remaining ones ignored.", f);
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering fputs(" # Total length of all search domains is too long, remaining ones ignored.", f);
f8dc7e343d903f053070d01f3273db819deee951Lennart Poetteringstatic int write_resolv_conf_contents(FILE *f, OrderedSet *dns, OrderedSet *domains) {
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering fputs("# This file is managed by systemd-resolved(8). Do not edit.\n#\n"
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering "# Third party programs must not access this file directly, but\n"
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering "# only through the symlink at /etc/resolv.conf. To manage\n"
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering "# resolv.conf(5) in a different way, replace the symlink by a\n"
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering "# static file or a different symlink.\n\n", f);
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering write_resolv_conf_search(domain, f, &count, &length);
f8dc7e343d903f053070d01f3273db819deee951Lennart Poetteringint manager_write_resolv_conf(Manager *m) {
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering _cleanup_ordered_set_free_ OrderedSet *dns = NULL, *domains = NULL;
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering /* Read the system /etc/resolv.conf first */
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering /* Add the full list to a set, to filter out duplicates */
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering r = manager_compile_dns_servers(m, &dns);
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering r = manager_compile_search_domains(m, &domains);
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering r = fopen_temporary_label(PRIVATE_RESOLV_CONF, PRIVATE_RESOLV_CONF, &f, &temp_path);
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering r = write_resolv_conf_contents(f, dns, domains);