resolved-dns-server.c revision f2f1dbe50fea13abadc9c1e845a29031b90b40f3
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering/***
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering This file is part of systemd.
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering Copyright 2014 Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering systemd is free software; you can redistribute it and/or modify it
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering under the terms of the GNU Lesser General Public License as published by
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering (at your option) any later version.
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering systemd is distributed in the hope that it will be useful, but
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering Lesser General Public License for more details.
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering You should have received a copy of the GNU Lesser General Public License
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering***/
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
8bdbb8d9cbe1d35708385573d70984ab4533812dLennart Poettering#include "alloc-util.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "resolved-dns-server.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "resolved-resolv-conf.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "siphash24.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "string-util.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering/* After how much time to repeat classic DNS requests */
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering#define DNS_TIMEOUT_MIN_USEC (500 * USEC_PER_MSEC)
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering#define DNS_TIMEOUT_MAX_USEC (5 * USEC_PER_SEC)
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poetteringint dns_server_new(
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering Manager *m,
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen DnsServer **ret,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering DnsServerType type,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering Link *l,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering int family,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering const union in_addr_union *in_addr) {
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen DnsServer *s, *tail;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert(m);
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering assert((type == DNS_SERVER_LINK) == !!l);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert(in_addr);
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering s = new0(DnsServer, 1);
023fb90b83871a15ef7f57e8cd126e3426f99b9eLennart Poettering if (!s)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return -ENOMEM;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering s->n_ref = 1;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering s->type = type;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering s->family = family;
e56056e93d33619a3acf13e483900b4f8938228fThomas Hindoe Paaboel Andersen s->address = *in_addr;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering s->resend_timeout = DNS_TIMEOUT_MIN_USEC;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
d21ed1ead18d16d35c30299a69d3366847f8a039Lennart Poettering if (type == DNS_SERVER_LINK) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering LIST_FIND_TAIL(servers, l->dns_servers, tail);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering LIST_INSERT_AFTER(servers, l->dns_servers, tail, s);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering s->link = l;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering } else if (type == DNS_SERVER_SYSTEM) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering LIST_FIND_TAIL(servers, m->dns_servers, tail);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering LIST_INSERT_AFTER(servers, m->dns_servers, tail, s);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering } else if (type == DNS_SERVER_FALLBACK) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering LIST_FIND_TAIL(servers, m->fallback_dns_servers, tail);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering LIST_INSERT_AFTER(servers, m->fallback_dns_servers, tail, s);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering } else
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert_not_reached("Unknown server type");
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen s->manager = m;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen /* A new DNS server that isn't fallback is added and the one
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering * we used so far was a fallback one? Then let's try to pick
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering * the new one */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (type != DNS_SERVER_FALLBACK &&
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering m->current_dns_server &&
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering m->current_dns_server->type == DNS_SERVER_FALLBACK)
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen manager_set_dns_server(m, NULL);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen if (ret)
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen *ret = s;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen return 0;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen}
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom GundersenDnsServer* dns_server_ref(DnsServer *s) {
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen if (!s)
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen return NULL;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert(s->n_ref > 0);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
e56056e93d33619a3acf13e483900b4f8938228fThomas Hindoe Paaboel Andersen s->n_ref ++;
e56056e93d33619a3acf13e483900b4f8938228fThomas Hindoe Paaboel Andersen
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return s;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen}
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
5b30bef856e89a571df57b7b953e9a1409d9acedLennart Poetteringstatic DnsServer* dns_server_free(DnsServer *s) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (!s)
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen return NULL;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (s->link && s->link->current_dns_server == s)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering link_set_dns_server(s->link, NULL);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen if (s->manager && s->manager->current_dns_server == s)
5b30bef856e89a571df57b7b953e9a1409d9acedLennart Poettering manager_set_dns_server(s->manager, NULL);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen free(s);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
5b30bef856e89a571df57b7b953e9a1409d9acedLennart Poettering return NULL;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering}
e56056e93d33619a3acf13e483900b4f8938228fThomas Hindoe Paaboel Andersen
e56056e93d33619a3acf13e483900b4f8938228fThomas Hindoe Paaboel AndersenDnsServer* dns_server_unref(DnsServer *s) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (!s)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return NULL;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert(s->n_ref > 0);
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen if (s->n_ref == 1)
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen dns_server_free(s);
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering else
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering s->n_ref --;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering return NULL;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering}
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poetteringvoid dns_server_packet_received(DnsServer *s, usec_t rtt) {
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering assert(s);
d21ed1ead18d16d35c30299a69d3366847f8a039Lennart Poettering
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering if (rtt <= s->max_rtt)
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering return;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering s->max_rtt = rtt;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering s->resend_timeout = MIN(MAX(DNS_TIMEOUT_MIN_USEC, s->max_rtt * 2), DNS_TIMEOUT_MAX_USEC);
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering}
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poetteringvoid dns_server_packet_lost(DnsServer *s, usec_t usec) {
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering assert(s);
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering if (s->resend_timeout > usec)
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering return;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen s->resend_timeout = MIN(s->resend_timeout * 2, DNS_TIMEOUT_MAX_USEC);
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering}
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersenstatic void dns_server_hash_func(const void *p, struct siphash *state) {
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering const DnsServer *s = p;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering assert(s);
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering
5b30bef856e89a571df57b7b953e9a1409d9acedLennart Poettering siphash24_compress(&s->family, sizeof(s->family), state);
5b30bef856e89a571df57b7b953e9a1409d9acedLennart Poettering siphash24_compress(&s->address, FAMILY_ADDRESS_SIZE(s->family), state);
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering}
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poetteringstatic int dns_server_compare_func(const void *a, const void *b) {
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering const DnsServer *x = a, *y = b;
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering if (x->family < y->family)
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering return -1;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering if (x->family > y->family)
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering return 1;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering return memcmp(&x->address, &y->address, FAMILY_ADDRESS_SIZE(x->family));
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering}
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poetteringconst struct hash_ops dns_server_hash_ops = {
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering .hash = dns_server_hash_func,
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering .compare = dns_server_compare_func
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering};
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poetteringvoid manager_flush_dns_servers(Manager *m, DnsServerType type) {
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering DnsServer **first, *s;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering assert(m);
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering first = type == DNS_SERVER_FALLBACK ? &m->fallback_dns_servers : &m->dns_servers;
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering while (*first) {
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering s = *first;
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering LIST_REMOVE(servers, *first, s);
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering dns_server_unref(s);
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering }
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering}
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poetteringvoid manager_flush_marked_dns_servers(Manager *m, DnsServerType type) {
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering DnsServer **first, *s, *next;
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering assert(m);
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering first = type == DNS_SERVER_FALLBACK ? &m->fallback_dns_servers : &m->dns_servers;
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering LIST_FOREACH_SAFE(servers, s, next, *first) {
0dd25fb9f005d8ab7ac4bc10a609d00569f8c56aLennart Poettering if (!s->marked)
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering continue;
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering LIST_REMOVE(servers, *first, s);
0dd25fb9f005d8ab7ac4bc10a609d00569f8c56aLennart Poettering dns_server_unref(s);
0dd25fb9f005d8ab7ac4bc10a609d00569f8c56aLennart Poettering }
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering}
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poetteringvoid manager_mark_dns_servers(Manager *m, DnsServerType type) {
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering DnsServer *first, *s;
0dd25fb9f005d8ab7ac4bc10a609d00569f8c56aLennart Poettering
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering assert(m);
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering first = type == DNS_SERVER_FALLBACK ? m->fallback_dns_servers : m->dns_servers;
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering LIST_FOREACH(servers, s, first)
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering s->marked = true;
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering}
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart PoetteringDnsServer* manager_find_dns_server(Manager *m, int family, const union in_addr_union *in_addr) {
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering DnsServer *s;
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering assert(m);
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering assert(in_addr);
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering LIST_FOREACH(servers, s, m->dns_servers)
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering if (s->family == family && in_addr_equal(family, &s->address, in_addr) > 0)
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering return s;
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering LIST_FOREACH(servers, s, m->fallback_dns_servers)
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering if (s->family == family && in_addr_equal(family, &s->address, in_addr) > 0)
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering return s;
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering return NULL;
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering}
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart PoetteringDnsServer *manager_set_dns_server(Manager *m, DnsServer *s) {
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering assert(m);
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering if (m->current_dns_server == s)
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering return s;
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering if (s) {
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering _cleanup_free_ char *ip = NULL;
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering in_addr_to_string(s->family, &s->address, &ip);
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering log_info("Switching to system DNS server %s.", strna(ip));
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering }
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering m->current_dns_server = s;
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering if (m->unicast_scope)
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering dns_cache_flush(&m->unicast_scope->cache);
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering return s;
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering}
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart PoetteringDnsServer *manager_get_dns_server(Manager *m) {
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering Link *l;
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering assert(m);
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering /* Try to read updates resolv.conf */
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering manager_read_resolv_conf(m);
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering /* If no DNS server was chose so far, pick the first one */
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering if (!m->current_dns_server)
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering manager_set_dns_server(m, m->dns_servers);
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering if (!m->current_dns_server) {
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering bool found = false;
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering Iterator i;
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering /* No DNS servers configured, let's see if there are
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering * any on any links. If not, we use the fallback
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering * servers */
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering HASHMAP_FOREACH(l, m->links, i)
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering if (l->dns_servers) {
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering found = true;
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering break;
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering }
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering if (!found)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering manager_set_dns_server(m, m->fallback_dns_servers);
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers return m->current_dns_server;
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers}
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sieversvoid manager_next_dns_server(Manager *m) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert(m);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering /* If there's currently no DNS server set, then the next
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering * manager_get_dns_server() will find one */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (!m->current_dns_server)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering /* Change to the next one */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (m->current_dns_server->servers_next) {
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering manager_set_dns_server(m, m->current_dns_server->servers_next);
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering return;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering /* If there was no next one, then start from the beginning of
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering * the list */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (m->current_dns_server->type == DNS_SERVER_FALLBACK)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering manager_set_dns_server(m, m->fallback_dns_servers);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering else
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering manager_set_dns_server(m, m->dns_servers);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering}
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering