resolved-dns-server.c revision 87f5a19343acf8ba697acc5a62bdb1a2b8c9eda3
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering/***
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering This file is part of systemd.
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering Copyright 2014 Lennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering systemd is free software; you can redistribute it and/or modify it
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering under the terms of the GNU Lesser General Public License as published by
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering the Free Software Foundation; either version 2.1 of the License, or
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering (at your option) any later version.
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering systemd is distributed in the hope that it will be useful, but
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering Lesser General Public License for more details.
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering You should have received a copy of the GNU Lesser General Public License
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering***/
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering#include "siphash24.h"
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering#include "resolved-dns-server.h"
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poetteringint dns_server_new(
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering Manager *m,
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering DnsServer **ret,
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering DnsServerType type,
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering Link *l,
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering int family,
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering const union in_addr_union *in_addr) {
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering DnsServer *s, *tail;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering assert(m);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering assert((type == DNS_SERVER_LINK) == !!l);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering assert(in_addr);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering s = new0(DnsServer, 1);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering if (!s)
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering return -ENOMEM;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering s->type = type;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering s->family = family;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering s->address = *in_addr;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
baed47c3c20512507e497058d388782400a072f6Lennart Poettering if (type == DNS_SERVER_LINK) {
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering LIST_FIND_TAIL(servers, l->dns_servers, tail);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering LIST_INSERT_AFTER(servers, l->dns_servers, tail, s);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering s->link = l;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering } else if (type == DNS_SERVER_SYSTEM) {
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering LIST_FIND_TAIL(servers, m->dns_servers, tail);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering LIST_INSERT_AFTER(servers, m->dns_servers, tail, s);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering } else if (type == DNS_SERVER_FALLBACK) {
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering LIST_FIND_TAIL(servers, m->fallback_dns_servers, tail);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering LIST_INSERT_AFTER(servers, m->fallback_dns_servers, tail, s);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering } else
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering assert_not_reached("Unknown server type");
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
14d10188de1fd58e663d73683a400d8d7dc67dbaLennart Poettering s->manager = m;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
9f6445e34a57c270f013c9416c123e56261553ddLennart Poettering /* A new DNS server that isn't fallback is added and the one
507f22bd0172bff5e5d98145b1419bd472a2c57fZbigniew Jędrzejewski-Szmek * we used so far was a fallback one? Then let's try to pick
507f22bd0172bff5e5d98145b1419bd472a2c57fZbigniew Jędrzejewski-Szmek * the new one */
e627440b41bb0284e4892f7aa9d84c77972487e2Lennart Poettering if (type != DNS_SERVER_FALLBACK &&
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering s->manager->current_dns_server &&
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering s->manager->current_dns_server->type == DNS_SERVER_FALLBACK)
5996c7c295e073ce21d41305169132c8aa993ad0Lennart Poettering manager_set_dns_server(s->manager, NULL);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering if (ret)
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering *ret = s;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering return 0;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering}
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart PoetteringDnsServer* dns_server_free(DnsServer *s) {
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering if (!s)
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering return NULL;
14d10188de1fd58e663d73683a400d8d7dc67dbaLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering if (s->manager) {
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering if (s->type == DNS_SERVER_LINK)
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering LIST_REMOVE(servers, s->link->dns_servers, s);
baed47c3c20512507e497058d388782400a072f6Lennart Poettering else if (s->type == DNS_SERVER_SYSTEM)
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering LIST_REMOVE(servers, s->manager->dns_servers, s);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering else if (s->type == DNS_SERVER_FALLBACK)
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering LIST_REMOVE(servers, s->manager->fallback_dns_servers, s);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering else
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering assert_not_reached("Unknown server type");
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering }
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
b7c9ae91d111b3e89d1ffc00e08f9ed97a8ff5dbLennart Poettering if (s->link && s->link->current_dns_server == s)
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering link_set_dns_server(s->link, NULL);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering if (s->manager && s->manager->current_dns_server == s)
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering manager_set_dns_server(s->manager, NULL);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering free(s);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering return NULL;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering}
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poetteringunsigned long dns_server_hash_func(const void *p, const uint8_t hash_key[HASH_KEY_SIZE]) {
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering const DnsServer *s = p;
baed47c3c20512507e497058d388782400a072f6Lennart Poettering uint64_t u;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
baed47c3c20512507e497058d388782400a072f6Lennart Poettering siphash24((uint8_t*) &u, &s->address, FAMILY_ADDRESS_SIZE(s->family), hash_key);
baed47c3c20512507e497058d388782400a072f6Lennart Poettering u = u * hash_key[0] + u + s->family;
15411c0cb1192799b37ec8f25d6f30e8d7292fc6David Herrmann
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering return u;
baed47c3c20512507e497058d388782400a072f6Lennart Poettering}
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poetteringint dns_server_compare_func(const void *a, const void *b) {
baed47c3c20512507e497058d388782400a072f6Lennart Poettering const DnsServer *x = a, *y = b;
baed47c3c20512507e497058d388782400a072f6Lennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering if (x->family < y->family)
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering return -1;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering if (x->family > y->family)
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering return 1;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
baed47c3c20512507e497058d388782400a072f6Lennart Poettering return memcmp(&x->address, &y->address, FAMILY_ADDRESS_SIZE(x->family));
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering}
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering