resolved-dns-server.c revision 91b14d6ff362b938a72db17b095ee9903d07381b
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering/***
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering This file is part of systemd.
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering Copyright 2014 Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering systemd is free software; you can redistribute it and/or modify it
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering under the terms of the GNU Lesser General Public License as published by
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering (at your option) any later version.
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering systemd is distributed in the hope that it will be useful, but
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering Lesser General Public License for more details.
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering You should have received a copy of the GNU Lesser General Public License
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering***/
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering#include "siphash24.h"
4871690d9e32608bbd9b18505b5326c2079c9690Allin Cottrell
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering#include "resolved-dns-server.h"
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
178cc7700c23ac088cd7190d7854282075028d91Lennart Poetteringint dns_server_new(
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering Manager *m,
d682b3a7e7c7c2941a4d3e193f1e330dbc9fae89Lennart Poettering DnsServer **ret,
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek DnsServerType type,
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering Link *l,
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering int family,
3b7124a8db56ed57525b9ecfd19cfdc8c9facba0Lennart Poettering const union in_addr_union *in_addr) {
40b71e89bae4e51768db4dc50ec64c1e9c96eec4Sebastian Thorarensen
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering DnsServer *s, *tail;
178cc7700c23ac088cd7190d7854282075028d91Lennart Poettering
178cc7700c23ac088cd7190d7854282075028d91Lennart Poettering assert(m);
178cc7700c23ac088cd7190d7854282075028d91Lennart Poettering assert((type == DNS_SERVER_LINK) == !!l);
3b3154df7e2773332bb814e167187367a0ccae4aLennart Poettering assert(in_addr);
b92bea5d2a9481de69bb627a7b442a9f58fca43dZbigniew Jędrzejewski-Szmek
46b131574fdd7d77c15a0919ca9010cad7aa6ac7Lennart Poettering s = new0(DnsServer, 1);
b92bea5d2a9481de69bb627a7b442a9f58fca43dZbigniew Jędrzejewski-Szmek if (!s)
b92bea5d2a9481de69bb627a7b442a9f58fca43dZbigniew Jędrzejewski-Szmek return -ENOMEM;
b92bea5d2a9481de69bb627a7b442a9f58fca43dZbigniew Jędrzejewski-Szmek
b92bea5d2a9481de69bb627a7b442a9f58fca43dZbigniew Jędrzejewski-Szmek s->n_ref = 1;
b92bea5d2a9481de69bb627a7b442a9f58fca43dZbigniew Jędrzejewski-Szmek s->type = type;
b92bea5d2a9481de69bb627a7b442a9f58fca43dZbigniew Jędrzejewski-Szmek s->family = family;
46b131574fdd7d77c15a0919ca9010cad7aa6ac7Lennart Poettering s->address = *in_addr;
b92bea5d2a9481de69bb627a7b442a9f58fca43dZbigniew Jędrzejewski-Szmek
f8294e4175918117ca6c131720bcf287eadcd029Josh Triplett if (type == DNS_SERVER_LINK) {
b92bea5d2a9481de69bb627a7b442a9f58fca43dZbigniew Jędrzejewski-Szmek LIST_FIND_TAIL(servers, l->dns_servers, tail);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering LIST_INSERT_AFTER(servers, l->dns_servers, tail, s);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering s->link = l;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering } else if (type == DNS_SERVER_SYSTEM) {
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering LIST_FIND_TAIL(servers, m->dns_servers, tail);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering LIST_INSERT_AFTER(servers, m->dns_servers, tail, s);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering } else if (type == DNS_SERVER_FALLBACK) {
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering LIST_FIND_TAIL(servers, m->fallback_dns_servers, tail);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering LIST_INSERT_AFTER(servers, m->fallback_dns_servers, tail, s);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering } else
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering assert_not_reached("Unknown server type");
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering s->manager = m;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering /* A new DNS server that isn't fallback is added and the one
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering * we used so far was a fallback one? Then let's try to pick
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering * the new one */
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (type != DNS_SERVER_FALLBACK &&
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering m->current_dns_server &&
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering m->current_dns_server->type == DNS_SERVER_FALLBACK)
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering manager_set_dns_server(m, NULL);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (ret)
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering *ret = s;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering return 0;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering}
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart PoetteringDnsServer* dns_server_ref(DnsServer *s) {
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (!s)
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering return NULL;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering assert(s->n_ref > 0);
178cc7700c23ac088cd7190d7854282075028d91Lennart Poettering
178cc7700c23ac088cd7190d7854282075028d91Lennart Poettering s->n_ref ++;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
178cc7700c23ac088cd7190d7854282075028d91Lennart Poettering return s;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering}
ccf23ad5faf228d450d263d7291156a948b61af2Christian Seiler
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poetteringstatic DnsServer* dns_server_free(DnsServer *s) {
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (!s)
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering return NULL;
ccf23ad5faf228d450d263d7291156a948b61af2Christian Seiler
ccf23ad5faf228d450d263d7291156a948b61af2Christian Seiler if (s->link && s->link->current_dns_server == s)
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering link_set_dns_server(s->link, NULL);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (s->manager && s->manager->current_dns_server == s)
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering manager_set_dns_server(s->manager, NULL);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering free(s);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering return NULL;
178cc7700c23ac088cd7190d7854282075028d91Lennart Poettering}
178cc7700c23ac088cd7190d7854282075028d91Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart PoetteringDnsServer* dns_server_unref(DnsServer *s) {
178cc7700c23ac088cd7190d7854282075028d91Lennart Poettering if (!s)
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering return NULL;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering assert(s->n_ref > 0);
56f64d95763a799ba4475daf44d8e9f72a1bd474Michal Schmidt
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (s->n_ref == 1)
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering dns_server_free(s);
3b3154df7e2773332bb814e167187367a0ccae4aLennart Poettering else
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering s->n_ref --;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering return NULL;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering}
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poetteringstatic unsigned long dns_server_hash_func(const void *p, const uint8_t hash_key[HASH_KEY_SIZE]) {
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering const DnsServer *s = p;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering uint64_t u;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering siphash24((uint8_t*) &u, &s->address, FAMILY_ADDRESS_SIZE(s->family), hash_key);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering u = u * hash_key[0] + u + s->family;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
3b3154df7e2773332bb814e167187367a0ccae4aLennart Poettering return u;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering}
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poetteringstatic int dns_server_compare_func(const void *a, const void *b) {
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering const DnsServer *x = a, *y = b;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (x->family < y->family)
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering return -1;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (x->family > y->family)
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering return 1;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering return memcmp(&x->address, &y->address, FAMILY_ADDRESS_SIZE(x->family));
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering}
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poetteringconst struct hash_ops dns_server_hash_ops = {
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering .hash = dns_server_hash_func,
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering .compare = dns_server_compare_func
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering};
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering