resolved-dns-server.c revision 6bb2c08597c999c429e889cd2403b2fef5f3e1a0
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier This file is part of systemd.
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier Copyright 2014 Lennart Poettering
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier systemd is free software; you can redistribute it and/or modify it
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier under the terms of the GNU Lesser General Public License as published by
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier the Free Software Foundation; either version 2.1 of the License, or
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier (at your option) any later version.
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier systemd is distributed in the hope that it will be useful, but
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier WITHOUT ANY WARRANTY; without even the implied warranty of
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier Lesser General Public License for more details.
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier You should have received a copy of the GNU Lesser General Public License
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier along with systemd; If not, see <http://www.gnu.org/licenses/>.
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering/* After how much time to repeat classic DNS requests */
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier#define DNS_TIMEOUT_MIN_USEC (500 * USEC_PER_MSEC)
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier#define DNS_TIMEOUT_MAX_USEC (5 * USEC_PER_SEC)
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier/* The amount of time to wait before retrying with a full feature set */
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier#define DNS_SERVER_FEATURE_GRACE_PERIOD_MAX_USEC (6 * USEC_PER_HOUR)
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier#define DNS_SERVER_FEATURE_GRACE_PERIOD_MIN_USEC (5 * USEC_PER_MINUTE)
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier/* The number of times we will attempt a certain feature set before degrading */
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier if (l->n_dns_servers >= LINK_DNS_SERVERS_MAX)
cda134ab1eac84f874aacf8e885a07112a7fd5ceLennart Poettering if (m->n_dns_servers >= MANAGER_DNS_SERVERS_MAX)
cda134ab1eac84f874aacf8e885a07112a7fd5ceLennart Poettering s->verified_feature_level = _DNS_SERVER_FEATURE_LEVEL_INVALID;
4c1fc3e404d648c70bd2f50ac50aeac6ece8872eDaniel Mack s->possible_feature_level = DNS_SERVER_FEATURE_LEVEL_BEST;
7430ec6ac08f2c0416d9f806964c46b30f3862b2Lennart Poettering s->features_grace_period_usec = DNS_SERVER_FEATURE_GRACE_PERIOD_MIN_USEC;
7430ec6ac08f2c0416d9f806964c46b30f3862b2Lennart Poettering s->received_udp_packet_max = DNS_PACKET_UNICAST_SIZE_MAX;
cda134ab1eac84f874aacf8e885a07112a7fd5ceLennart Poettering s->resend_timeout = DNS_TIMEOUT_MIN_USEC;
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier LIST_APPEND(servers, m->fallback_dns_servers, s);
63c372cb9df3bee01e3bf8cd7f96f336bddda846Lennart Poettering /* A new DNS server that isn't fallback is added and the one
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier * we used so far was a fallback one? Then let's try to pick
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier * the new one */
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier m->current_dns_server->type == DNS_SERVER_FALLBACK)
ad5ecc113821fbfa33f6fd43cdaee9c538cdff78Zbigniew Jędrzejewski-Szmekvoid dns_server_unlink(DnsServer *s) {
4f36d4004c407c16508001a20450c5f14f7d4d31Dimitri John Ledkov /* This removes the specified server from the linked list of
ad5ecc113821fbfa33f6fd43cdaee9c538cdff78Zbigniew Jędrzejewski-Szmek * servers, but any server might still stay around if it has
ad5ecc113821fbfa33f6fd43cdaee9c538cdff78Zbigniew Jędrzejewski-Szmek * refs, for example from an ongoing transaction. */
ad5ecc113821fbfa33f6fd43cdaee9c538cdff78Zbigniew Jędrzejewski-Szmek assert(s->link->n_dns_servers > 0);
ad5ecc113821fbfa33f6fd43cdaee9c538cdff78Zbigniew Jędrzejewski-Szmek LIST_REMOVE(servers, s->link->dns_servers, s);
ad5ecc113821fbfa33f6fd43cdaee9c538cdff78Zbigniew Jędrzejewski-Szmek assert(s->manager->n_dns_servers > 0);
ad5ecc113821fbfa33f6fd43cdaee9c538cdff78Zbigniew Jędrzejewski-Szmek LIST_REMOVE(servers, s->manager->dns_servers, s);
ad5ecc113821fbfa33f6fd43cdaee9c538cdff78Zbigniew Jędrzejewski-Szmek assert(s->manager->n_dns_servers > 0);
ad5ecc113821fbfa33f6fd43cdaee9c538cdff78Zbigniew Jędrzejewski-Szmek LIST_REMOVE(servers, s->manager->fallback_dns_servers, s);
cda134ab1eac84f874aacf8e885a07112a7fd5ceLennart Poettering if (s->link && s->link->current_dns_server == s)
dns_server_unref(s);
assert(s);
if (!s->marked)
s->marked = false;
switch (s->type) {
case DNS_SERVER_LINK:
case DNS_SERVER_SYSTEM:
case DNS_SERVER_FALLBACK:
assert(s);
void dns_server_packet_received(DnsServer *s, int protocol, DnsServerFeatureLevel level, usec_t rtt, size_t size) {
assert(s);
s->n_failed_udp = 0;
s->n_failed_tcp = 0;
assert(s);
s->n_failed_udp ++;
s->n_failed_tcp ++;
assert(s);
s->packet_failed = true;
assert(s);
s->packet_truncated = true;
assert(s);
log_warning("DNS server %s does not augment replies with RRSIG records, DNSSEC not available.", strna(ip));
s->rrsig_missing = true;
assert(s);
if (s->verified_usec == 0)
s->features_grace_period_usec = MIN(s->features_grace_period_usec * 2, DNS_SERVER_FEATURE_GRACE_PERIOD_MAX_USEC);
assert(s);
s->n_failed_udp = 0;
s->n_failed_tcp = 0;
s->packet_failed = false;
s->packet_truncated = false;
s->verified_usec = 0;
s->rrsig_missing = false;
(s->packet_failed &&
s->packet_truncated &&
s->possible_feature_level--;
if (p != s->possible_feature_level) {
s->n_failed_udp = 0;
s->n_failed_tcp = 0;
s->packet_failed = false;
s->packet_truncated = false;
s->verified_usec = 0;
return s->possible_feature_level;
bool edns_do;
const DnsServer *s = p;
assert(s);
static int dns_server_compare_func(const void *a, const void *b) {
const DnsServer *x = a, *y = b;
if (!first)
if (!first)
if (!first)
DnsServer *s;
return NULL;
assert(m);
case DNS_SERVER_SYSTEM:
return m->dns_servers;
case DNS_SERVER_FALLBACK:
return m->fallback_dns_servers;
return NULL;
assert(m);
if (m->current_dns_server == s)
if (m->unicast_scope)
Link *l;
assert(m);
/* Try to read updates resolv.conf */
if (!m->current_dns_server)
if (!m->current_dns_server) {
bool found = false;
Iterator i;
if (l->dns_servers) {
found = true;
if (!found)
return m->current_dns_server;
assert(m);
if (!m->current_dns_server)