resolved-dns-server.c revision 519ef04651b07a547f010d6462603669d7fde4e5
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen/***
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen This file is part of systemd.
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen Copyright 2014 Lennart Poettering
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen systemd is free software; you can redistribute it and/or modify it
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen under the terms of the GNU Lesser General Public License as published by
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen the Free Software Foundation; either version 2.1 of the License, or
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen (at your option) any later version.
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen systemd is distributed in the hope that it will be useful, but
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen WITHOUT ANY WARRANTY; without even the implied warranty of
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen Lesser General Public License for more details.
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen You should have received a copy of the GNU Lesser General Public License
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen along with systemd; If not, see <http://www.gnu.org/licenses/>.
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen***/
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen#include "alloc-util.h"
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen#include "resolved-dns-server.h"
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen#include "resolved-resolv-conf.h"
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen#include "siphash24.h"
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen#include "string-table.h"
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen#include "string-util.h"
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen/* After how much time to repeat classic DNS requests */
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen#define DNS_TIMEOUT_MIN_USEC (500 * USEC_PER_MSEC)
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen#define DNS_TIMEOUT_MAX_USEC (5 * USEC_PER_SEC)
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen/* The amount of time to wait before retrying with a full feature set */
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen#define DNS_SERVER_FEATURE_GRACE_PERIOD_MAX_USEC (6 * USEC_PER_HOUR)
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen#define DNS_SERVER_FEATURE_GRACE_PERIOD_MIN_USEC (5 * USEC_PER_MINUTE)
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen
b95cc756de7a27f7546e42dd9acf6da0669da402Tom Gundersen/* The number of times we will attempt a certain feature set before degrading */
b95cc756de7a27f7546e42dd9acf6da0669da402Tom Gundersen#define DNS_SERVER_FEATURE_RETRY_ATTEMPTS 3
b95cc756de7a27f7546e42dd9acf6da0669da402Tom Gundersen
b95cc756de7a27f7546e42dd9acf6da0669da402Tom Gundersenint dns_server_new(
b95cc756de7a27f7546e42dd9acf6da0669da402Tom Gundersen Manager *m,
b95cc756de7a27f7546e42dd9acf6da0669da402Tom Gundersen DnsServer **ret,
b95cc756de7a27f7546e42dd9acf6da0669da402Tom Gundersen DnsServerType type,
b95cc756de7a27f7546e42dd9acf6da0669da402Tom Gundersen Link *l,
b95cc756de7a27f7546e42dd9acf6da0669da402Tom Gundersen int family,
b95cc756de7a27f7546e42dd9acf6da0669da402Tom Gundersen const union in_addr_union *in_addr) {
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen DnsServer *s;
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen assert(m);
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen assert((type == DNS_SERVER_LINK) == !!l);
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen assert(in_addr);
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen if (!IN_SET(family, AF_INET, AF_INET6))
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen return -EAFNOSUPPORT;
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen if (l) {
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen if (l->n_dns_servers >= LINK_DNS_SERVERS_MAX)
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen return -E2BIG;
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen } else {
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen if (m->n_dns_servers >= MANAGER_DNS_SERVERS_MAX)
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen return -E2BIG;
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen }
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen s = new0(DnsServer, 1);
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen if (!s)
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen return -ENOMEM;
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen s->n_ref = 1;
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen s->manager = m;
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen s->verified_features = _DNS_SERVER_FEATURE_LEVEL_INVALID;
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen s->possible_features = DNS_SERVER_FEATURE_LEVEL_BEST;
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen s->features_grace_period_usec = DNS_SERVER_FEATURE_GRACE_PERIOD_MIN_USEC;
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen s->received_udp_packet_max = DNS_PACKET_UNICAST_SIZE_MAX;
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen s->type = type;
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen s->family = family;
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen s->address = *in_addr;
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen s->resend_timeout = DNS_TIMEOUT_MIN_USEC;
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen switch (type) {
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen case DNS_SERVER_LINK:
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen s->link = l;
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen LIST_APPEND(servers, l->dns_servers, s);
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen l->n_dns_servers++;
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen break;
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen case DNS_SERVER_SYSTEM:
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen LIST_APPEND(servers, m->dns_servers, s);
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen m->n_dns_servers++;
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen break;
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen case DNS_SERVER_FALLBACK:
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen LIST_APPEND(servers, m->fallback_dns_servers, s);
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen m->n_dns_servers++;
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen break;
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen default:
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen assert_not_reached("Unknown server type");
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen }
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen s->linked = true;
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen /* A new DNS server that isn't fallback is added and the one
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen * we used so far was a fallback one? Then let's try to pick
b95cc756de7a27f7546e42dd9acf6da0669da402Tom Gundersen * the new one */
b95cc756de7a27f7546e42dd9acf6da0669da402Tom Gundersen if (type != DNS_SERVER_FALLBACK &&
b95cc756de7a27f7546e42dd9acf6da0669da402Tom Gundersen m->current_dns_server &&
b95cc756de7a27f7546e42dd9acf6da0669da402Tom Gundersen m->current_dns_server->type == DNS_SERVER_FALLBACK)
b95cc756de7a27f7546e42dd9acf6da0669da402Tom Gundersen manager_set_dns_server(m, NULL);
b95cc756de7a27f7546e42dd9acf6da0669da402Tom Gundersen
b95cc756de7a27f7546e42dd9acf6da0669da402Tom Gundersen if (ret)
b95cc756de7a27f7546e42dd9acf6da0669da402Tom Gundersen *ret = s;
b95cc756de7a27f7546e42dd9acf6da0669da402Tom Gundersen
b95cc756de7a27f7546e42dd9acf6da0669da402Tom Gundersen return 0;
b95cc756de7a27f7546e42dd9acf6da0669da402Tom Gundersen}
b95cc756de7a27f7546e42dd9acf6da0669da402Tom Gundersen
b95cc756de7a27f7546e42dd9acf6da0669da402Tom GundersenDnsServer* dns_server_ref(DnsServer *s) {
b95cc756de7a27f7546e42dd9acf6da0669da402Tom Gundersen if (!s)
b95cc756de7a27f7546e42dd9acf6da0669da402Tom Gundersen return NULL;
b95cc756de7a27f7546e42dd9acf6da0669da402Tom Gundersen
b95cc756de7a27f7546e42dd9acf6da0669da402Tom Gundersen assert(s->n_ref > 0);
b95cc756de7a27f7546e42dd9acf6da0669da402Tom Gundersen s->n_ref ++;
b95cc756de7a27f7546e42dd9acf6da0669da402Tom Gundersen
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen return s;
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen}
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom GundersenDnsServer* dns_server_unref(DnsServer *s) {
b95cc756de7a27f7546e42dd9acf6da0669da402Tom Gundersen if (!s)
b95cc756de7a27f7546e42dd9acf6da0669da402Tom Gundersen return NULL;
b95cc756de7a27f7546e42dd9acf6da0669da402Tom Gundersen
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen assert(s->n_ref > 0);
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen s->n_ref --;
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen if (s->n_ref > 0)
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen return NULL;
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen free(s);
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen return NULL;
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen}
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersenvoid dns_server_unlink(DnsServer *s) {
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen assert(s);
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen assert(s->manager);
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen /* This removes the specified server from the linked list of
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen * servers, but any server might still stay around if it has
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen * refs, for example from an ongoing transaction. */
b95cc756de7a27f7546e42dd9acf6da0669da402Tom Gundersen
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen if (!s->linked)
b95cc756de7a27f7546e42dd9acf6da0669da402Tom Gundersen return;
b95cc756de7a27f7546e42dd9acf6da0669da402Tom Gundersen
b95cc756de7a27f7546e42dd9acf6da0669da402Tom Gundersen switch (s->type) {
b95cc756de7a27f7546e42dd9acf6da0669da402Tom Gundersen
b95cc756de7a27f7546e42dd9acf6da0669da402Tom Gundersen case DNS_SERVER_LINK:
b95cc756de7a27f7546e42dd9acf6da0669da402Tom Gundersen assert(s->link);
b95cc756de7a27f7546e42dd9acf6da0669da402Tom Gundersen assert(s->link->n_dns_servers > 0);
b95cc756de7a27f7546e42dd9acf6da0669da402Tom Gundersen LIST_REMOVE(servers, s->link->dns_servers, s);
b95cc756de7a27f7546e42dd9acf6da0669da402Tom Gundersen break;
b95cc756de7a27f7546e42dd9acf6da0669da402Tom Gundersen
b95cc756de7a27f7546e42dd9acf6da0669da402Tom Gundersen case DNS_SERVER_SYSTEM:
b95cc756de7a27f7546e42dd9acf6da0669da402Tom Gundersen assert(s->manager->n_dns_servers > 0);
b95cc756de7a27f7546e42dd9acf6da0669da402Tom Gundersen LIST_REMOVE(servers, s->manager->dns_servers, s);
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen s->manager->n_dns_servers--;
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen break;
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen case DNS_SERVER_FALLBACK:
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen assert(s->manager->n_dns_servers > 0);
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen LIST_REMOVE(servers, s->manager->fallback_dns_servers, s);
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen s->manager->n_dns_servers--;
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen break;
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen }
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen s->linked = false;
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen if (s->link && s->link->current_dns_server == s)
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen link_set_dns_server(s->link, NULL);
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen if (s->manager->current_dns_server == s)
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen manager_set_dns_server(s->manager, NULL);
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen dns_server_unref(s);
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen}
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersenvoid dns_server_move_back_and_unmark(DnsServer *s) {
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen DnsServer *tail;
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen assert(s);
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen if (!s->marked)
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen return;
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen s->marked = false;
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen if (!s->linked || !s->servers_next)
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen return;
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen /* Move us to the end of the list, so that the order is
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen * strictly kept, if we are not at the end anyway. */
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen switch (s->type) {
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen case DNS_SERVER_LINK:
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen assert(s->link);
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen LIST_FIND_TAIL(servers, s, tail);
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen LIST_REMOVE(servers, s->link->dns_servers, s);
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen LIST_INSERT_AFTER(servers, s->link->dns_servers, tail, s);
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen break;
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen case DNS_SERVER_SYSTEM:
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen LIST_FIND_TAIL(servers, s, tail);
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen LIST_REMOVE(servers, s->manager->dns_servers, s);
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen LIST_INSERT_AFTER(servers, s->manager->dns_servers, tail, s);
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen break;
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen case DNS_SERVER_FALLBACK:
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen LIST_FIND_TAIL(servers, s, tail);
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen LIST_REMOVE(servers, s->manager->fallback_dns_servers, s);
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen LIST_INSERT_AFTER(servers, s->manager->fallback_dns_servers, tail, s);
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen break;
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen default:
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen assert_not_reached("Unknown server type");
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen }
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen}
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersenvoid dns_server_packet_received(DnsServer *s, DnsServerFeatureLevel features, usec_t rtt, size_t size) {
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen assert(s);
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen if (features == DNS_SERVER_FEATURE_LEVEL_LARGE) {
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen /* Even if we successfully receive a reply to a
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen request announcing support for large packets, that
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen does not mean we can necessarily receive large
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen packets. */
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen
9c5a882b7fc256ddc0b227677fa06546f0e944a8Tom Gundersen if (s->verified_features < DNS_SERVER_FEATURE_LEVEL_LARGE - 1) {
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen s->verified_features = DNS_SERVER_FEATURE_LEVEL_LARGE - 1;
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen assert_se(sd_event_now(s->manager->event, clock_boottime_or_monotonic(), &s->verified_usec) >= 0);
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen }
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen } else if (s->verified_features < features) {
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen s->verified_features = features;
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen assert_se(sd_event_now(s->manager->event, clock_boottime_or_monotonic(), &s->verified_usec) >= 0);
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen }
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen if (s->possible_features == features)
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen s->n_failed_attempts = 0;
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen /* Remember the size of the largest UDP packet we received from a server,
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen we know that we can always announce support for packets with at least
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen this size. */
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen if (s->received_udp_packet_max < size)
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen s->received_udp_packet_max = size;
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen if (s->max_rtt < rtt) {
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen s->max_rtt = rtt;
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen s->resend_timeout = MIN(MAX(DNS_TIMEOUT_MIN_USEC, s->max_rtt * 2), DNS_TIMEOUT_MAX_USEC);
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen }
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen}
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersenvoid dns_server_packet_lost(DnsServer *s, DnsServerFeatureLevel features, usec_t usec) {
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen assert(s);
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen assert(s->manager);
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen if (s->possible_features == features)
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen s->n_failed_attempts ++;
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen if (s->resend_timeout > usec)
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen return;
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen s->resend_timeout = MIN(s->resend_timeout * 2, DNS_TIMEOUT_MAX_USEC);
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen}
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersenvoid dns_server_packet_failed(DnsServer *s, DnsServerFeatureLevel features) {
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen assert(s);
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen assert(s->manager);
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen if (s->possible_features != features)
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen return;
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen s->n_failed_attempts = (unsigned) -1;
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen}
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersenvoid dns_server_packet_rrsig_missing(DnsServer *s) {
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen _cleanup_free_ char *ip = NULL;
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen assert(s);
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen assert(s->manager);
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen in_addr_to_string(s->family, &s->address, &ip);
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen log_warning("DNS server %s does not augment replies with RRSIG records, DNSSEC not available.", strna(ip));
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen s->rrsig_missing = true;
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen}
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersenstatic bool dns_server_grace_period_expired(DnsServer *s) {
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen usec_t ts;
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen assert(s);
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen assert(s->manager);
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen if (s->verified_usec == 0)
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen return false;
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen assert_se(sd_event_now(s->manager->event, clock_boottime_or_monotonic(), &ts) >= 0);
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen if (s->verified_usec + s->features_grace_period_usec > ts)
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen return false;
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen s->features_grace_period_usec = MIN(s->features_grace_period_usec * 2, DNS_SERVER_FEATURE_GRACE_PERIOD_MAX_USEC);
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen return true;
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen}
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen
89489ef7d451d61e176764deb608a84e29b1fd38Tom GundersenDnsServerFeatureLevel dns_server_possible_features(DnsServer *s) {
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen assert(s);
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen if (s->possible_features != DNS_SERVER_FEATURE_LEVEL_BEST &&
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen dns_server_grace_period_expired(s)) {
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen _cleanup_free_ char *ip = NULL;
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen s->possible_features = DNS_SERVER_FEATURE_LEVEL_BEST;
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen s->n_failed_attempts = 0;
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen s->verified_usec = 0;
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen s->rrsig_missing = false;
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen in_addr_to_string(s->family, &s->address, &ip);
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen log_info("Grace period over, resuming full feature set for DNS server %s", strna(ip));
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen } else if (s->possible_features <= s->verified_features)
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen s->possible_features = s->verified_features;
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen else if (s->n_failed_attempts >= DNS_SERVER_FEATURE_RETRY_ATTEMPTS &&
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen s->possible_features > DNS_SERVER_FEATURE_LEVEL_WORST) {
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen _cleanup_free_ char *ip = NULL;
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen s->possible_features --;
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen s->n_failed_attempts = 0;
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen s->verified_usec = 0;
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen in_addr_to_string(s->family, &s->address, &ip);
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen log_warning("Using degraded feature set (%s) for DNS server %s",
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen dns_server_feature_level_to_string(s->possible_features), strna(ip));
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen }
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen return s->possible_features;
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen}
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersenint dns_server_adjust_opt(DnsServer *server, DnsPacket *packet, DnsServerFeatureLevel level) {
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen size_t packet_size;
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen bool edns_do;
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen int r;
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen assert(server);
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen assert(packet);
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen assert(packet->protocol == DNS_PROTOCOL_DNS);
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen /* Fix the OPT field in the packet to match our current feature level. */
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen r = dns_packet_truncate_opt(packet);
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen if (r < 0)
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen return r;
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen if (level < DNS_SERVER_FEATURE_LEVEL_EDNS0)
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen return 0;
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen edns_do = level >= DNS_SERVER_FEATURE_LEVEL_DO;
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen if (level >= DNS_SERVER_FEATURE_LEVEL_LARGE)
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen packet_size = DNS_PACKET_UNICAST_SIZE_LARGE_MAX;
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen else
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen packet_size = server->received_udp_packet_max;
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen return dns_packet_append_opt(packet, packet_size, edns_do, NULL);
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen}
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersenstatic void dns_server_hash_func(const void *p, struct siphash *state) {
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen const DnsServer *s = p;
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen assert(s);
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen siphash24_compress(&s->family, sizeof(s->family), state);
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen siphash24_compress(&s->address, FAMILY_ADDRESS_SIZE(s->family), state);
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen}
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersenstatic int dns_server_compare_func(const void *a, const void *b) {
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen const DnsServer *x = a, *y = b;
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen if (x->family < y->family)
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen return -1;
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen if (x->family > y->family)
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen return 1;
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen return memcmp(&x->address, &y->address, FAMILY_ADDRESS_SIZE(x->family));
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen}
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersenconst struct hash_ops dns_server_hash_ops = {
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen .hash = dns_server_hash_func,
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen .compare = dns_server_compare_func
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen};
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersenvoid dns_server_unlink_all(DnsServer *first) {
846a6b3d89aaf4ee2cece0f10148f675c4796841David Herrmann DnsServer *next;
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen if (!first)
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen return;
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen next = first->servers_next;
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen dns_server_unlink(first);
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen dns_server_unlink_all(next);
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen}
817d1cd824bedba8feeef24c9724ec8bd160a7b2David Herrmann
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersenvoid dns_server_unlink_marked(DnsServer *first) {
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen DnsServer *next;
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen if (!first)
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen return;
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen next = first->servers_next;
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen if (first->marked)
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen dns_server_unlink(first);
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen dns_server_unlink_marked(next);
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen}
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersenvoid dns_server_mark_all(DnsServer *first) {
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen if (!first)
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen return;
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen first->marked = true;
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen dns_server_mark_all(first->servers_next);
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen}
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen
89489ef7d451d61e176764deb608a84e29b1fd38Tom GundersenDnsServer *dns_server_find(DnsServer *first, int family, const union in_addr_union *in_addr) {
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen DnsServer *s;
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen LIST_FOREACH(servers, s, first)
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen if (s->family == family && in_addr_equal(family, &s->address, in_addr) > 0)
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen return s;
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen return NULL;
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen}
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen
89489ef7d451d61e176764deb608a84e29b1fd38Tom GundersenDnsServer *manager_get_first_dns_server(Manager *m, DnsServerType t) {
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen assert(m);
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen switch (t) {
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen case DNS_SERVER_SYSTEM:
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen return m->dns_servers;
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen case DNS_SERVER_FALLBACK:
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen return m->fallback_dns_servers;
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen default:
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen return NULL;
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen }
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen}
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen
89489ef7d451d61e176764deb608a84e29b1fd38Tom GundersenDnsServer *manager_set_dns_server(Manager *m, DnsServer *s) {
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen assert(m);
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen if (m->current_dns_server == s)
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen return s;
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen if (s) {
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen _cleanup_free_ char *ip = NULL;
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen in_addr_to_string(s->family, &s->address, &ip);
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen log_info("Switching to system DNS server %s.", strna(ip));
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen }
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen dns_server_unref(m->current_dns_server);
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen m->current_dns_server = dns_server_ref(s);
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen if (m->unicast_scope)
89489ef7d451d61e176764deb608a84e29b1fd38Tom Gundersen dns_cache_flush(&m->unicast_scope->cache);
return s;
}
DnsServer *manager_get_dns_server(Manager *m) {
Link *l;
assert(m);
/* Try to read updates resolv.conf */
manager_read_resolv_conf(m);
/* If no DNS server was chose so far, pick the first one */
if (!m->current_dns_server)
manager_set_dns_server(m, m->dns_servers);
if (!m->current_dns_server) {
bool found = false;
Iterator i;
/* No DNS servers configured, let's see if there are
* any on any links. If not, we use the fallback
* servers */
HASHMAP_FOREACH(l, m->links, i)
if (l->dns_servers) {
found = true;
break;
}
if (!found)
manager_set_dns_server(m, m->fallback_dns_servers);
}
return m->current_dns_server;
}
void manager_next_dns_server(Manager *m) {
assert(m);
/* If there's currently no DNS server set, then the next
* manager_get_dns_server() will find one */
if (!m->current_dns_server)
return;
/* Change to the next one, but make sure to follow the linked
* list only if the server is still linked. */
if (m->current_dns_server->linked && m->current_dns_server->servers_next) {
manager_set_dns_server(m, m->current_dns_server->servers_next);
return;
}
/* If there was no next one, then start from the beginning of
* the list */
if (m->current_dns_server->type == DNS_SERVER_FALLBACK)
manager_set_dns_server(m, m->fallback_dns_servers);
else
manager_set_dns_server(m, m->dns_servers);
}
static const char* const dns_server_feature_level_table[_DNS_SERVER_FEATURE_LEVEL_MAX] = {
[DNS_SERVER_FEATURE_LEVEL_TCP] = "TCP",
[DNS_SERVER_FEATURE_LEVEL_UDP] = "UDP",
[DNS_SERVER_FEATURE_LEVEL_EDNS0] = "UDP+EDNS0",
[DNS_SERVER_FEATURE_LEVEL_DO] = "UDP+EDNS0+DO",
[DNS_SERVER_FEATURE_LEVEL_LARGE] = "UDP+EDNS0+DO+LARGE",
};
DEFINE_STRING_TABLE_LOOKUP(dns_server_feature_level, DnsServerFeatureLevel);