resolved-dns-rr.c revision 7c6423e19136a7b7b6ef3fe06b94822e582dda27
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen/***
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen This file is part of systemd.
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen Copyright 2014 Lennart Poettering
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen systemd is free software; you can redistribute it and/or modify it
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen under the terms of the GNU Lesser General Public License as published by
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen the Free Software Foundation; either version 2.1 of the License, or
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen (at your option) any later version.
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen systemd is distributed in the hope that it will be useful, but
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen WITHOUT ANY WARRANTY; without even the implied warranty of
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen Lesser General Public License for more details.
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen You should have received a copy of the GNU Lesser General Public License
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen along with systemd; If not, see <http://www.gnu.org/licenses/>.
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen***/
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
43b3a5ef61859f06cdbaf26765cab8e1adac4296Tom Gundersen#include <math.h>
7eb08da4b388b920c8a894b1500c9cc7dc1f31efTom Gundersen
43b3a5ef61859f06cdbaf26765cab8e1adac4296Tom Gundersen#include "strv.h"
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen#include "dns-domain.h"
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include "resolved-dns-rr.h"
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include "resolved-dns-packet.h"
a501033335ed402c8f7e86fe41a15531ba69abd7Tom Gundersen#include "dns-type.h"
43b3a5ef61859f06cdbaf26765cab8e1adac4296Tom Gundersen
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart PoetteringDnsResourceKey* dns_resource_key_new(uint16_t class, uint16_t type, const char *name) {
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen DnsResourceKey *k;
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering size_t l;
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen
c6f7c917a1b494d4455800823472227463f87438Tom Gundersen assert(name);
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering
3df3e884ae1237ef0d4d23b0e80f4ffda95ac135Ronny Chevalier l = strlen(name);
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering k = malloc0(sizeof(DnsResourceKey) + l + 1);
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering if (!k)
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering return NULL;
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen k->n_ref = 1;
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen k->class = class;
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen k->type = type;
a501033335ed402c8f7e86fe41a15531ba69abd7Tom Gundersen
a501033335ed402c8f7e86fe41a15531ba69abd7Tom Gundersen strcpy((char*) k + sizeof(DnsResourceKey), name);
f61942250a43a123580d7bbe5d7873dc5118ed97Tom Gundersen
f61942250a43a123580d7bbe5d7873dc5118ed97Tom Gundersen return k;
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen}
43b3a5ef61859f06cdbaf26765cab8e1adac4296Tom Gundersen
97f2d76d4f4dfab8b0629c09926a05a1e5621125Tom GundersenDnsResourceKey* dns_resource_key_new_consume(uint16_t class, uint16_t type, char *name) {
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen DnsResourceKey *k;
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
2ad8416dd057e7e3185169609ca3006e7649f576Zbigniew Jędrzejewski-Szmek assert(name);
2ad8416dd057e7e3185169609ca3006e7649f576Zbigniew Jędrzejewski-Szmek
2ad8416dd057e7e3185169609ca3006e7649f576Zbigniew Jędrzejewski-Szmek k = new0(DnsResourceKey, 1);
2ad8416dd057e7e3185169609ca3006e7649f576Zbigniew Jędrzejewski-Szmek if (!k)
2ad8416dd057e7e3185169609ca3006e7649f576Zbigniew Jędrzejewski-Szmek return NULL;
2ad8416dd057e7e3185169609ca3006e7649f576Zbigniew Jędrzejewski-Szmek
2ad8416dd057e7e3185169609ca3006e7649f576Zbigniew Jędrzejewski-Szmek k->n_ref = 1;
2ad8416dd057e7e3185169609ca3006e7649f576Zbigniew Jędrzejewski-Szmek k->class = class;
2ad8416dd057e7e3185169609ca3006e7649f576Zbigniew Jędrzejewski-Szmek k->type = type;
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen k->_name = name;
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen return k;
5b9d4dc05560ddda89e48b6b39365824b15e1300Tom Gundersen}
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen
9a4b012e43f23516373bf398dd9a458439d19939Tom GundersenDnsResourceKey* dns_resource_key_ref(DnsResourceKey *k) {
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen
43d60b77a83b3185e37c65c4f2649d24c227c7f0Tom Gundersen if (!k)
43d60b77a83b3185e37c65c4f2649d24c227c7f0Tom Gundersen return NULL;
43d60b77a83b3185e37c65c4f2649d24c227c7f0Tom Gundersen
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen assert(k->n_ref > 0);
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen k->n_ref++;
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen return k;
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen}
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen
9a4b012e43f23516373bf398dd9a458439d19939Tom GundersenDnsResourceKey* dns_resource_key_unref(DnsResourceKey *k) {
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen if (!k)
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen return NULL;
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen assert(k->n_ref > 0);
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen if (k->n_ref == 1) {
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen free(k->_name);
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen free(k);
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen } else
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen k->n_ref--;
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen return NULL;
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen}
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersenint dns_resource_key_equal(const DnsResourceKey *a, const DnsResourceKey *b) {
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen int r;
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen r = dns_name_equal(DNS_RESOURCE_KEY_NAME(a), DNS_RESOURCE_KEY_NAME(b));
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen if (r <= 0)
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen return r;
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen if (a->class != b->class)
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen return 0;
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
03e334a1c7dc8c20c38902aa039440763acc9b17Lennart Poettering if (a->type != b->type)
43b3a5ef61859f06cdbaf26765cab8e1adac4296Tom Gundersen return 0;
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen
43b3a5ef61859f06cdbaf26765cab8e1adac4296Tom Gundersen return 1;
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen}
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersenint dns_resource_key_match_rr(const DnsResourceKey *key, const DnsResourceRecord *rr) {
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen assert(key);
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen assert(rr);
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen if (rr->key->class != key->class && key->class != DNS_CLASS_ANY)
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen return 0;
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen if (rr->key->type != key->type && key->type != DNS_TYPE_ANY)
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen return 0;
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen return dns_name_equal(DNS_RESOURCE_KEY_NAME(rr->key), DNS_RESOURCE_KEY_NAME(key));
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen}
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersenint dns_resource_key_match_cname(const DnsResourceKey *key, const DnsResourceRecord *rr) {
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen assert(key);
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen assert(rr);
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen if (rr->key->class != key->class && key->class != DNS_CLASS_ANY)
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen return 0;
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen if (rr->key->type != DNS_TYPE_CNAME)
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen return 0;
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen return dns_name_equal(DNS_RESOURCE_KEY_NAME(rr->key), DNS_RESOURCE_KEY_NAME(key));
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen}
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersenstatic unsigned long dns_resource_key_hash_func(const void *i, const uint8_t hash_key[HASH_KEY_SIZE]) {
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen const DnsResourceKey *k = i;
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen unsigned long ul;
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen ul = dns_name_hash_func(DNS_RESOURCE_KEY_NAME(k), hash_key);
6e37cd2f4af8928d905203108a4331e375d7127cThomas Hindoe Paaboel Andersen ul = ul * hash_key[0] + ul + k->class;
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen ul = ul * hash_key[1] + ul + k->type;
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
187dc6e554f2d5b4b5a3bee72c73ff5df6418aa6Thomas Hindoe Paaboel Andersen return ul;
187dc6e554f2d5b4b5a3bee72c73ff5df6418aa6Thomas Hindoe Paaboel Andersen}
187dc6e554f2d5b4b5a3bee72c73ff5df6418aa6Thomas Hindoe Paaboel Andersen
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersenstatic int dns_resource_key_compare_func(const void *a, const void *b) {
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen const DnsResourceKey *x = a, *y = b;
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen int ret;
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen ret = dns_name_compare_func(DNS_RESOURCE_KEY_NAME(x), DNS_RESOURCE_KEY_NAME(y));
ecb08ec6a5c52f2d940f3b8147e2a480affd46e1Zbigniew Jędrzejewski-Szmek if (ret != 0)
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen return ret;
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
ed88bcfb7c15029f9fc95ee2380759a9eb782d46Zbigniew Jędrzejewski-Szmek if (x->type < y->type)
ed88bcfb7c15029f9fc95ee2380759a9eb782d46Zbigniew Jędrzejewski-Szmek return -1;
ed88bcfb7c15029f9fc95ee2380759a9eb782d46Zbigniew Jędrzejewski-Szmek if (x->type > y->type)
ed88bcfb7c15029f9fc95ee2380759a9eb782d46Zbigniew Jędrzejewski-Szmek return 1;
ed88bcfb7c15029f9fc95ee2380759a9eb782d46Zbigniew Jędrzejewski-Szmek
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen if (x->class < y->class)
ecb08ec6a5c52f2d940f3b8147e2a480affd46e1Zbigniew Jędrzejewski-Szmek return -1;
ecb08ec6a5c52f2d940f3b8147e2a480affd46e1Zbigniew Jędrzejewski-Szmek if (x->class > y->class)
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen return 1;
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen return 0;
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen}
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen
e9f3d2d508bfd9fb5b54e82994bda365a71eb864Zbigniew Jędrzejewski-Szmekconst struct hash_ops dns_resource_key_hash_ops = {
e9f3d2d508bfd9fb5b54e82994bda365a71eb864Zbigniew Jędrzejewski-Szmek .hash = dns_resource_key_hash_func,
e9f3d2d508bfd9fb5b54e82994bda365a71eb864Zbigniew Jędrzejewski-Szmek .compare = dns_resource_key_compare_func
36f822c4bd077f9121757e24b6516e5c7ada63b5Zbigniew Jędrzejewski-Szmek};
36f822c4bd077f9121757e24b6516e5c7ada63b5Zbigniew Jędrzejewski-Szmek
ecb08ec6a5c52f2d940f3b8147e2a480affd46e1Zbigniew Jędrzejewski-Szmekint dns_resource_key_to_string(const DnsResourceKey *key, char **ret) {
36f822c4bd077f9121757e24b6516e5c7ada63b5Zbigniew Jędrzejewski-Szmek char cbuf[DECIMAL_STR_MAX(uint16_t)], tbuf[DECIMAL_STR_MAX(uint16_t)];
98a375f6d5cac24eb80d6d4e00699851324afdecTom Gundersen const char *c, *t;
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen char *s;
dab495dc23bf9a5ba0487a057bb594355555a0e9Tom Gundersen
dab495dc23bf9a5ba0487a057bb594355555a0e9Tom Gundersen c = dns_class_to_string(key->class);
dab495dc23bf9a5ba0487a057bb594355555a0e9Tom Gundersen if (!c) {
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen sprintf(cbuf, "%i", key->class);
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen c = cbuf;
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen }
ecb08ec6a5c52f2d940f3b8147e2a480affd46e1Zbigniew Jędrzejewski-Szmek
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen t = dns_type_to_string(key->type);
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen if (!t){
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen sprintf(tbuf, "%i", key->type);
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen t = tbuf;
f61942250a43a123580d7bbe5d7873dc5118ed97Tom Gundersen }
f8a0bb5285024b6ce372c3157e761e6543ebdcd2Andreas Henriksson
a2a5291b3f5ab6ed4c92f51d0fd10a03047380d8Zbigniew Jędrzejewski-Szmek if (asprintf(&s, "%s %s %-5s", DNS_RESOURCE_KEY_NAME(key), c, t) < 0)
f61942250a43a123580d7bbe5d7873dc5118ed97Tom Gundersen return -ENOMEM;
f61942250a43a123580d7bbe5d7873dc5118ed97Tom Gundersen
f61942250a43a123580d7bbe5d7873dc5118ed97Tom Gundersen *ret = s;
74df0fca09b3c31ed19e14ba80f996fdff772417Lennart Poettering return 0;
b5884878a2874447b2a9f07f324a7cd909d96d48Lennart Poettering}
da927ba997d68401563b927f92e6e40e021a8e5cMichal Schmidt
74df0fca09b3c31ed19e14ba80f996fdff772417Lennart PoetteringDnsResourceRecord* dns_resource_record_new(DnsResourceKey *key) {
b5884878a2874447b2a9f07f324a7cd909d96d48Lennart Poettering DnsResourceRecord *rr;
f61942250a43a123580d7bbe5d7873dc5118ed97Tom Gundersen
a2a5291b3f5ab6ed4c92f51d0fd10a03047380d8Zbigniew Jędrzejewski-Szmek rr = new0(DnsResourceRecord, 1);
a2a5291b3f5ab6ed4c92f51d0fd10a03047380d8Zbigniew Jędrzejewski-Szmek if (!rr)
f61942250a43a123580d7bbe5d7873dc5118ed97Tom Gundersen return NULL;
f61942250a43a123580d7bbe5d7873dc5118ed97Tom Gundersen
f61942250a43a123580d7bbe5d7873dc5118ed97Tom Gundersen rr->n_ref = 1;
f61942250a43a123580d7bbe5d7873dc5118ed97Tom Gundersen rr->key = dns_resource_key_ref(key);
f61942250a43a123580d7bbe5d7873dc5118ed97Tom Gundersen
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen return rr;
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen}
edf029b7fd9a5853a87d3ca99aac2922bb8a277eTom Gundersen
edf029b7fd9a5853a87d3ca99aac2922bb8a277eTom GundersenDnsResourceRecord* dns_resource_record_new_full(uint16_t class, uint16_t type, const char *name) {
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen key = dns_resource_key_new(class, type, name);
f61942250a43a123580d7bbe5d7873dc5118ed97Tom Gundersen if (!key)
f61942250a43a123580d7bbe5d7873dc5118ed97Tom Gundersen return NULL;
3f85ef0f05ffc51e19f86fb83a1c51e8e3cd6817Harald Hoyer
f61942250a43a123580d7bbe5d7873dc5118ed97Tom Gundersen return dns_resource_record_new(key);
f61942250a43a123580d7bbe5d7873dc5118ed97Tom Gundersen}
97f2d76d4f4dfab8b0629c09926a05a1e5621125Tom Gundersen
2ad8416dd057e7e3185169609ca3006e7649f576Zbigniew Jędrzejewski-SzmekDnsResourceRecord* dns_resource_record_ref(DnsResourceRecord *rr) {
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen if (!rr)
2ad8416dd057e7e3185169609ca3006e7649f576Zbigniew Jędrzejewski-Szmek return NULL;
f647962d64e844689f3e2acfce6102fc47e76df2Michal Schmidt
f647962d64e844689f3e2acfce6102fc47e76df2Michal Schmidt assert(rr->n_ref > 0);
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen rr->n_ref++;
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen return rr;
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen}
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom GundersenDnsResourceRecord* dns_resource_record_unref(DnsResourceRecord *rr) {
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen if (!rr)
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen return NULL;
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen assert(rr->n_ref > 0);
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
2ad8416dd057e7e3185169609ca3006e7649f576Zbigniew Jędrzejewski-Szmek if (rr->n_ref > 1) {
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen rr->n_ref--;
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen return NULL;
464cf22f17e0cf2d8bfa6d72b5e7a662d634f149Tom Gundersen }
464cf22f17e0cf2d8bfa6d72b5e7a662d634f149Tom Gundersen
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen if (rr->key) {
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen switch(rr->key->type) {
3b64e4d4f40baac56148c7d333d6a0053358ec7aTom Gundersen
3b64e4d4f40baac56148c7d333d6a0053358ec7aTom Gundersen case DNS_TYPE_SRV:
3b64e4d4f40baac56148c7d333d6a0053358ec7aTom Gundersen free(rr->srv.name);
3b64e4d4f40baac56148c7d333d6a0053358ec7aTom Gundersen break;
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
7eb08da4b388b920c8a894b1500c9cc7dc1f31efTom Gundersen case DNS_TYPE_PTR:
7eb08da4b388b920c8a894b1500c9cc7dc1f31efTom Gundersen case DNS_TYPE_NS:
7eb08da4b388b920c8a894b1500c9cc7dc1f31efTom Gundersen case DNS_TYPE_CNAME:
b3e013148603aa670bc2c060ac63d48e54d76fc2Tom Gundersen case DNS_TYPE_DNAME:
edbb03e95a3c31bf719d5c6c46eec14d0bcb9c8fTom Gundersen free(rr->ptr.name);
7eb08da4b388b920c8a894b1500c9cc7dc1f31efTom Gundersen break;
edbb03e95a3c31bf719d5c6c46eec14d0bcb9c8fTom Gundersen
eb7040ec50fbfe5aad9eaf305bd442a4a235abaaTom Gundersen case DNS_TYPE_HINFO:
b3e013148603aa670bc2c060ac63d48e54d76fc2Tom Gundersen free(rr->hinfo.cpu);
9b1c2626cef16722603bded9bb52033aba34dd74Tom Gundersen free(rr->hinfo.os);
bf175aafd20c9ef974709ef12c5acf836121af33Tom Gundersen break;
b3e013148603aa670bc2c060ac63d48e54d76fc2Tom Gundersen
32bc8adcd836baff68e4d0f53b9a382f358cccf8Tom Gundersen case DNS_TYPE_TXT:
32bc8adcd836baff68e4d0f53b9a382f358cccf8Tom Gundersen case DNS_TYPE_SPF:
32bc8adcd836baff68e4d0f53b9a382f358cccf8Tom Gundersen strv_free(rr->txt.strings);
32bc8adcd836baff68e4d0f53b9a382f358cccf8Tom Gundersen break;
32bc8adcd836baff68e4d0f53b9a382f358cccf8Tom Gundersen
32bc8adcd836baff68e4d0f53b9a382f358cccf8Tom Gundersen case DNS_TYPE_SOA:
dc75168823540076b354135f6e2de7a9a978fbcaZbigniew Jędrzejewski-Szmek free(rr->soa.mname);
32bc8adcd836baff68e4d0f53b9a382f358cccf8Tom Gundersen free(rr->soa.rname);
32bc8adcd836baff68e4d0f53b9a382f358cccf8Tom Gundersen break;
ca6038b89645c0c1bd547d6a420bf95eb3d6f4ccTom Gundersen
32bc8adcd836baff68e4d0f53b9a382f358cccf8Tom Gundersen case DNS_TYPE_MX:
32bc8adcd836baff68e4d0f53b9a382f358cccf8Tom Gundersen free(rr->mx.exchange);
32bc8adcd836baff68e4d0f53b9a382f358cccf8Tom Gundersen break;
32bc8adcd836baff68e4d0f53b9a382f358cccf8Tom Gundersen
32bc8adcd836baff68e4d0f53b9a382f358cccf8Tom Gundersen case DNS_TYPE_SSHFP:
32bc8adcd836baff68e4d0f53b9a382f358cccf8Tom Gundersen free(rr->sshfp.key);
32bc8adcd836baff68e4d0f53b9a382f358cccf8Tom Gundersen break;
32bc8adcd836baff68e4d0f53b9a382f358cccf8Tom Gundersen
ca6038b89645c0c1bd547d6a420bf95eb3d6f4ccTom Gundersen case DNS_TYPE_DNSKEY:
32bc8adcd836baff68e4d0f53b9a382f358cccf8Tom Gundersen free(rr->dnskey.key);
ca6038b89645c0c1bd547d6a420bf95eb3d6f4ccTom Gundersen break;
32bc8adcd836baff68e4d0f53b9a382f358cccf8Tom Gundersen
ca6038b89645c0c1bd547d6a420bf95eb3d6f4ccTom Gundersen case DNS_TYPE_RRSIG:
ca6038b89645c0c1bd547d6a420bf95eb3d6f4ccTom Gundersen free(rr->rrsig.signer);
32bc8adcd836baff68e4d0f53b9a382f358cccf8Tom Gundersen free(rr->rrsig.signature);
ca6038b89645c0c1bd547d6a420bf95eb3d6f4ccTom Gundersen break;
ca6038b89645c0c1bd547d6a420bf95eb3d6f4ccTom Gundersen
ca6038b89645c0c1bd547d6a420bf95eb3d6f4ccTom Gundersen case DNS_TYPE_LOC:
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen case DNS_TYPE_A:
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen case DNS_TYPE_AAAA:
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen break;
be32eb9b7fbcb22e4b648086d644135e38279633Tom Gundersen
be32eb9b7fbcb22e4b648086d644135e38279633Tom Gundersen default:
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen free(rr->generic.data);
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen }
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen dns_resource_key_unref(rr->key);
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen }
f1ac700248f231b7bdac2aafe8c35650efddb89fTom Gundersen
f1ac700248f231b7bdac2aafe8c35650efddb89fTom Gundersen free(rr);
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen
3c9b886068d99e5d3cbabcac32a4decf37244c54Tom Gundersen return NULL;
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen}
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen
3c9b886068d99e5d3cbabcac32a4decf37244c54Tom Gundersenint dns_resource_record_new_reverse(DnsResourceRecord **ret, int family, const union in_addr_union *address, const char *hostname) {
3c9b886068d99e5d3cbabcac32a4decf37244c54Tom Gundersen _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
f1ac700248f231b7bdac2aafe8c35650efddb89fTom Gundersen _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
f1ac700248f231b7bdac2aafe8c35650efddb89fTom Gundersen _cleanup_free_ char *ptr = NULL;
f1ac700248f231b7bdac2aafe8c35650efddb89fTom Gundersen int r;
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen
04b67d49254d956d31bcfe80340fb9df7ed332d3Tom Gundersen assert(ret);
04b67d49254d956d31bcfe80340fb9df7ed332d3Tom Gundersen assert(address);
04b67d49254d956d31bcfe80340fb9df7ed332d3Tom Gundersen assert(hostname);
04b67d49254d956d31bcfe80340fb9df7ed332d3Tom Gundersen
04b67d49254d956d31bcfe80340fb9df7ed332d3Tom Gundersen r = dns_name_reverse(family, address, &ptr);
04b67d49254d956d31bcfe80340fb9df7ed332d3Tom Gundersen if (r < 0)
04b67d49254d956d31bcfe80340fb9df7ed332d3Tom Gundersen return r;
04b67d49254d956d31bcfe80340fb9df7ed332d3Tom Gundersen
3c9b886068d99e5d3cbabcac32a4decf37244c54Tom Gundersen key = dns_resource_key_new_consume(DNS_CLASS_IN, DNS_TYPE_PTR, ptr);
04b67d49254d956d31bcfe80340fb9df7ed332d3Tom Gundersen if (!key)
04b67d49254d956d31bcfe80340fb9df7ed332d3Tom Gundersen return -ENOMEM;
3c9b886068d99e5d3cbabcac32a4decf37244c54Tom Gundersen
3c9b886068d99e5d3cbabcac32a4decf37244c54Tom Gundersen ptr = NULL;
04b67d49254d956d31bcfe80340fb9df7ed332d3Tom Gundersen
04b67d49254d956d31bcfe80340fb9df7ed332d3Tom Gundersen rr = dns_resource_record_new(key);
04b67d49254d956d31bcfe80340fb9df7ed332d3Tom Gundersen if (!rr)
04b67d49254d956d31bcfe80340fb9df7ed332d3Tom Gundersen return -ENOMEM;
04b67d49254d956d31bcfe80340fb9df7ed332d3Tom Gundersen
04b67d49254d956d31bcfe80340fb9df7ed332d3Tom Gundersen rr->ptr.name = strdup(hostname);
04b67d49254d956d31bcfe80340fb9df7ed332d3Tom Gundersen if (!rr->ptr.name)
3c9b886068d99e5d3cbabcac32a4decf37244c54Tom Gundersen return -ENOMEM;
3c9b886068d99e5d3cbabcac32a4decf37244c54Tom Gundersen
04b67d49254d956d31bcfe80340fb9df7ed332d3Tom Gundersen *ret = rr;
3c9b886068d99e5d3cbabcac32a4decf37244c54Tom Gundersen rr = NULL;
04b67d49254d956d31bcfe80340fb9df7ed332d3Tom Gundersen
3c9b886068d99e5d3cbabcac32a4decf37244c54Tom Gundersen return 0;
04b67d49254d956d31bcfe80340fb9df7ed332d3Tom Gundersen}
04b67d49254d956d31bcfe80340fb9df7ed332d3Tom Gundersen
04b67d49254d956d31bcfe80340fb9df7ed332d3Tom Gundersenint dns_resource_record_equal(const DnsResourceRecord *a, const DnsResourceRecord *b) {
3c9b886068d99e5d3cbabcac32a4decf37244c54Tom Gundersen int r;
3c9b886068d99e5d3cbabcac32a4decf37244c54Tom Gundersen
04b67d49254d956d31bcfe80340fb9df7ed332d3Tom Gundersen assert(a);
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen assert(b);
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen
464cf22f17e0cf2d8bfa6d72b5e7a662d634f149Tom Gundersen r = dns_resource_key_equal(a->key, b->key);
464cf22f17e0cf2d8bfa6d72b5e7a662d634f149Tom Gundersen if (r <= 0)
9bf3b53533cdc9b95c921b71da755401f223f765Lennart Poettering return r;
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen if (a->unparseable != b->unparseable)
9bf3b53533cdc9b95c921b71da755401f223f765Lennart Poettering return 0;
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen
9bf3b53533cdc9b95c921b71da755401f223f765Lennart Poettering switch (a->unparseable ? _DNS_TYPE_INVALID : a->key->type) {
9bf3b53533cdc9b95c921b71da755401f223f765Lennart Poettering
b5db00e52ee2e20578839e4e4488f7b9af9abc38Umut Tezduyar Lindskog case DNS_TYPE_SRV:
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen r = dns_name_equal(a->srv.name, b->srv.name);
55428d84f31b52da1c50b7469f14e15740547f20Tom Gundersen if (r <= 0)
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen return r;
9bf3b53533cdc9b95c921b71da755401f223f765Lennart Poettering
9bf3b53533cdc9b95c921b71da755401f223f765Lennart Poettering return a->srv.priority == b->srv.priority &&
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen a->srv.weight == b->srv.weight &&
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen a->srv.port == b->srv.port;
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen
3c9b886068d99e5d3cbabcac32a4decf37244c54Tom Gundersen case DNS_TYPE_PTR:
3c9b886068d99e5d3cbabcac32a4decf37244c54Tom Gundersen case DNS_TYPE_NS:
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen case DNS_TYPE_CNAME:
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen case DNS_TYPE_DNAME:
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen return dns_name_equal(a->ptr.name, b->ptr.name);
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen
464cf22f17e0cf2d8bfa6d72b5e7a662d634f149Tom Gundersen case DNS_TYPE_HINFO:
464cf22f17e0cf2d8bfa6d72b5e7a662d634f149Tom Gundersen return strcaseeq(a->hinfo.cpu, b->hinfo.cpu) &&
3e137a1b9a0eac2bf43d493d3302c3c959b6ccdbTom Gundersen strcaseeq(a->hinfo.os, b->hinfo.os);
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen case DNS_TYPE_SPF: /* exactly the same as TXT */
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen case DNS_TYPE_TXT:
04b67d49254d956d31bcfe80340fb9df7ed332d3Tom Gundersen return strv_equal(a->txt.strings, b->txt.strings);
43b3a5ef61859f06cdbaf26765cab8e1adac4296Tom Gundersen
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen case DNS_TYPE_A:
3e137a1b9a0eac2bf43d493d3302c3c959b6ccdbTom Gundersen return memcmp(&a->a.in_addr, &b->a.in_addr, sizeof(struct in_addr)) == 0;
3e137a1b9a0eac2bf43d493d3302c3c959b6ccdbTom Gundersen
3e137a1b9a0eac2bf43d493d3302c3c959b6ccdbTom Gundersen case DNS_TYPE_AAAA:
3e137a1b9a0eac2bf43d493d3302c3c959b6ccdbTom Gundersen return memcmp(&a->aaaa.in6_addr, &b->aaaa.in6_addr, sizeof(struct in6_addr)) == 0;
3e137a1b9a0eac2bf43d493d3302c3c959b6ccdbTom Gundersen
3e137a1b9a0eac2bf43d493d3302c3c959b6ccdbTom Gundersen case DNS_TYPE_SOA:
3e137a1b9a0eac2bf43d493d3302c3c959b6ccdbTom Gundersen r = dns_name_equal(a->soa.mname, b->soa.mname);
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen if (r <= 0)
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen return r;
dab495dc23bf9a5ba0487a057bb594355555a0e9Tom Gundersen r = dns_name_equal(a->soa.rname, b->soa.rname);
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen if (r <= 0)
dab495dc23bf9a5ba0487a057bb594355555a0e9Tom Gundersen return r;
755bde375f4db393ad06e73340bfcf4d0cf91bb2Lennart Poettering
755bde375f4db393ad06e73340bfcf4d0cf91bb2Lennart Poettering return a->soa.serial == b->soa.serial &&
a501033335ed402c8f7e86fe41a15531ba69abd7Tom Gundersen a->soa.refresh == b->soa.refresh &&
aedca89268ed4fd6be41e55a605f011033ad1fb5Tom Gundersen a->soa.retry == b->soa.retry &&
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen a->soa.expire == b->soa.expire &&
755bde375f4db393ad06e73340bfcf4d0cf91bb2Lennart Poettering a->soa.minimum == b->soa.minimum;
755bde375f4db393ad06e73340bfcf4d0cf91bb2Lennart Poettering
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen case DNS_TYPE_MX:
43b3a5ef61859f06cdbaf26765cab8e1adac4296Tom Gundersen if (a->mx.priority != b->mx.priority)
43b3a5ef61859f06cdbaf26765cab8e1adac4296Tom Gundersen return 0;
43b3a5ef61859f06cdbaf26765cab8e1adac4296Tom Gundersen
43b3a5ef61859f06cdbaf26765cab8e1adac4296Tom Gundersen return dns_name_equal(a->mx.exchange, b->mx.exchange);
43b3a5ef61859f06cdbaf26765cab8e1adac4296Tom Gundersen
43b3a5ef61859f06cdbaf26765cab8e1adac4296Tom Gundersen case DNS_TYPE_LOC:
f61942250a43a123580d7bbe5d7873dc5118ed97Tom Gundersen assert(a->loc.version == b->loc.version);
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen
daeb71a36a98834664e4d95773a3629b746f4db8Tom Gundersen return a->loc.size == b->loc.size &&
68ba38770640413b4fa06773447666eb88a38d4cTom Gundersen a->loc.horiz_pre == b->loc.horiz_pre &&
68ba38770640413b4fa06773447666eb88a38d4cTom Gundersen a->loc.vert_pre == b->loc.vert_pre &&
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen a->loc.latitude == b->loc.latitude &&
04b67d49254d956d31bcfe80340fb9df7ed332d3Tom Gundersen a->loc.longitude == b->loc.longitude &&
04b67d49254d956d31bcfe80340fb9df7ed332d3Tom Gundersen a->loc.altitude == b->loc.altitude;
04b67d49254d956d31bcfe80340fb9df7ed332d3Tom Gundersen
e51660ae56bb747ece2cab8fe6eec37f4d06a438Tom Gundersen case DNS_TYPE_SSHFP:
e51660ae56bb747ece2cab8fe6eec37f4d06a438Tom Gundersen return a->sshfp.algorithm == b->sshfp.algorithm &&
e51660ae56bb747ece2cab8fe6eec37f4d06a438Tom Gundersen a->sshfp.fptype == b->sshfp.fptype &&
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen a->sshfp.key_size == b->sshfp.key_size &&
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen memcmp(a->sshfp.key, b->sshfp.key, a->sshfp.key_size) == 0;
daeb71a36a98834664e4d95773a3629b746f4db8Tom Gundersen
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen case DNS_TYPE_DNSKEY:
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen return a->dnskey.zone_key_flag == b->dnskey.zone_key_flag &&
daeb71a36a98834664e4d95773a3629b746f4db8Tom Gundersen a->dnskey.sep_flag == b->dnskey.sep_flag &&
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen a->dnskey.algorithm == b->dnskey.algorithm &&
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen a->dnskey.key_size == b->dnskey.key_size &&
daeb71a36a98834664e4d95773a3629b746f4db8Tom Gundersen memcmp(a->dnskey.key, b->dnskey.key, a->dnskey.key_size) == 0;
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen case DNS_TYPE_RRSIG:
daeb71a36a98834664e4d95773a3629b746f4db8Tom Gundersen /* do the fast comparisons first */
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen if (a->rrsig.type_covered != b->rrsig.type_covered ||
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen a->rrsig.algorithm != b->rrsig.algorithm ||
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen a->rrsig.labels != b->rrsig.labels ||
daeb71a36a98834664e4d95773a3629b746f4db8Tom Gundersen a->rrsig.original_ttl != b->rrsig.original_ttl ||
daeb71a36a98834664e4d95773a3629b746f4db8Tom Gundersen a->rrsig.expiration != b->rrsig.expiration ||
daeb71a36a98834664e4d95773a3629b746f4db8Tom Gundersen a->rrsig.inception != b->rrsig.inception ||
04b67d49254d956d31bcfe80340fb9df7ed332d3Tom Gundersen a->rrsig.key_tag != b->rrsig.key_tag ||
3c9b886068d99e5d3cbabcac32a4decf37244c54Tom Gundersen a->rrsig.signature_size != b->rrsig.signature_size ||
04b67d49254d956d31bcfe80340fb9df7ed332d3Tom Gundersen memcmp(a->rrsig.signature, b->rrsig.signature, a->rrsig.signature_size) != 0)
04b67d49254d956d31bcfe80340fb9df7ed332d3Tom Gundersen return false;
04b67d49254d956d31bcfe80340fb9df7ed332d3Tom Gundersen
04b67d49254d956d31bcfe80340fb9df7ed332d3Tom Gundersen return dns_name_equal(a->rrsig.signer, b->rrsig.signer);
04b67d49254d956d31bcfe80340fb9df7ed332d3Tom Gundersen
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen default:
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen return a->generic.size == b->generic.size &&
92d927f850d4b668b44f3e5f41e266d934d03726Tom Gundersen memcmp(a->generic.data, b->generic.data, a->generic.size) == 0;
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen }
1c25683e0f40c6169676cc44fa1897082597feecTom Gundersen}
1c25683e0f40c6169676cc44fa1897082597feecTom Gundersen
a669ea9860900d5cdebbc4cb9aaea72db7e28a02Tom Gundersenstatic char* format_location(uint32_t latitude, uint32_t longitude, uint32_t altitude,
1c25683e0f40c6169676cc44fa1897082597feecTom Gundersen uint8_t size, uint8_t horiz_pre, uint8_t vert_pre) {
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen char *s;
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen char NS = latitude >= 1U<<31 ? 'N' : 'S';
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen char EW = longitude >= 1U<<31 ? 'E' : 'W';
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen int lat = latitude >= 1U<<31 ? (int) (latitude - (1U<<31)) : (int) ((1U<<31) - latitude);
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen int lon = longitude >= 1U<<31 ? (int) (longitude - (1U<<31)) : (int) ((1U<<31) - longitude);
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen double alt = altitude >= 10000000u ? altitude - 10000000u : -(double)(10000000u - altitude);
1c25683e0f40c6169676cc44fa1897082597feecTom Gundersen double siz = (size >> 4) * exp10((double) (size & 0xF));
1c25683e0f40c6169676cc44fa1897082597feecTom Gundersen double hor = (horiz_pre >> 4) * exp10((double) (horiz_pre & 0xF));
a669ea9860900d5cdebbc4cb9aaea72db7e28a02Tom Gundersen double ver = (vert_pre >> 4) * exp10((double) (vert_pre & 0xF));
1c25683e0f40c6169676cc44fa1897082597feecTom Gundersen
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen if (asprintf(&s, "%d %d %.3f %c %d %d %.3f %c %.2fm %.2fm %.2fm %.2fm",
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen (lat / 60000 / 60),
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen (lat / 60000) % 60,
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen (lat % 60000) / 1000.,
66d3752e812915a549ebee01769ee761c1495667Jacob Keller NS,
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen (lon / 60000 / 60),
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen (lon / 60000) % 60,
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen (lon % 60000) / 1000.,
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen EW,
dab495dc23bf9a5ba0487a057bb594355555a0e9Tom Gundersen alt / 100.,
f647962d64e844689f3e2acfce6102fc47e76df2Michal Schmidt siz / 100.,
f647962d64e844689f3e2acfce6102fc47e76df2Michal Schmidt hor / 100.,
43b3a5ef61859f06cdbaf26765cab8e1adac4296Tom Gundersen ver / 100.) < 0)
d95b83b87d7d7c50e550f7128827f73a321c8934Tom Gundersen return NULL;
d95b83b87d7d7c50e550f7128827f73a321c8934Tom Gundersen
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen return s;
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen}
be32eb9b7fbcb22e4b648086d644135e38279633Tom Gundersen
847a8a5fed4d265dfa659917515c6f9bd1b8d5c4Tom Gundersenstatic int format_timestamp_dns(char *buf, size_t l, time_t sec) {
847a8a5fed4d265dfa659917515c6f9bd1b8d5c4Tom Gundersen struct tm tm;
a7f7d1bde43fc825c49afea3f946f5b4b3d563e0Harald Hoyer
847a8a5fed4d265dfa659917515c6f9bd1b8d5c4Tom Gundersen assert(buf);
847a8a5fed4d265dfa659917515c6f9bd1b8d5c4Tom Gundersen assert(l > strlen("YYYYMMDDHHmmSS"));
847a8a5fed4d265dfa659917515c6f9bd1b8d5c4Tom Gundersen
847a8a5fed4d265dfa659917515c6f9bd1b8d5c4Tom Gundersen if (!gmtime_r(&sec, &tm))
847a8a5fed4d265dfa659917515c6f9bd1b8d5c4Tom Gundersen return -EINVAL;
847a8a5fed4d265dfa659917515c6f9bd1b8d5c4Tom Gundersen
aedca89268ed4fd6be41e55a605f011033ad1fb5Tom Gundersen if (strftime(buf, l, "%Y%m%d%H%M%S", &tm) <= 0)
847a8a5fed4d265dfa659917515c6f9bd1b8d5c4Tom Gundersen return -EINVAL;
847a8a5fed4d265dfa659917515c6f9bd1b8d5c4Tom Gundersen
847a8a5fed4d265dfa659917515c6f9bd1b8d5c4Tom Gundersen return 0;
847a8a5fed4d265dfa659917515c6f9bd1b8d5c4Tom Gundersen}
847a8a5fed4d265dfa659917515c6f9bd1b8d5c4Tom Gundersen
847a8a5fed4d265dfa659917515c6f9bd1b8d5c4Tom Gundersenint dns_resource_record_to_string(const DnsResourceRecord *rr, char **ret) {
847a8a5fed4d265dfa659917515c6f9bd1b8d5c4Tom Gundersen _cleanup_free_ char *k = NULL, *t = NULL;
2c5859afecee81e345fc9526b1083bf79990ffb8Daniel Mack char *s;
be32eb9b7fbcb22e4b648086d644135e38279633Tom Gundersen int r;
66d3752e812915a549ebee01769ee761c1495667Jacob Keller
66d3752e812915a549ebee01769ee761c1495667Jacob Keller assert(rr);
be32eb9b7fbcb22e4b648086d644135e38279633Tom Gundersen
be32eb9b7fbcb22e4b648086d644135e38279633Tom Gundersen r = dns_resource_key_to_string(rr->key, &k);
be32eb9b7fbcb22e4b648086d644135e38279633Tom Gundersen if (r < 0)
464cf22f17e0cf2d8bfa6d72b5e7a662d634f149Tom Gundersen return r;
464cf22f17e0cf2d8bfa6d72b5e7a662d634f149Tom Gundersen
be32eb9b7fbcb22e4b648086d644135e38279633Tom Gundersen switch (rr->unparseable ? _DNS_TYPE_INVALID : rr->key->type) {
2c5859afecee81e345fc9526b1083bf79990ffb8Daniel Mack
04b67d49254d956d31bcfe80340fb9df7ed332d3Tom Gundersen case DNS_TYPE_SRV:
e51660ae56bb747ece2cab8fe6eec37f4d06a438Tom Gundersen r = asprintf(&s, "%s %u %u %u %s",
be32eb9b7fbcb22e4b648086d644135e38279633Tom Gundersen k,
be32eb9b7fbcb22e4b648086d644135e38279633Tom Gundersen rr->srv.priority,
be32eb9b7fbcb22e4b648086d644135e38279633Tom Gundersen rr->srv.weight,
be32eb9b7fbcb22e4b648086d644135e38279633Tom Gundersen rr->srv.port,
be32eb9b7fbcb22e4b648086d644135e38279633Tom Gundersen strna(rr->srv.name));
be32eb9b7fbcb22e4b648086d644135e38279633Tom Gundersen if (r < 0)
be32eb9b7fbcb22e4b648086d644135e38279633Tom Gundersen return -ENOMEM;
464cf22f17e0cf2d8bfa6d72b5e7a662d634f149Tom Gundersen break;
464cf22f17e0cf2d8bfa6d72b5e7a662d634f149Tom Gundersen
464cf22f17e0cf2d8bfa6d72b5e7a662d634f149Tom Gundersen 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 = base64mem(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;
}
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;
}
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;
}