resolved-dns-rr.c revision ff3d6560bead6879a2fed1bf99bfe8273b3723f1
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering/***
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering This file is part of systemd.
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering Copyright 2014 Lennart Poettering
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering systemd is free software; you can redistribute it and/or modify it
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering under the terms of the GNU Lesser General Public License as published by
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering (at your option) any later version.
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering systemd is distributed in the hope that it will be useful, but
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering Lesser General Public License for more details.
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering You should have received a copy of the GNU Lesser General Public License
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering***/
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering
96cde13ace6406582688028f3df5668a172ba628Zbigniew Jędrzejewski-Szmek#include <math.h>
96cde13ace6406582688028f3df5668a172ba628Zbigniew Jędrzejewski-Szmek
96cde13ace6406582688028f3df5668a172ba628Zbigniew Jędrzejewski-Szmek#include "strv.h"
143bfdaf0b890fa7acadf02d1eafacaef1b696bdHolger Hans Peter Freyther
6482f6269c87d2249e52e889a63adbdd50f2d691Ronny Chevalier#include "resolved-dns-domain.h"
0b452006de98294d1690f045f6ea2f7f6630ec3bRonny Chevalier#include "resolved-dns-rr.h"
96cde13ace6406582688028f3df5668a172ba628Zbigniew Jędrzejewski-Szmek#include "resolved-dns-packet.h"
7027ff61a34a12487712b382a061c654acc3a679Lennart Poettering#include "dns-type.h"
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering
d4fffc4b8beb86e77fd710c1f43913a490ed083aZbigniew Jędrzejewski-SzmekDnsResourceKey* dns_resource_key_new(uint16_t class, uint16_t type, const char *name) {
96cde13ace6406582688028f3df5668a172ba628Zbigniew Jędrzejewski-Szmek DnsResourceKey *k;
d4fffc4b8beb86e77fd710c1f43913a490ed083aZbigniew Jędrzejewski-Szmek size_t l;
d4fffc4b8beb86e77fd710c1f43913a490ed083aZbigniew Jędrzejewski-Szmek
d4fffc4b8beb86e77fd710c1f43913a490ed083aZbigniew Jędrzejewski-Szmek assert(name);
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering l = strlen(name);
96cde13ace6406582688028f3df5668a172ba628Zbigniew Jędrzejewski-Szmek k = malloc0(sizeof(DnsResourceKey) + l + 1);
7027ff61a34a12487712b382a061c654acc3a679Lennart Poettering if (!k)
d7bd3de0654669e65b9642c248c5fa6d1d9a9f61Lennart Poettering return NULL;
d7bd3de0654669e65b9642c248c5fa6d1d9a9f61Lennart Poettering
d7bd3de0654669e65b9642c248c5fa6d1d9a9f61Lennart Poettering k->n_ref = 1;
cfeaa44a09756a93a881f786678973d9b1e382dbLennart Poettering k->class = class;
cfeaa44a09756a93a881f786678973d9b1e382dbLennart Poettering k->type = type;
7027ff61a34a12487712b382a061c654acc3a679Lennart Poettering
cfeaa44a09756a93a881f786678973d9b1e382dbLennart Poettering strcpy((char*) k + sizeof(DnsResourceKey), name);
cfeaa44a09756a93a881f786678973d9b1e382dbLennart Poettering
d7bd3de0654669e65b9642c248c5fa6d1d9a9f61Lennart Poettering return k;
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering}
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering
6c03089c32c251d823173bda4d809a9e643219f0Lennart PoetteringDnsResourceKey* dns_resource_key_new_consume(uint16_t class, uint16_t type, char *name) {
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering DnsResourceKey *k;
d4fffc4b8beb86e77fd710c1f43913a490ed083aZbigniew Jędrzejewski-Szmek
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering assert(name);
d4fffc4b8beb86e77fd710c1f43913a490ed083aZbigniew Jędrzejewski-Szmek
d4fffc4b8beb86e77fd710c1f43913a490ed083aZbigniew Jędrzejewski-Szmek k = new0(DnsResourceKey, 1);
d4fffc4b8beb86e77fd710c1f43913a490ed083aZbigniew Jędrzejewski-Szmek if (!k)
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering return NULL;
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering k->n_ref = 1;
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering k->class = class;
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering k->type = type;
d7bd3de0654669e65b9642c248c5fa6d1d9a9f61Lennart Poettering k->_name = name;
d7bd3de0654669e65b9642c248c5fa6d1d9a9f61Lennart Poettering
d7bd3de0654669e65b9642c248c5fa6d1d9a9f61Lennart Poettering return k;
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering}
cfeaa44a09756a93a881f786678973d9b1e382dbLennart Poettering
cfeaa44a09756a93a881f786678973d9b1e382dbLennart PoetteringDnsResourceKey* dns_resource_key_ref(DnsResourceKey *k) {
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering
d7bd3de0654669e65b9642c248c5fa6d1d9a9f61Lennart Poettering if (!k)
d4fffc4b8beb86e77fd710c1f43913a490ed083aZbigniew Jędrzejewski-Szmek return NULL;
cfeaa44a09756a93a881f786678973d9b1e382dbLennart Poettering
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering assert(k->n_ref > 0);
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering k->n_ref++;
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering return k;
d4fffc4b8beb86e77fd710c1f43913a490ed083aZbigniew Jędrzejewski-Szmek}
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering
d4fffc4b8beb86e77fd710c1f43913a490ed083aZbigniew Jędrzejewski-SzmekDnsResourceKey* dns_resource_key_unref(DnsResourceKey *k) {
d4fffc4b8beb86e77fd710c1f43913a490ed083aZbigniew Jędrzejewski-Szmek if (!k)
d4fffc4b8beb86e77fd710c1f43913a490ed083aZbigniew Jędrzejewski-Szmek return NULL;
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering assert(k->n_ref > 0);
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering if (k->n_ref == 1) {
374ec6abf31ada6ca554cc8ea99b282373fac010Lennart Poettering free(k->_name);
374ec6abf31ada6ca554cc8ea99b282373fac010Lennart Poettering free(k);
374ec6abf31ada6ca554cc8ea99b282373fac010Lennart Poettering } else
374ec6abf31ada6ca554cc8ea99b282373fac010Lennart Poettering k->n_ref--;
cfeaa44a09756a93a881f786678973d9b1e382dbLennart Poettering
d7bd3de0654669e65b9642c248c5fa6d1d9a9f61Lennart Poettering return NULL;
d7bd3de0654669e65b9642c248c5fa6d1d9a9f61Lennart Poettering}
d7bd3de0654669e65b9642c248c5fa6d1d9a9f61Lennart Poettering
cfeaa44a09756a93a881f786678973d9b1e382dbLennart Poetteringint dns_resource_key_equal(const DnsResourceKey *a, const DnsResourceKey *b) {
d7bd3de0654669e65b9642c248c5fa6d1d9a9f61Lennart Poettering int r;
d4fffc4b8beb86e77fd710c1f43913a490ed083aZbigniew Jędrzejewski-Szmek
320814811417146cfa1e416f69f1101eed630c36Luke Shumaker r = dns_name_equal(DNS_RESOURCE_KEY_NAME(a), DNS_RESOURCE_KEY_NAME(b));
cfeaa44a09756a93a881f786678973d9b1e382dbLennart Poettering if (r <= 0)
7027ff61a34a12487712b382a061c654acc3a679Lennart Poettering return r;
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering if (a->class != b->class)
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering return 0;
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering if (a->type != b->type)
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering return 0;
96cde13ace6406582688028f3df5668a172ba628Zbigniew Jędrzejewski-Szmek
96cde13ace6406582688028f3df5668a172ba628Zbigniew Jędrzejewski-Szmek return 1;
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering}
374ec6abf31ada6ca554cc8ea99b282373fac010Lennart Poettering
374ec6abf31ada6ca554cc8ea99b282373fac010Lennart Poetteringint dns_resource_key_match_rr(const DnsResourceKey *key, const DnsResourceRecord *rr) {
cfeaa44a09756a93a881f786678973d9b1e382dbLennart Poettering assert(key);
cfeaa44a09756a93a881f786678973d9b1e382dbLennart Poettering assert(rr);
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering
7027ff61a34a12487712b382a061c654acc3a679Lennart Poettering if (rr->key->class != key->class && key->class != DNS_CLASS_ANY)
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering return 0;
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering
7027ff61a34a12487712b382a061c654acc3a679Lennart Poettering if (rr->key->type != key->type && key->type != DNS_TYPE_ANY)
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering return 0;
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering return dns_name_equal(DNS_RESOURCE_KEY_NAME(rr->key), DNS_RESOURCE_KEY_NAME(key));
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering}
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering
374ec6abf31ada6ca554cc8ea99b282373fac010Lennart Poetteringint dns_resource_key_match_cname(const DnsResourceKey *key, const DnsResourceRecord *rr) {
374ec6abf31ada6ca554cc8ea99b282373fac010Lennart Poettering assert(key);
cfeaa44a09756a93a881f786678973d9b1e382dbLennart Poettering assert(rr);
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering
7027ff61a34a12487712b382a061c654acc3a679Lennart Poettering if (rr->key->class != key->class && key->class != DNS_CLASS_ANY)
8b0849e9710d721c5d0b775aaf0fd662eefa1449Lennart Poettering return 0;
8b0849e9710d721c5d0b775aaf0fd662eefa1449Lennart Poettering
8b0849e9710d721c5d0b775aaf0fd662eefa1449Lennart Poettering if (rr->key->type != DNS_TYPE_CNAME)
8b0849e9710d721c5d0b775aaf0fd662eefa1449Lennart Poettering return 0;
8b0849e9710d721c5d0b775aaf0fd662eefa1449Lennart Poettering
8b0849e9710d721c5d0b775aaf0fd662eefa1449Lennart Poettering return dns_name_equal(DNS_RESOURCE_KEY_NAME(rr->key), DNS_RESOURCE_KEY_NAME(key));
8b0849e9710d721c5d0b775aaf0fd662eefa1449Lennart Poettering}
8b0849e9710d721c5d0b775aaf0fd662eefa1449Lennart Poettering
8b0849e9710d721c5d0b775aaf0fd662eefa1449Lennart Poetteringunsigned long dns_resource_key_hash_func(const void *i, const uint8_t hash_key[HASH_KEY_SIZE]) {
8b0849e9710d721c5d0b775aaf0fd662eefa1449Lennart Poettering const DnsResourceKey *k = i;
8b0849e9710d721c5d0b775aaf0fd662eefa1449Lennart Poettering unsigned long ul;
8b0849e9710d721c5d0b775aaf0fd662eefa1449Lennart Poettering
8b0849e9710d721c5d0b775aaf0fd662eefa1449Lennart Poettering ul = dns_name_hash_func(DNS_RESOURCE_KEY_NAME(k), hash_key);
8b0849e9710d721c5d0b775aaf0fd662eefa1449Lennart Poettering ul = ul * hash_key[0] + ul + k->class;
8b0849e9710d721c5d0b775aaf0fd662eefa1449Lennart Poettering ul = ul * hash_key[1] + ul + k->type;
8b0849e9710d721c5d0b775aaf0fd662eefa1449Lennart Poettering
8b0849e9710d721c5d0b775aaf0fd662eefa1449Lennart Poettering return ul;
329ac4bc5429cd86c4ac76b13e7e2784f3982760Lennart Poettering}
329ac4bc5429cd86c4ac76b13e7e2784f3982760Lennart Poettering
329ac4bc5429cd86c4ac76b13e7e2784f3982760Lennart Poetteringint dns_resource_key_compare_func(const void *a, const void *b) {
329ac4bc5429cd86c4ac76b13e7e2784f3982760Lennart Poettering const DnsResourceKey *x = a, *y = b;
329ac4bc5429cd86c4ac76b13e7e2784f3982760Lennart Poettering int ret;
329ac4bc5429cd86c4ac76b13e7e2784f3982760Lennart Poettering
329ac4bc5429cd86c4ac76b13e7e2784f3982760Lennart Poettering ret = dns_name_compare_func(DNS_RESOURCE_KEY_NAME(x), DNS_RESOURCE_KEY_NAME(y));
329ac4bc5429cd86c4ac76b13e7e2784f3982760Lennart Poettering if (ret != 0)
329ac4bc5429cd86c4ac76b13e7e2784f3982760Lennart Poettering return ret;
329ac4bc5429cd86c4ac76b13e7e2784f3982760Lennart Poettering
329ac4bc5429cd86c4ac76b13e7e2784f3982760Lennart Poettering if (x->type < y->type)
329ac4bc5429cd86c4ac76b13e7e2784f3982760Lennart Poettering return -1;
329ac4bc5429cd86c4ac76b13e7e2784f3982760Lennart Poettering if (x->type > y->type)
329ac4bc5429cd86c4ac76b13e7e2784f3982760Lennart Poettering return 1;
329ac4bc5429cd86c4ac76b13e7e2784f3982760Lennart Poettering
329ac4bc5429cd86c4ac76b13e7e2784f3982760Lennart Poettering if (x->class < y->class)
329ac4bc5429cd86c4ac76b13e7e2784f3982760Lennart Poettering return -1;
329ac4bc5429cd86c4ac76b13e7e2784f3982760Lennart Poettering if (x->class > y->class)
329ac4bc5429cd86c4ac76b13e7e2784f3982760Lennart Poettering return 1;
329ac4bc5429cd86c4ac76b13e7e2784f3982760Lennart Poettering
329ac4bc5429cd86c4ac76b13e7e2784f3982760Lennart Poettering return 0;
329ac4bc5429cd86c4ac76b13e7e2784f3982760Lennart Poettering}
329ac4bc5429cd86c4ac76b13e7e2784f3982760Lennart Poettering
329ac4bc5429cd86c4ac76b13e7e2784f3982760Lennart Poetteringint dns_resource_key_to_string(const DnsResourceKey *key, char **ret) {
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering char cbuf[DECIMAL_STR_MAX(uint16_t)], tbuf[DECIMAL_STR_MAX(uint16_t)];
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering const char *c, *t;
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering char *s;
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering c = dns_class_to_string(key->class);
7027ff61a34a12487712b382a061c654acc3a679Lennart Poettering if (!c) {
7027ff61a34a12487712b382a061c654acc3a679Lennart Poettering sprintf(cbuf, "%i", key->class);
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering c = cbuf;
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering }
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering t = dns_type_to_string(key->type);
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering if (!t){
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering sprintf(tbuf, "%i", key->type);
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering t = tbuf;
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering }
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering
e9174f29c7e3ee45137537b126458718913a3ec5Lennart Poettering if (asprintf(&s, "%s %s %-5s", DNS_RESOURCE_KEY_NAME(key), c, t) < 0)
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering return -ENOMEM;
fed1e721fd0c81e60c77120539f34e16c2585634Lennart Poettering
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering *ret = s;
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering return 0;
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering}
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering
aff38e74bd776471f15ba54b305a24b0251eb865Lennart PoetteringDnsResourceRecord* dns_resource_record_new(DnsResourceKey *key) {
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering DnsResourceRecord *rr;
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering rr = new0(DnsResourceRecord, 1);
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering if (!rr)
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poettering return NULL;
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poettering
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poettering rr->n_ref = 1;
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering rr->key = dns_resource_key_ref(key);
e9174f29c7e3ee45137537b126458718913a3ec5Lennart Poettering
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poettering return rr;
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering}
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering
aff38e74bd776471f15ba54b305a24b0251eb865Lennart PoetteringDnsResourceRecord* dns_resource_record_new_full(uint16_t class, uint16_t type, const char *name) {
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
1021b21bc6f8dd522b46116e8598b17f9f93f1b7Lennart Poettering
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering key = dns_resource_key_new(class, type, name);
de0671ee7fe465e108f62dcbbbe9366f81dd9e9aZbigniew Jędrzejewski-Szmek if (!key)
de0671ee7fe465e108f62dcbbbe9366f81dd9e9aZbigniew Jędrzejewski-Szmek return NULL;
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering return dns_resource_record_new(key);
de0671ee7fe465e108f62dcbbbe9366f81dd9e9aZbigniew Jędrzejewski-Szmek}
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering
aff38e74bd776471f15ba54b305a24b0251eb865Lennart PoetteringDnsResourceRecord* dns_resource_record_ref(DnsResourceRecord *rr) {
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering if (!rr)
1021b21bc6f8dd522b46116e8598b17f9f93f1b7Lennart Poettering return NULL;
1021b21bc6f8dd522b46116e8598b17f9f93f1b7Lennart Poettering
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering assert(rr->n_ref > 0);
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering rr->n_ref++;
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poettering return rr;
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poettering}
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poettering
ae018d9bc900d6355dea4af05119b49c67945184Lennart PoetteringDnsResourceRecord* dns_resource_record_unref(DnsResourceRecord *rr) {
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poettering if (!rr)
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poettering return NULL;
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poettering
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poettering assert(rr->n_ref > 0);
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poettering
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poettering if (rr->n_ref > 1) {
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poettering rr->n_ref--;
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poettering return NULL;
a0ab566574303be1ca12cdb334f284cfd407caa5Lennart Poettering }
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poettering
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poettering if (rr->key) {
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poettering switch(rr->key->type) {
e13bb5d2b133f9ae51c0a2d20aa51071c780e9aeKay Sievers
e13bb5d2b133f9ae51c0a2d20aa51071c780e9aeKay Sievers case DNS_TYPE_SRV:
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poettering free(rr->srv.name);
a0ab566574303be1ca12cdb334f284cfd407caa5Lennart Poettering break;
a0ab566574303be1ca12cdb334f284cfd407caa5Lennart Poettering
a0ab566574303be1ca12cdb334f284cfd407caa5Lennart Poettering case DNS_TYPE_PTR:
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poettering case DNS_TYPE_NS:
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poettering case DNS_TYPE_CNAME:
78edb35ab4f4227485cb9ec816b43c37e0d5e62aLennart Poettering case DNS_TYPE_DNAME:
185a08745957cbd32e8293daf8c51ab9c995a71eDimitri John Ledkov free(rr->ptr.name);
185a08745957cbd32e8293daf8c51ab9c995a71eDimitri John Ledkov break;
185a08745957cbd32e8293daf8c51ab9c995a71eDimitri John Ledkov
185a08745957cbd32e8293daf8c51ab9c995a71eDimitri John Ledkov case DNS_TYPE_HINFO:
185a08745957cbd32e8293daf8c51ab9c995a71eDimitri John Ledkov free(rr->hinfo.cpu);
185a08745957cbd32e8293daf8c51ab9c995a71eDimitri John Ledkov free(rr->hinfo.os);
185a08745957cbd32e8293daf8c51ab9c995a71eDimitri John Ledkov break;
185a08745957cbd32e8293daf8c51ab9c995a71eDimitri John Ledkov
185a08745957cbd32e8293daf8c51ab9c995a71eDimitri John Ledkov case DNS_TYPE_TXT:
185a08745957cbd32e8293daf8c51ab9c995a71eDimitri John Ledkov case DNS_TYPE_SPF:
78edb35ab4f4227485cb9ec816b43c37e0d5e62aLennart Poettering strv_free(rr->txt.strings);
78edb35ab4f4227485cb9ec816b43c37e0d5e62aLennart Poettering break;
a016b9228f338cb9b380ce7e00826ef462767d98Lennart Poettering
a016b9228f338cb9b380ce7e00826ef462767d98Lennart Poettering case DNS_TYPE_SOA:
a016b9228f338cb9b380ce7e00826ef462767d98Lennart Poettering free(rr->soa.mname);
a016b9228f338cb9b380ce7e00826ef462767d98Lennart Poettering free(rr->soa.rname);
a016b9228f338cb9b380ce7e00826ef462767d98Lennart Poettering break;
a016b9228f338cb9b380ce7e00826ef462767d98Lennart Poettering
a016b9228f338cb9b380ce7e00826ef462767d98Lennart Poettering case DNS_TYPE_MX:
a016b9228f338cb9b380ce7e00826ef462767d98Lennart Poettering free(rr->mx.exchange);
a016b9228f338cb9b380ce7e00826ef462767d98Lennart Poettering break;
a016b9228f338cb9b380ce7e00826ef462767d98Lennart Poettering
a016b9228f338cb9b380ce7e00826ef462767d98Lennart Poettering case DNS_TYPE_SSHFP:
a016b9228f338cb9b380ce7e00826ef462767d98Lennart Poettering free(rr->sshfp.key);
c96cc5822c165e86be78ed96dac6573986032fabLennart Poettering break;
c96cc5822c165e86be78ed96dac6573986032fabLennart Poettering
c96cc5822c165e86be78ed96dac6573986032fabLennart Poettering case DNS_TYPE_DNSKEY:
a016b9228f338cb9b380ce7e00826ef462767d98Lennart Poettering free(rr->dnskey.key);
a016b9228f338cb9b380ce7e00826ef462767d98Lennart Poettering break;
c96cc5822c165e86be78ed96dac6573986032fabLennart Poettering
e66e5b612a9e5921d79a6aedab4983e33dff8cb1Lennart Poettering case DNS_TYPE_LOC:
c96cc5822c165e86be78ed96dac6573986032fabLennart Poettering case DNS_TYPE_A:
a016b9228f338cb9b380ce7e00826ef462767d98Lennart Poettering case DNS_TYPE_AAAA:
a016b9228f338cb9b380ce7e00826ef462767d98Lennart Poettering break;
a016b9228f338cb9b380ce7e00826ef462767d98Lennart Poettering
a016b9228f338cb9b380ce7e00826ef462767d98Lennart Poettering default:
751bc6ac79320bc16e63e8c1bbb713c30a3b7bc9Lennart Poettering free(rr->generic.data);
751bc6ac79320bc16e63e8c1bbb713c30a3b7bc9Lennart Poettering }
751bc6ac79320bc16e63e8c1bbb713c30a3b7bc9Lennart Poettering
751bc6ac79320bc16e63e8c1bbb713c30a3b7bc9Lennart Poettering dns_resource_key_unref(rr->key);
751bc6ac79320bc16e63e8c1bbb713c30a3b7bc9Lennart Poettering }
751bc6ac79320bc16e63e8c1bbb713c30a3b7bc9Lennart Poettering
751bc6ac79320bc16e63e8c1bbb713c30a3b7bc9Lennart Poettering free(rr);
751bc6ac79320bc16e63e8c1bbb713c30a3b7bc9Lennart Poettering
751bc6ac79320bc16e63e8c1bbb713c30a3b7bc9Lennart Poettering return NULL;
751bc6ac79320bc16e63e8c1bbb713c30a3b7bc9Lennart Poettering}
751bc6ac79320bc16e63e8c1bbb713c30a3b7bc9Lennart Poettering
751bc6ac79320bc16e63e8c1bbb713c30a3b7bc9Lennart Poetteringint dns_resource_record_new_reverse(DnsResourceRecord **ret, int family, const union in_addr_union *address, const char *hostname) {
751bc6ac79320bc16e63e8c1bbb713c30a3b7bc9Lennart Poettering _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
751bc6ac79320bc16e63e8c1bbb713c30a3b7bc9Lennart Poettering _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
751bc6ac79320bc16e63e8c1bbb713c30a3b7bc9Lennart Poettering _cleanup_free_ char *ptr = NULL;
5f4c5fef66581383ee852b301db67f687663004cLennart Poettering int r;
5f4c5fef66581383ee852b301db67f687663004cLennart Poettering
5f4c5fef66581383ee852b301db67f687663004cLennart Poettering assert(ret);
5f4c5fef66581383ee852b301db67f687663004cLennart Poettering assert(address);
5f4c5fef66581383ee852b301db67f687663004cLennart Poettering assert(hostname);
5f4c5fef66581383ee852b301db67f687663004cLennart Poettering
5f4c5fef66581383ee852b301db67f687663004cLennart Poettering r = dns_name_reverse(family, address, &ptr);
5f4c5fef66581383ee852b301db67f687663004cLennart Poettering if (r < 0)
5f4c5fef66581383ee852b301db67f687663004cLennart Poettering return r;
5f4c5fef66581383ee852b301db67f687663004cLennart Poettering
5f4c5fef66581383ee852b301db67f687663004cLennart Poettering key = dns_resource_key_new_consume(DNS_CLASS_IN, DNS_TYPE_PTR, ptr);
96cde13ace6406582688028f3df5668a172ba628Zbigniew Jędrzejewski-Szmek if (!key)
7027ff61a34a12487712b382a061c654acc3a679Lennart Poettering return -ENOMEM;
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering
7027ff61a34a12487712b382a061c654acc3a679Lennart Poettering ptr = NULL;
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering rr = dns_resource_record_new(key);
8b0849e9710d721c5d0b775aaf0fd662eefa1449Lennart Poettering if (!rr)
329ac4bc5429cd86c4ac76b13e7e2784f3982760Lennart Poettering return -ENOMEM;
143bfdaf0b890fa7acadf02d1eafacaef1b696bdHolger Hans Peter Freyther
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering rr->ptr.name = strdup(hostname);
143bfdaf0b890fa7acadf02d1eafacaef1b696bdHolger Hans Peter Freyther if (!rr->ptr.name)
78edb35ab4f4227485cb9ec816b43c37e0d5e62aLennart Poettering return -ENOMEM;
a016b9228f338cb9b380ce7e00826ef462767d98Lennart Poettering
751bc6ac79320bc16e63e8c1bbb713c30a3b7bc9Lennart Poettering *ret = rr;
5f4c5fef66581383ee852b301db67f687663004cLennart Poettering rr = NULL;
96cde13ace6406582688028f3df5668a172ba628Zbigniew Jędrzejewski-Szmek
96cde13ace6406582688028f3df5668a172ba628Zbigniew Jędrzejewski-Szmek return 0;
96cde13ace6406582688028f3df5668a172ba628Zbigniew Jędrzejewski-Szmek}
int dns_resource_record_equal(const DnsResourceRecord *a, const DnsResourceRecord *b) {
int r;
assert(a);
assert(b);
r = dns_resource_key_equal(a->key, b->key);
if (r <= 0)
return r;
if (a->unparseable != b->unparseable)
return 0;
switch (a->unparseable ? _DNS_TYPE_INVALID : a->key->type) {
case DNS_TYPE_SRV:
r = dns_name_equal(a->srv.name, b->srv.name);
if (r <= 0)
return r;
return a->srv.priority == b->srv.priority &&
a->srv.weight == b->srv.weight &&
a->srv.port == b->srv.port;
case DNS_TYPE_PTR:
case DNS_TYPE_NS:
case DNS_TYPE_CNAME:
case DNS_TYPE_DNAME:
return dns_name_equal(a->ptr.name, b->ptr.name);
case DNS_TYPE_HINFO:
return strcaseeq(a->hinfo.cpu, b->hinfo.cpu) &&
strcaseeq(a->hinfo.os, b->hinfo.os);
case DNS_TYPE_SPF: /* exactly the same as TXT */
case DNS_TYPE_TXT: {
int i;
for (i = 0; a->txt.strings[i] || b->txt.strings[i]; i++)
if (!streq_ptr(a->txt.strings[i], b->txt.strings[i]))
return false;
return true;
}
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_SSHFP:
return a->sshfp.algorithm == b->sshfp.algorithm &&
a->sshfp.fptype == b->sshfp.fptype &&
a->sshfp.key_size == b->sshfp.key_size &&
memcmp(a->sshfp.key, b->sshfp.key, a->sshfp.key_size) == 0;
case DNS_TYPE_DNSKEY:
return a->dnskey.zone_key_flag == b->dnskey.zone_key_flag &&
a->dnskey.sep_flag == b->dnskey.sep_flag &&
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;
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;
}
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 = strv_join_quoted(rr->txt.strings);
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_SSHFP:
t = hexmem(rr->sshfp.key, rr->sshfp.key_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 = hexmem(rr->dnskey.key, rr->dnskey.key_size);
if (!t)
return -ENOMEM;
r = asprintf(&s, "%s %u 3 %.*s%.*u %s",
k,
dnskey_to_flags(rr),
alg ? -1 : 0, alg,
alg ? 0 : 1, alg ? 0u : (unsigned) rr->dnskey.algorithm,
t);
if (r < 0)
return -ENOMEM;
break;
}
default:
t = hexmem(rr->generic.data, rr->generic.size);
if (!t)
return -ENOMEM;
s = strjoin(k, " ", t, NULL);
if (!s)
return -ENOMEM;
break;
}
*ret = s;
return 0;
}
const char *dns_class_to_string(uint16_t class) {
switch (class) {
case DNS_CLASS_IN:
return "IN";
case DNS_CLASS_ANY:
return "ANY";
}
return NULL;
}
int dns_class_from_string(const char *s, uint16_t *class) {
assert(s);
assert(class);
if (strcaseeq(s, "IN"))
*class = DNS_CLASS_IN;
else if (strcaseeq(s, "ANY"))
*class = DNS_TYPE_ANY;
else
return -EINVAL;
return 0;
}