resolved-resolv-conf.c revision 9176a57c101d51b4a7fb4141240b5ce03abac57d
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen/***
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen This file is part of systemd.
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen Copyright 2014 Tom Gundersen <teg@jklm.no>
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen systemd is free software; you can redistribute it and/or modify it
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen under the terms of the GNU Lesser General Public License as published by
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen the Free Software Foundation; either version 2.1 of the License, or
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen (at your option) any later version.
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen systemd is distributed in the hope that it will be useful, but
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen WITHOUT ANY WARRANTY; without even the implied warranty of
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen Lesser General Public License for more details.
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen You should have received a copy of the GNU Lesser General Public License
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen along with systemd; If not, see <http://www.gnu.org/licenses/>.
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen ***/
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen#include <resolv.h>
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen#include "alloc-util.h"
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen#include "dns-domain.h"
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen#include "fd-util.h"
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen#include "fileio-label.h"
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen#include "fileio.h"
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen#include "ordered-set.h"
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen#include "resolved-conf.h"
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen#include "resolved-resolv-conf.h"
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen#include "string-util.h"
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen#include "strv.h"
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersenint manager_read_resolv_conf(Manager *m) {
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen _cleanup_fclose_ FILE *f = NULL;
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen struct stat st, own;
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen char line[LINE_MAX];
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen usec_t t;
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen int r;
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen assert(m);
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen /* Reads the system /etc/resolv.conf, if it exists and is not
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen * symlinked to our own resolv.conf instance */
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen if (!m->read_resolv_conf)
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen return 0;
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen r = stat("/etc/resolv.conf", &st);
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen if (r < 0) {
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen if (errno == ENOENT)
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen r = 0;
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen else
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen r = log_warning_errno(errno, "Failed to stat /etc/resolv.conf: %m");
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen goto clear;
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen }
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen /* Have we already seen the file? */
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen t = timespec_load(&st.st_mtim);
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen if (t == m->resolv_conf_mtime)
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen return 0;
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen m->resolv_conf_mtime = t;
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen /* Is it symlinked to our own file? */
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen if (stat("/run/systemd/resolve/resolv.conf", &own) >= 0 &&
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen st.st_dev == own.st_dev &&
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen st.st_ino == own.st_ino) {
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen r = 0;
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen goto clear;
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen }
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen f = fopen("/etc/resolv.conf", "re");
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen if (!f) {
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen if (errno == ENOENT)
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen r = 0;
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen else
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen r = log_warning_errno(errno, "Failed to open /etc/resolv.conf: %m");
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen goto clear;
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen }
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen if (fstat(fileno(f), &st) < 0) {
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen r = log_error_errno(errno, "Failed to stat open file: %m");
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen goto clear;
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen }
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen dns_server_mark_all(m->dns_servers);
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen dns_search_domain_mark_all(m->search_domains);
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen FOREACH_LINE(line, f, r = -errno; goto clear) {
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen const char *a;
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen char *l;
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen l = strstrip(line);
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen if (*l == '#' || *l == ';')
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen continue;
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen a = first_word(l, "nameserver");
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen if (a) {
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen r = manager_add_dns_server_by_string(m, DNS_SERVER_SYSTEM, a);
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen if (r < 0)
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen log_warning_errno(r, "Failed to parse DNS server address '%s', ignoring.", a);
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen continue;
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen }
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen a = first_word(l, "domain");
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen if (!a) /* We treat "domain" lines, and "search" lines as equivalent, and add both to our list. */
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen a = first_word(l, "search");
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen if (a) {
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen r = manager_parse_search_domains_and_warn(m, a);
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen if (r < 0)
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen log_warning_errno(r, "Failed to parse search domain string '%s', ignoring.", a);
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen }
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen }
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen /* Flush out all servers and search domains that are still
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen * marked. Those are then ones that didn't appear in the new
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen * /etc/resolv.conf */
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen dns_server_unlink_marked(m->dns_servers);
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen dns_search_domain_unlink_marked(m->search_domains);
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen /* Whenever /etc/resolv.conf changes, start using the first
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen * DNS server of it. This is useful to deal with broken
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen * network managing implementations (like NetworkManager),
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen * that when connecting to a VPN place both the VPN DNS
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen * servers and the local ones in /etc/resolv.conf. Without
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen * resetting the DNS server to use back to the first entry we
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen * will continue to use the local one thus being unable to
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen * resolve VPN domains. */
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen manager_set_dns_server(m, m->dns_servers);
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen return 0;
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersenclear:
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen dns_server_unlink_all(m->dns_servers);
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen dns_search_domain_unlink_all(m->search_domains);
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen return r;
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen}
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersenstatic void write_resolv_conf_server(DnsServer *s, FILE *f, unsigned *count) {
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen _cleanup_free_ char *t = NULL;
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen int r;
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen assert(s);
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen assert(f);
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen assert(count);
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen r = in_addr_to_string(s->family, &s->address, &t);
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen if (r < 0) {
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen log_warning_errno(r, "Invalid DNS address. Ignoring: %m");
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen return;
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen }
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen if (*count == MAXNS)
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen fputs("# Too many DNS servers configured, the following entries may be ignored.\n", f);
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen (*count) ++;
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen fprintf(f, "nameserver %s\n", t);
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen}
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersenstatic void write_resolv_conf_search(
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen const char *domain,
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen FILE *f,
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen unsigned *count,
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen unsigned *length) {
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen assert(domain);
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen assert(f);
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen assert(length);
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen if (*count >= MAXDNSRCH ||
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen *length + strlen(domain) > 256) {
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen if (*count == MAXDNSRCH)
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen fputs(" # Too many search domains configured, remaining ones ignored.", f);
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen if (*length <= 256)
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen fputs(" # Total length of all search domains is too long, remaining ones ignored.", f);
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen return;
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen }
2237aa02f3e2739a1ebe9c0bc224b5125f5eb292David Herrmann
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen (*length) += strlen(domain);
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen (*count) ++;
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen fputc(' ', f);
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen fputs(domain, f);
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen}
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersenstatic int write_resolv_conf_contents(FILE *f, OrderedSet *dns, OrderedSet *domains) {
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen Iterator i;
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen fputs("# This file is managed by systemd-resolved(8). Do not edit.\n#\n"
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen "# Third party programs must not access this file directly, but\n"
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen "# only through the symlink at /etc/resolv.conf. To manage\n"
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen "# resolv.conf(5) in a different way, replace the symlink by a\n"
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen "# static file or a different symlink.\n\n", f);
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen if (ordered_set_isempty(dns))
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen fputs("# No DNS servers known.\n", f);
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen else {
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen unsigned count = 0;
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen DnsServer *s;
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen ORDERED_SET_FOREACH(s, dns, i)
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen write_resolv_conf_server(s, f, &count);
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen }
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen if (!ordered_set_isempty(domains)) {
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen unsigned length = 0, count = 0;
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen char *domain;
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen fputs("search", f);
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen ORDERED_SET_FOREACH(domain, domains, i)
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen write_resolv_conf_search(domain, f, &count, &length);
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen fputs("\n", f);
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen }
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen return fflush_and_check(f);
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen}
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersenint manager_write_resolv_conf(Manager *m) {
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen #define PRIVATE_RESOLV_CONF "/run/systemd/resolve/resolv.conf"
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen _cleanup_ordered_set_free_ OrderedSet *dns = NULL, *domains = NULL;
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen _cleanup_free_ char *temp_path = NULL;
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen _cleanup_fclose_ FILE *f = NULL;
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen int r;
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen assert(m);
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen /* Read the system /etc/resolv.conf first */
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen manager_read_resolv_conf(m);
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen /* Add the full list to a set, to filter out duplicates */
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen r = manager_compile_dns_servers(m, &dns);
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen if (r < 0)
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen return r;
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen r = manager_compile_search_domains(m, &domains);
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen if (r < 0)
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen return r;
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen r = fopen_temporary_label(PRIVATE_RESOLV_CONF, PRIVATE_RESOLV_CONF, &f, &temp_path);
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen if (r < 0)
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen return r;
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen fchmod(fileno(f), 0644);
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen r = write_resolv_conf_contents(f, dns, domains);
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen if (r < 0)
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen goto fail;
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen if (rename(temp_path, PRIVATE_RESOLV_CONF) < 0) {
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen r = -errno;
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen goto fail;
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen }
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen return 0;
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersenfail:
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen (void) unlink(PRIVATE_RESOLV_CONF);
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen (void) unlink(temp_path);
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen return r;
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen}
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen