resolved-dns-rr.c revision 0936416a1cba187dc76903dae73246f4cbddf312
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering/***
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering This file is part of systemd.
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering Copyright 2014 Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering systemd is free software; you can redistribute it and/or modify it
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering under the terms of the GNU Lesser General Public License as published by
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering (at your option) any later version.
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering systemd is distributed in the hope that it will be useful, but
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering Lesser General Public License for more details.
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering You should have received a copy of the GNU Lesser General Public License
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering***/
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering#include <math.h>
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering#include "alloc-util.h"
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering#include "dns-domain.h"
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering#include "dns-type.h"
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering#include "hexdecoct.h"
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering#include "resolved-dns-packet.h"
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering#include "resolved-dns-rr.h"
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering#include "string-table.h"
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering#include "string-util.h"
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering#include "strv.h"
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart PoetteringDnsResourceKey* dns_resource_key_new(uint16_t class, uint16_t type, const char *name) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering DnsResourceKey *k;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering size_t l;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering assert(name);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering l = strlen(name);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering k = malloc0(sizeof(DnsResourceKey) + l + 1);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (!k)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return NULL;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering k->n_ref = 1;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering k->class = class;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering k->type = type;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering strcpy((char*) k + sizeof(DnsResourceKey), name);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return k;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering}
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart PoetteringDnsResourceKey* dns_resource_key_new_redirect(const DnsResourceKey *key, const DnsResourceRecord *cname) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering int r;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering assert(key);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering assert(cname);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering assert(IN_SET(cname->key->type, DNS_TYPE_CNAME, DNS_TYPE_DNAME));
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (cname->key->type == DNS_TYPE_CNAME)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return dns_resource_key_new(key->class, key->type, cname->cname.name);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering else {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering DnsResourceKey *k;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering char *destination = NULL;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = dns_name_change_suffix(DNS_RESOURCE_KEY_NAME(key), DNS_RESOURCE_KEY_NAME(cname->key), cname->dname.name, &destination);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (r < 0)
78fe420ff0bb4cd94de3c4d3f15a3021cc3e2878Lennart Poettering return NULL;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (r == 0)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return dns_resource_key_ref((DnsResourceKey*) key);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering k = dns_resource_key_new_consume(key->class, key->type, destination);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (!k) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering free(destination);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return NULL;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering }
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return k;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering }
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering}
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poetteringint dns_resource_key_new_append_suffix(DnsResourceKey **ret, DnsResourceKey *key, char *name) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering DnsResourceKey *new_key;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering char *joined;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering int r;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering assert(ret);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering assert(key);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering assert(name);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (dns_name_is_root(name)) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering *ret = dns_resource_key_ref(key);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return 0;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering }
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = dns_name_concat(DNS_RESOURCE_KEY_NAME(key), name, &joined);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (r < 0)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return r;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering new_key = dns_resource_key_new_consume(key->class, key->type, joined);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (!new_key) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering free(joined);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return -ENOMEM;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering }
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering *ret = new_key;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return 0;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering}
78fe420ff0bb4cd94de3c4d3f15a3021cc3e2878Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart PoetteringDnsResourceKey* dns_resource_key_new_consume(uint16_t class, uint16_t type, char *name) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering DnsResourceKey *k;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering assert(name);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering k = new0(DnsResourceKey, 1);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (!k)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return NULL;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
78fe420ff0bb4cd94de3c4d3f15a3021cc3e2878Lennart Poettering k->n_ref = 1;
78fe420ff0bb4cd94de3c4d3f15a3021cc3e2878Lennart Poettering k->class = class;
78fe420ff0bb4cd94de3c4d3f15a3021cc3e2878Lennart Poettering k->type = type;
78fe420ff0bb4cd94de3c4d3f15a3021cc3e2878Lennart Poettering k->_name = name;
78fe420ff0bb4cd94de3c4d3f15a3021cc3e2878Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return k;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering}
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
78fe420ff0bb4cd94de3c4d3f15a3021cc3e2878Lennart PoetteringDnsResourceKey* dns_resource_key_ref(DnsResourceKey *k) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (!k)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return NULL;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering /* Static/const keys created with DNS_RESOURCE_KEY_CONST will
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering * set this to -1, they should not be reffed/unreffed */
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering assert(k->n_ref != (unsigned) -1);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering assert(k->n_ref > 0);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering k->n_ref++;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return k;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering}
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart PoetteringDnsResourceKey* dns_resource_key_unref(DnsResourceKey *k) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (!k)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return NULL;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering assert(k->n_ref != (unsigned) -1);
78fe420ff0bb4cd94de3c4d3f15a3021cc3e2878Lennart Poettering assert(k->n_ref > 0);
78fe420ff0bb4cd94de3c4d3f15a3021cc3e2878Lennart Poettering
78fe420ff0bb4cd94de3c4d3f15a3021cc3e2878Lennart Poettering if (k->n_ref == 1) {
78fe420ff0bb4cd94de3c4d3f15a3021cc3e2878Lennart Poettering free(k->_name);
78fe420ff0bb4cd94de3c4d3f15a3021cc3e2878Lennart Poettering free(k);
78fe420ff0bb4cd94de3c4d3f15a3021cc3e2878Lennart Poettering } else
78fe420ff0bb4cd94de3c4d3f15a3021cc3e2878Lennart Poettering k->n_ref--;
78fe420ff0bb4cd94de3c4d3f15a3021cc3e2878Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return NULL;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering}
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poetteringbool dns_resource_key_is_address(const DnsResourceKey *key) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering assert(key);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering /* Check if this is an A or AAAA resource key */
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return key->class == DNS_CLASS_IN && IN_SET(key->type, DNS_TYPE_A, DNS_TYPE_AAAA);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering}
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poetteringint dns_resource_key_equal(const DnsResourceKey *a, const DnsResourceKey *b) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering int r;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (a == b)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return 1;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = dns_name_equal(DNS_RESOURCE_KEY_NAME(a), DNS_RESOURCE_KEY_NAME(b));
9833a66c7eba011c3740867c80133bc6fa976aa3Lennart Poettering if (r <= 0)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return r;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (a->class != b->class)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return 0;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (a->type != b->type)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return 0;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return 1;
9833a66c7eba011c3740867c80133bc6fa976aa3Lennart Poettering}
9833a66c7eba011c3740867c80133bc6fa976aa3Lennart Poettering
9833a66c7eba011c3740867c80133bc6fa976aa3Lennart Poetteringint dns_resource_key_match_rr(const DnsResourceKey *key, DnsResourceRecord *rr, const char *search_domain) {
9833a66c7eba011c3740867c80133bc6fa976aa3Lennart Poettering int r;
9833a66c7eba011c3740867c80133bc6fa976aa3Lennart Poettering
9833a66c7eba011c3740867c80133bc6fa976aa3Lennart Poettering assert(key);
9833a66c7eba011c3740867c80133bc6fa976aa3Lennart Poettering assert(rr);
9833a66c7eba011c3740867c80133bc6fa976aa3Lennart Poettering
9833a66c7eba011c3740867c80133bc6fa976aa3Lennart Poettering if (key == rr->key)
9833a66c7eba011c3740867c80133bc6fa976aa3Lennart Poettering return 1;
9833a66c7eba011c3740867c80133bc6fa976aa3Lennart Poettering
9833a66c7eba011c3740867c80133bc6fa976aa3Lennart Poettering /* Checks if an rr matches the specified key. If a search
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering * domain is specified, it will also be checked if the key
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering * with the search domain suffixed might match the RR. */
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (rr->key->class != key->class && key->class != DNS_CLASS_ANY)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return 0;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (rr->key->type != key->type && key->type != DNS_TYPE_ANY)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return 0;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = dns_name_equal(DNS_RESOURCE_KEY_NAME(rr->key), DNS_RESOURCE_KEY_NAME(key));
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (r != 0)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return r;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (search_domain) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering _cleanup_free_ char *joined = NULL;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = dns_name_concat(DNS_RESOURCE_KEY_NAME(key), search_domain, &joined);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (r < 0)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return r;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return dns_name_equal(DNS_RESOURCE_KEY_NAME(rr->key), joined);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering }
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return 0;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering}
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poetteringint dns_resource_key_match_cname_or_dname(const DnsResourceKey *key, const DnsResourceKey *cname, const char *search_domain) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering int r;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering assert(key);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering assert(cname);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (cname->class != key->class && key->class != DNS_CLASS_ANY)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return 0;
78fe420ff0bb4cd94de3c4d3f15a3021cc3e2878Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (cname->type == DNS_TYPE_CNAME)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = dns_name_equal(DNS_RESOURCE_KEY_NAME(key), DNS_RESOURCE_KEY_NAME(cname));
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering else if (cname->type == DNS_TYPE_DNAME)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = dns_name_endswith(DNS_RESOURCE_KEY_NAME(key), DNS_RESOURCE_KEY_NAME(cname));
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering else
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return 0;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (r != 0)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return r;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (search_domain) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering _cleanup_free_ char *joined = NULL;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = dns_name_concat(DNS_RESOURCE_KEY_NAME(key), search_domain, &joined);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (r < 0)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return r;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (cname->type == DNS_TYPE_CNAME)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return dns_name_equal(joined, DNS_RESOURCE_KEY_NAME(cname));
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering else if (cname->type == DNS_TYPE_DNAME)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return dns_name_endswith(joined, DNS_RESOURCE_KEY_NAME(cname));
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering }
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return 0;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering}
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poetteringint dns_resource_key_match_soa(const DnsResourceKey *key, const DnsResourceKey *soa) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering assert(soa);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering assert(key);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering /* Checks whether 'soa' is a SOA record for the specified key. */
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (soa->class != key->class)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return 0;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (soa->type != DNS_TYPE_SOA)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return 0;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return dns_name_endswith(DNS_RESOURCE_KEY_NAME(key), DNS_RESOURCE_KEY_NAME(soa));
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering}
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poetteringstatic void dns_resource_key_hash_func(const void *i, struct siphash *state) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering const DnsResourceKey *k = i;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering assert(k);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering dns_name_hash_func(DNS_RESOURCE_KEY_NAME(k), state);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering siphash24_compress(&k->class, sizeof(k->class), state);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering siphash24_compress(&k->type, sizeof(k->type), state);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering}
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poetteringstatic int dns_resource_key_compare_func(const void *a, const void *b) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering const DnsResourceKey *x = a, *y = b;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering int ret;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering ret = dns_name_compare_func(DNS_RESOURCE_KEY_NAME(x), DNS_RESOURCE_KEY_NAME(y));
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (ret != 0)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return ret;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (x->type < y->type)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return -1;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (x->type > y->type)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return 1;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (x->class < y->class)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return -1;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (x->class > y->class)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return 1;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return 0;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering}
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poetteringconst struct hash_ops dns_resource_key_hash_ops = {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering .hash = dns_resource_key_hash_func,
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering .compare = dns_resource_key_compare_func
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering};
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poetteringint dns_resource_key_to_string(const DnsResourceKey *key, char **ret) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering char cbuf[strlen("CLASS") + DECIMAL_STR_MAX(uint16_t)], tbuf[strlen("TYPE") + DECIMAL_STR_MAX(uint16_t)];
23bbb0de4e3f85d9704a5c12a5afa2dfa0159e41Michal Schmidt const char *c, *t;
23bbb0de4e3f85d9704a5c12a5afa2dfa0159e41Michal Schmidt char *s;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering c = dns_class_to_string(key->class);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (!c) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering sprintf(cbuf, "CLASS%u", key->class);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering c = cbuf;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering }
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering t = dns_type_to_string(key->type);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (!t){
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering sprintf(tbuf, "TYPE%u", key->type);
23bbb0de4e3f85d9704a5c12a5afa2dfa0159e41Michal Schmidt t = tbuf;
23bbb0de4e3f85d9704a5c12a5afa2dfa0159e41Michal Schmidt }
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (asprintf(&s, "%s. %s %-5s", DNS_RESOURCE_KEY_NAME(key), c, t) < 0)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return -ENOMEM;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering *ret = s;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return 0;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering}
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart PoetteringDnsResourceRecord* dns_resource_record_new(DnsResourceKey *key) {
0b97208d8c39131f8a7cfcfccb5c40b86af44ee5Lennart Poettering DnsResourceRecord *rr;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering rr = new0(DnsResourceRecord, 1);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (!rr)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return NULL;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering rr->n_ref = 1;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering rr->key = dns_resource_key_ref(key);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return rr;
25b3245fb483e52766867dfe33ce271011caaca9Lennart Poettering}
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart PoetteringDnsResourceRecord* dns_resource_record_new_full(uint16_t class, uint16_t type, const char *name) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering key = dns_resource_key_new(class, type, name);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (!key)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return NULL;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return dns_resource_record_new(key);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering}
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart PoetteringDnsResourceRecord* dns_resource_record_ref(DnsResourceRecord *rr) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (!rr)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return NULL;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering assert(rr->n_ref > 0);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering rr->n_ref++;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
5034c7bcdfc4493ed3c30722e9d897c8da78fedeLennart Poettering return rr;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering}
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart PoetteringDnsResourceRecord* dns_resource_record_unref(DnsResourceRecord *rr) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (!rr)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return NULL;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering assert(rr->n_ref > 0);
5034c7bcdfc4493ed3c30722e9d897c8da78fedeLennart Poettering
5034c7bcdfc4493ed3c30722e9d897c8da78fedeLennart Poettering if (rr->n_ref > 1) {
5034c7bcdfc4493ed3c30722e9d897c8da78fedeLennart Poettering rr->n_ref--;
5034c7bcdfc4493ed3c30722e9d897c8da78fedeLennart Poettering return NULL;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering }
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (rr->key) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering switch(rr->key->type) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering case DNS_TYPE_SRV:
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering free(rr->srv.name);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering break;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering case DNS_TYPE_PTR:
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering case DNS_TYPE_NS:
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering case DNS_TYPE_CNAME:
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering case DNS_TYPE_DNAME:
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering free(rr->ptr.name);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering break;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering case DNS_TYPE_HINFO:
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering free(rr->hinfo.cpu);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering free(rr->hinfo.os);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering break;
124aff6251c095367ce1323a21fa23235cbb0490Lennart Poettering
124aff6251c095367ce1323a21fa23235cbb0490Lennart Poettering case DNS_TYPE_TXT:
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering case DNS_TYPE_SPF:
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering dns_txt_item_free_all(rr->txt.items);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering break;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering case DNS_TYPE_SOA:
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering free(rr->soa.mname);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering free(rr->soa.rname);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering break;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering case DNS_TYPE_MX:
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering free(rr->mx.exchange);
0b97208d8c39131f8a7cfcfccb5c40b86af44ee5Lennart Poettering break;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering case DNS_TYPE_DS:
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering free(rr->ds.digest);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering break;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering case DNS_TYPE_SSHFP:
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering free(rr->sshfp.fingerprint);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering break;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering case DNS_TYPE_DNSKEY:
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering free(rr->dnskey.key);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering break;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering case DNS_TYPE_RRSIG:
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering free(rr->rrsig.signer);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering free(rr->rrsig.signature);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering break;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering case DNS_TYPE_NSEC:
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering free(rr->nsec.next_domain_name);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering bitmap_free(rr->nsec.types);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering break;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering case DNS_TYPE_NSEC3:
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering free(rr->nsec3.next_hashed_name);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering free(rr->nsec3.salt);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering bitmap_free(rr->nsec3.types);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering break;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering case DNS_TYPE_LOC:
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering case DNS_TYPE_A:
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering case DNS_TYPE_AAAA:
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering break;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering default:
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering free(rr->generic.data);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering }
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering free(rr->wire_format);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering dns_resource_key_unref(rr->key);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering }
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering free(rr);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return NULL;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering}
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poetteringint dns_resource_record_new_reverse(DnsResourceRecord **ret, int family, const union in_addr_union *address, const char *hostname) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering _cleanup_free_ char *ptr = NULL;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering int r;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
0b97208d8c39131f8a7cfcfccb5c40b86af44ee5Lennart Poettering assert(ret);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering assert(address);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering assert(hostname);
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering r = dns_name_reverse(family, address, &ptr);
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering if (r < 0)
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering return r;
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering key = dns_resource_key_new_consume(DNS_CLASS_IN, DNS_TYPE_PTR, ptr);
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering if (!key)
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering return -ENOMEM;
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering ptr = NULL;
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering rr = dns_resource_record_new(key);
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering if (!rr)
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering return -ENOMEM;
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering rr->ptr.name = strdup(hostname);
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering if (!rr->ptr.name)
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering return -ENOMEM;
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering *ret = rr;
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering rr = NULL;
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering return 0;
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering}
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poetteringint dns_resource_record_new_address(DnsResourceRecord **ret, int family, const union in_addr_union *address, const char *name) {
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering DnsResourceRecord *rr;
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering assert(ret);
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering assert(address);
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering assert(family);
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering if (family == AF_INET) {
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering rr = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_A, name);
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering if (!rr)
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering return -ENOMEM;
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering rr->a.in_addr = address->in;
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering } else if (family == AF_INET6) {
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering rr = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_AAAA, name);
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering if (!rr)
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering return -ENOMEM;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering rr->aaaa.in6_addr = address->in6;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering } else
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return -EAFNOSUPPORT;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering *ret = rr;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return 0;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering}
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poetteringint dns_resource_record_equal(const DnsResourceRecord *a, const DnsResourceRecord *b) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering int r;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering assert(a);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering assert(b);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (a == b)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return 1;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = dns_resource_key_equal(a->key, b->key);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (r <= 0)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return r;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (a->unparseable != b->unparseable)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return 0;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering switch (a->unparseable ? _DNS_TYPE_INVALID : a->key->type) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering case DNS_TYPE_SRV:
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = dns_name_equal(a->srv.name, b->srv.name);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (r <= 0)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return r;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return a->srv.priority == b->srv.priority &&
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering a->srv.weight == b->srv.weight &&
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering a->srv.port == b->srv.port;
23bbb0de4e3f85d9704a5c12a5afa2dfa0159e41Michal Schmidt
23bbb0de4e3f85d9704a5c12a5afa2dfa0159e41Michal Schmidt case DNS_TYPE_PTR:
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering case DNS_TYPE_NS:
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering case DNS_TYPE_CNAME:
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering case DNS_TYPE_DNAME:
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering return dns_name_equal(a->ptr.name, b->ptr.name);
da927ba997d68401563b927f92e6e40e021a8e5cMichal Schmidt
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering case DNS_TYPE_HINFO:
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return strcaseeq(a->hinfo.cpu, b->hinfo.cpu) &&
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering strcaseeq(a->hinfo.os, b->hinfo.os);
case DNS_TYPE_SPF: /* exactly the same as TXT */
case DNS_TYPE_TXT:
return dns_txt_item_equal(a->txt.items, b->txt.items);
case DNS_TYPE_A:
return memcmp(&a->a.in_addr, &b->a.in_addr, sizeof(struct in_addr)) == 0;
case DNS_TYPE_AAAA:
return memcmp(&a->aaaa.in6_addr, &b->aaaa.in6_addr, sizeof(struct in6_addr)) == 0;
case DNS_TYPE_SOA:
r = dns_name_equal(a->soa.mname, b->soa.mname);
if (r <= 0)
return r;
r = dns_name_equal(a->soa.rname, b->soa.rname);
if (r <= 0)
return r;
return a->soa.serial == b->soa.serial &&
a->soa.refresh == b->soa.refresh &&
a->soa.retry == b->soa.retry &&
a->soa.expire == b->soa.expire &&
a->soa.minimum == b->soa.minimum;
case DNS_TYPE_MX:
if (a->mx.priority != b->mx.priority)
return 0;
return dns_name_equal(a->mx.exchange, b->mx.exchange);
case DNS_TYPE_LOC:
assert(a->loc.version == b->loc.version);
return a->loc.size == b->loc.size &&
a->loc.horiz_pre == b->loc.horiz_pre &&
a->loc.vert_pre == b->loc.vert_pre &&
a->loc.latitude == b->loc.latitude &&
a->loc.longitude == b->loc.longitude &&
a->loc.altitude == b->loc.altitude;
case DNS_TYPE_DS:
return a->ds.key_tag == b->ds.key_tag &&
a->ds.algorithm == b->ds.algorithm &&
a->ds.digest_type == b->ds.digest_type &&
a->ds.digest_size == b->ds.digest_size &&
memcmp(a->ds.digest, b->ds.digest, a->ds.digest_size) == 0;
case DNS_TYPE_SSHFP:
return a->sshfp.algorithm == b->sshfp.algorithm &&
a->sshfp.fptype == b->sshfp.fptype &&
a->sshfp.fingerprint_size == b->sshfp.fingerprint_size &&
memcmp(a->sshfp.fingerprint, b->sshfp.fingerprint, a->sshfp.fingerprint_size) == 0;
case DNS_TYPE_DNSKEY:
return a->dnskey.flags == b->dnskey.flags &&
a->dnskey.protocol == b->dnskey.protocol &&
a->dnskey.algorithm == b->dnskey.algorithm &&
a->dnskey.key_size == b->dnskey.key_size &&
memcmp(a->dnskey.key, b->dnskey.key, a->dnskey.key_size) == 0;
case DNS_TYPE_RRSIG:
/* do the fast comparisons first */
if (a->rrsig.type_covered != b->rrsig.type_covered ||
a->rrsig.algorithm != b->rrsig.algorithm ||
a->rrsig.labels != b->rrsig.labels ||
a->rrsig.original_ttl != b->rrsig.original_ttl ||
a->rrsig.expiration != b->rrsig.expiration ||
a->rrsig.inception != b->rrsig.inception ||
a->rrsig.key_tag != b->rrsig.key_tag ||
a->rrsig.signature_size != b->rrsig.signature_size ||
memcmp(a->rrsig.signature, b->rrsig.signature, a->rrsig.signature_size) != 0)
return false;
return dns_name_equal(a->rrsig.signer, b->rrsig.signer);
case DNS_TYPE_NSEC:
return dns_name_equal(a->nsec.next_domain_name, b->nsec.next_domain_name) &&
bitmap_equal(a->nsec.types, b->nsec.types);
case DNS_TYPE_NSEC3:
return a->nsec3.algorithm == b->nsec3.algorithm &&
a->nsec3.flags == b->nsec3.flags &&
a->nsec3.iterations == b->nsec3.iterations &&
a->nsec3.salt_size == b->nsec3.salt_size &&
memcmp(a->nsec3.salt, b->nsec3.salt, a->nsec3.salt_size) == 0 &&
memcmp(a->nsec3.next_hashed_name, b->nsec3.next_hashed_name, a->nsec3.next_hashed_name_size) == 0 &&
bitmap_equal(a->nsec3.types, b->nsec3.types);
default:
return a->generic.size == b->generic.size &&
memcmp(a->generic.data, b->generic.data, a->generic.size) == 0;
}
}
static char* format_location(uint32_t latitude, uint32_t longitude, uint32_t altitude,
uint8_t size, uint8_t horiz_pre, uint8_t vert_pre) {
char *s;
char NS = latitude >= 1U<<31 ? 'N' : 'S';
char EW = longitude >= 1U<<31 ? 'E' : 'W';
int lat = latitude >= 1U<<31 ? (int) (latitude - (1U<<31)) : (int) ((1U<<31) - latitude);
int lon = longitude >= 1U<<31 ? (int) (longitude - (1U<<31)) : (int) ((1U<<31) - longitude);
double alt = altitude >= 10000000u ? altitude - 10000000u : -(double)(10000000u - altitude);
double siz = (size >> 4) * exp10((double) (size & 0xF));
double hor = (horiz_pre >> 4) * exp10((double) (horiz_pre & 0xF));
double ver = (vert_pre >> 4) * exp10((double) (vert_pre & 0xF));
if (asprintf(&s, "%d %d %.3f %c %d %d %.3f %c %.2fm %.2fm %.2fm %.2fm",
(lat / 60000 / 60),
(lat / 60000) % 60,
(lat % 60000) / 1000.,
NS,
(lon / 60000 / 60),
(lon / 60000) % 60,
(lon % 60000) / 1000.,
EW,
alt / 100.,
siz / 100.,
hor / 100.,
ver / 100.) < 0)
return NULL;
return s;
}
static int format_timestamp_dns(char *buf, size_t l, time_t sec) {
struct tm tm;
assert(buf);
assert(l > strlen("YYYYMMDDHHmmSS"));
if (!gmtime_r(&sec, &tm))
return -EINVAL;
if (strftime(buf, l, "%Y%m%d%H%M%S", &tm) <= 0)
return -EINVAL;
return 0;
}
static char *format_types(Bitmap *types) {
_cleanup_strv_free_ char **strv = NULL;
_cleanup_free_ char *str = NULL;
Iterator i;
unsigned type;
int r;
BITMAP_FOREACH(type, types, i) {
if (dns_type_to_string(type)) {
r = strv_extend(&strv, dns_type_to_string(type));
if (r < 0)
return NULL;
} else {
char *t;
r = asprintf(&t, "TYPE%u", type);
if (r < 0)
return NULL;
r = strv_consume(&strv, t);
if (r < 0)
return NULL;
}
}
str = strv_join(strv, " ");
if (!str)
return NULL;
return strjoin("( ", str, " )", NULL);
}
static char *format_txt(DnsTxtItem *first) {
DnsTxtItem *i;
size_t c = 1;
char *p, *s;
LIST_FOREACH(items, i, first)
c += i->length * 4 + 3;
p = s = new(char, c);
if (!s)
return NULL;
LIST_FOREACH(items, i, first) {
size_t j;
if (i != first)
*(p++) = ' ';
*(p++) = '"';
for (j = 0; j < i->length; j++) {
if (i->data[j] < ' ' || i->data[j] == '"' || i->data[j] >= 127) {
*(p++) = '\\';
*(p++) = '0' + (i->data[j] / 100);
*(p++) = '0' + ((i->data[j] / 10) % 10);
*(p++) = '0' + (i->data[j] % 10);
} else
*(p++) = i->data[j];
}
*(p++) = '"';
}
*p = 0;
return s;
}
int dns_resource_record_to_string(const DnsResourceRecord *rr, char **ret) {
_cleanup_free_ char *k = NULL, *t = NULL;
char *s;
int r;
assert(rr);
r = dns_resource_key_to_string(rr->key, &k);
if (r < 0)
return r;
switch (rr->unparseable ? _DNS_TYPE_INVALID : rr->key->type) {
case DNS_TYPE_SRV:
r = asprintf(&s, "%s %u %u %u %s",
k,
rr->srv.priority,
rr->srv.weight,
rr->srv.port,
strna(rr->srv.name));
if (r < 0)
return -ENOMEM;
break;
case DNS_TYPE_PTR:
case DNS_TYPE_NS:
case DNS_TYPE_CNAME:
case DNS_TYPE_DNAME:
s = strjoin(k, " ", rr->ptr.name, NULL);
if (!s)
return -ENOMEM;
break;
case DNS_TYPE_HINFO:
s = strjoin(k, " ", rr->hinfo.cpu, " ", rr->hinfo.os, NULL);
if (!s)
return -ENOMEM;
break;
case DNS_TYPE_SPF: /* exactly the same as TXT */
case DNS_TYPE_TXT:
t = format_txt(rr->txt.items);
if (!t)
return -ENOMEM;
s = strjoin(k, " ", t, NULL);
if (!s)
return -ENOMEM;
break;
case DNS_TYPE_A: {
_cleanup_free_ char *x = NULL;
r = in_addr_to_string(AF_INET, (const union in_addr_union*) &rr->a.in_addr, &x);
if (r < 0)
return r;
s = strjoin(k, " ", x, NULL);
if (!s)
return -ENOMEM;
break;
}
case DNS_TYPE_AAAA:
r = in_addr_to_string(AF_INET6, (const union in_addr_union*) &rr->aaaa.in6_addr, &t);
if (r < 0)
return r;
s = strjoin(k, " ", t, NULL);
if (!s)
return -ENOMEM;
break;
case DNS_TYPE_SOA:
r = asprintf(&s, "%s %s %s %u %u %u %u %u",
k,
strna(rr->soa.mname),
strna(rr->soa.rname),
rr->soa.serial,
rr->soa.refresh,
rr->soa.retry,
rr->soa.expire,
rr->soa.minimum);
if (r < 0)
return -ENOMEM;
break;
case DNS_TYPE_MX:
r = asprintf(&s, "%s %u %s",
k,
rr->mx.priority,
rr->mx.exchange);
if (r < 0)
return -ENOMEM;
break;
case DNS_TYPE_LOC:
assert(rr->loc.version == 0);
t = format_location(rr->loc.latitude,
rr->loc.longitude,
rr->loc.altitude,
rr->loc.size,
rr->loc.horiz_pre,
rr->loc.vert_pre);
if (!t)
return -ENOMEM;
s = strjoin(k, " ", t, NULL);
if (!s)
return -ENOMEM;
break;
case DNS_TYPE_DS:
t = hexmem(rr->ds.digest, rr->ds.digest_size);
if (!t)
return -ENOMEM;
r = asprintf(&s, "%s %u %u %u %s",
k,
rr->ds.key_tag,
rr->ds.algorithm,
rr->ds.digest_type,
t);
if (r < 0)
return -ENOMEM;
break;
case DNS_TYPE_SSHFP:
t = hexmem(rr->sshfp.fingerprint, rr->sshfp.fingerprint_size);
if (!t)
return -ENOMEM;
r = asprintf(&s, "%s %u %u %s",
k,
rr->sshfp.algorithm,
rr->sshfp.fptype,
t);
if (r < 0)
return -ENOMEM;
break;
case DNS_TYPE_DNSKEY: {
const char *alg;
alg = dnssec_algorithm_to_string(rr->dnskey.algorithm);
t = base64mem(rr->dnskey.key, rr->dnskey.key_size);
if (!t)
return -ENOMEM;
r = asprintf(&s, "%s %u %u %.*s%.*u %s",
k,
rr->dnskey.flags,
rr->dnskey.protocol,
alg ? -1 : 0, alg,
alg ? 0 : 1, alg ? 0u : (unsigned) rr->dnskey.algorithm,
t);
if (r < 0)
return -ENOMEM;
break;
}
case DNS_TYPE_RRSIG: {
const char *type, *alg;
char expiration[strlen("YYYYMMDDHHmmSS") + 1], inception[strlen("YYYYMMDDHHmmSS") + 1];
type = dns_type_to_string(rr->rrsig.type_covered);
alg = dnssec_algorithm_to_string(rr->rrsig.algorithm);
t = base64mem(rr->rrsig.signature, rr->rrsig.signature_size);
if (!t)
return -ENOMEM;
r = format_timestamp_dns(expiration, sizeof(expiration), rr->rrsig.expiration);
if (r < 0)
return r;
r = format_timestamp_dns(inception, sizeof(inception), rr->rrsig.inception);
if (r < 0)
return r;
/* TYPE?? follows
* http://tools.ietf.org/html/rfc3597#section-5 */
r = asprintf(&s, "%s %s%.*u %.*s%.*u %u %u %s %s %u %s %s",
k,
type ?: "TYPE",
type ? 0 : 1, type ? 0u : (unsigned) rr->rrsig.type_covered,
alg ? -1 : 0, alg,
alg ? 0 : 1, alg ? 0u : (unsigned) rr->rrsig.algorithm,
rr->rrsig.labels,
rr->rrsig.original_ttl,
expiration,
inception,
rr->rrsig.key_tag,
rr->rrsig.signer,
t);
if (r < 0)
return -ENOMEM;
break;
}
case DNS_TYPE_NSEC:
t = format_types(rr->nsec.types);
if (!t)
return -ENOMEM;
r = asprintf(&s, "%s %s %s",
k,
rr->nsec.next_domain_name,
t);
if (r < 0)
return -ENOMEM;
break;
case DNS_TYPE_NSEC3: {
_cleanup_free_ char *salt = NULL, *hash = NULL;
if (rr->nsec3.salt_size > 0) {
salt = hexmem(rr->nsec3.salt, rr->nsec3.salt_size);
if (!salt)
return -ENOMEM;
}
hash = base32hexmem(rr->nsec3.next_hashed_name, rr->nsec3.next_hashed_name_size, false);
if (!hash)
return -ENOMEM;
t = format_types(rr->nsec3.types);
if (!t)
return -ENOMEM;
r = asprintf(&s, "%s %"PRIu8" %"PRIu8" %"PRIu16" %s %s %s",
k,
rr->nsec3.algorithm,
rr->nsec3.flags,
rr->nsec3.iterations,
rr->nsec3.salt_size > 0 ? salt : "-",
hash,
t);
if (r < 0)
return -ENOMEM;
break;
}
default:
t = hexmem(rr->generic.data, rr->generic.size);
if (!t)
return -ENOMEM;
r = asprintf(&s, "%s \\# %zu %s", k, rr->generic.size, t);
if (r < 0)
return -ENOMEM;
break;
}
*ret = s;
return 0;
}
int dns_resource_record_to_wire_format(DnsResourceRecord *rr, bool canonical) {
DnsPacket packet = {
.n_ref = 1,
.protocol = DNS_PROTOCOL_DNS,
.on_stack = true,
.refuse_compression = true,
.canonical_form = canonical,
};
size_t start, rds;
int r;
assert(rr);
/* Generates the RR in wire-format, optionally in the
* canonical form as discussed in the DNSSEC RFC 4034, Section
* 6.2. We allocate a throw-away DnsPacket object on the stack
* here, because we need some book-keeping for memory
* management, and can reuse the DnsPacket serializer, that
* can generate the canonical form, too, but also knows label
* compression and suchlike. */
if (rr->wire_format && rr->wire_format_canonical == canonical)
return 0;
r = dns_packet_append_rr(&packet, rr, &start, &rds);
if (r < 0)
return r;
assert(start == 0);
assert(packet._data);
free(rr->wire_format);
rr->wire_format = packet._data;
rr->wire_format_size = packet.size;
rr->wire_format_rdata_offset = rds;
rr->wire_format_canonical = canonical;
packet._data = NULL;
dns_packet_unref(&packet);
return 0;
}
DnsTxtItem *dns_txt_item_free_all(DnsTxtItem *i) {
DnsTxtItem *n;
if (!i)
return NULL;
n = i->items_next;
free(i);
return dns_txt_item_free_all(n);
}
bool dns_txt_item_equal(DnsTxtItem *a, DnsTxtItem *b) {
if (a == b)
return true;
if (!a != !b)
return false;
if (!a)
return true;
if (a->length != b->length)
return false;
if (memcmp(a->data, b->data, a->length) != 0)
return false;
return dns_txt_item_equal(a->items_next, b->items_next);
}
static const char* const dnssec_algorithm_table[_DNSSEC_ALGORITHM_MAX_DEFINED] = {
[DNSSEC_ALGORITHM_RSAMD5] = "RSAMD5",
[DNSSEC_ALGORITHM_DH] = "DH",
[DNSSEC_ALGORITHM_DSA] = "DSA",
[DNSSEC_ALGORITHM_ECC] = "ECC",
[DNSSEC_ALGORITHM_RSASHA1] = "RSASHA1",
[DNSSEC_ALGORITHM_DSA_NSEC3_SHA1] = "DSA-NSEC3-SHA1",
[DNSSEC_ALGORITHM_RSASHA1_NSEC3_SHA1] = "RSASHA1-NSEC3-SHA1",
[DNSSEC_ALGORITHM_RSASHA256] = "RSASHA256",
[DNSSEC_ALGORITHM_RSASHA512] = "RSASHA512",
[DNSSEC_ALGORITHM_INDIRECT] = "INDIRECT",
[DNSSEC_ALGORITHM_PRIVATEDNS] = "PRIVATEDNS",
[DNSSEC_ALGORITHM_PRIVATEOID] = "PRIVATEOID",
};
DEFINE_STRING_TABLE_LOOKUP(dnssec_algorithm, int);
static const char* const dnssec_digest_table[_DNSSEC_DIGEST_MAX_DEFINED] = {
[DNSSEC_DIGEST_SHA1] = "SHA1",
[DNSSEC_DIGEST_SHA256] = "SHA256",
};
DEFINE_STRING_TABLE_LOOKUP(dnssec_digest, int);