Beispiel #1
0
DnsServer *manager_set_dns_server(Manager *m, DnsServer *s) {
        assert(m);

        if (m->current_dns_server == s)
                return s;

        if (s)
                log_debug("Switching to %s DNS server %s.",
                          dns_server_type_to_string(s->type),
                          dns_server_string(s));

        dns_server_unref(m->current_dns_server);
        m->current_dns_server = dns_server_ref(s);

        if (m->unicast_scope)
                dns_cache_flush(&m->unicast_scope->cache);

        return s;
}
Beispiel #2
0
void link_set_dnssec_mode(Link *l, DnssecMode mode) {

        assert(l);

        if (l->dnssec_mode == mode)
                return;

        if ((l->dnssec_mode == _DNSSEC_MODE_INVALID) ||
            (l->dnssec_mode == DNSSEC_NO && mode != DNSSEC_NO) ||
            (l->dnssec_mode == DNSSEC_ALLOW_DOWNGRADE && mode == DNSSEC_YES)) {

                /* When switching from non-DNSSEC mode to DNSSEC mode, flush the cache. Also when switching from the
                 * allow-downgrade mode to full DNSSEC mode, flush it too. */
                if (l->unicast_scope)
                        dns_cache_flush(&l->unicast_scope->cache);
        }

        l->dnssec_mode = mode;
}
Beispiel #3
0
DnsServer *manager_set_dns_server(Manager *m, DnsServer *s) {
        assert(m);

        if (m->current_dns_server == s)
                return s;

        if (s) {
                _cleanup_free_ char *ip = NULL;

                in_addr_to_string(s->family, &s->address, &ip);
                log_info("Switching to system DNS server %s.", strna(ip));
        }

        dns_server_unref(m->current_dns_server);
        m->current_dns_server = dns_server_ref(s);

        if (m->unicast_scope)
                dns_cache_flush(&m->unicast_scope->cache);

        return s;
}
Beispiel #4
0
int manager_read_resolv_conf(Manager *m) {
        _cleanup_fclose_ FILE *f = NULL;
        struct stat st, own;
        char line[LINE_MAX];
        usec_t t;
        int r;

        assert(m);

        /* Reads the system /etc/resolv.conf, if it exists and is not
         * symlinked to our own resolv.conf instance */

        if (!m->read_resolv_conf)
                return 0;

        r = stat("/etc/resolv.conf", &st);
        if (r < 0) {
                if (errno == ENOENT)
                        return 0;

                r = log_warning_errno(errno, "Failed to stat /etc/resolv.conf: %m");
                goto clear;
        }

        /* Have we already seen the file? */
        t = timespec_load(&st.st_mtim);
        if (t == m->resolv_conf_mtime)
                return 0;

        /* Is it symlinked to our own file? */
        if (stat(PRIVATE_RESOLV_CONF, &own) >= 0 &&
            st.st_dev == own.st_dev &&
            st.st_ino == own.st_ino)
                return 0;

        f = fopen("/etc/resolv.conf", "re");
        if (!f) {
                if (errno == ENOENT)
                        return 0;

                r = log_warning_errno(errno, "Failed to open /etc/resolv.conf: %m");
                goto clear;
        }

        if (fstat(fileno(f), &st) < 0) {
                r = log_error_errno(errno, "Failed to stat open file: %m");
                goto clear;
        }

        dns_server_mark_all(m->dns_servers);
        dns_search_domain_mark_all(m->search_domains);

        FOREACH_LINE(line, f, r = -errno; goto clear) {
                const char *a;
                char *l;

                l = strstrip(line);
                if (IN_SET(*l, '#', ';'))
                        continue;

                a = first_word(l, "nameserver");
                if (a) {
                        r = manager_parse_dns_server_string_and_warn(m, DNS_SERVER_SYSTEM, a);
                        if (r < 0)
                                log_warning_errno(r, "Failed to parse DNS server address '%s', ignoring.", a);

                        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);
                }
        }

        m->resolv_conf_mtime = t;

        /* 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 */
        dns_server_unlink_marked(m->dns_servers);
        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
         * network managing implementations (like NetworkManager),
         * that when connecting to a VPN place both the VPN DNS
         * servers and the local ones in /etc/resolv.conf. Without
         * resetting the DNS server to use back to the first entry we
         * will continue to use the local one thus being unable to
         * resolve VPN domains. */
        manager_set_dns_server(m, m->dns_servers);

        /* Unconditionally flush the cache when /etc/resolv.conf is
         * modified, even if the data it contained was completely
         * identical to the previous version we used. We do this
         * because altering /etc/resolv.conf is typically done when
         * the network configuration changes, and that should be
         * enough to flush the global unicast DNS cache. */
        if (m->unicast_scope)
                dns_cache_flush(&m->unicast_scope->cache);

        /* If /etc/resolv.conf changed, make sure to forget everything we learned about the DNS servers. After all we
         * might now talk to a very different DNS server that just happens to have the same IP address as an old one
         * (think 192.168.1.1). */
        dns_server_reset_features_all(m->dns_servers);

        return 0;

clear:
        dns_server_unlink_all(m->dns_servers);
        dns_search_domain_unlink_all(m->search_domains);
        return r;
}