resolved-dns-rr.c revision 7c6423e19136a7b7b6ef3fe06b94822e582dda27
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen This file is part of systemd.
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen Copyright 2014 Lennart Poettering
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 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 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/>.
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart PoetteringDnsResourceKey* dns_resource_key_new(uint16_t class, uint16_t type, const char *name) {
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering k = malloc0(sizeof(DnsResourceKey) + l + 1);
a501033335ed402c8f7e86fe41a15531ba69abd7Tom Gundersen strcpy((char*) k + sizeof(DnsResourceKey), name);
97f2d76d4f4dfab8b0629c09926a05a1e5621125Tom GundersenDnsResourceKey* dns_resource_key_new_consume(uint16_t class, uint16_t type, char *name) {
9a4b012e43f23516373bf398dd9a458439d19939Tom GundersenDnsResourceKey* dns_resource_key_ref(DnsResourceKey *k) {
9a4b012e43f23516373bf398dd9a458439d19939Tom GundersenDnsResourceKey* dns_resource_key_unref(DnsResourceKey *k) {
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersenint dns_resource_key_equal(const DnsResourceKey *a, const DnsResourceKey *b) {
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen r = dns_name_equal(DNS_RESOURCE_KEY_NAME(a), DNS_RESOURCE_KEY_NAME(b));
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersenint dns_resource_key_match_rr(const DnsResourceKey *key, const DnsResourceRecord *rr) {
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen if (rr->key->class != key->class && key->class != DNS_CLASS_ANY)
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen if (rr->key->type != key->type && key->type != DNS_TYPE_ANY)
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen return dns_name_equal(DNS_RESOURCE_KEY_NAME(rr->key), DNS_RESOURCE_KEY_NAME(key));
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersenint dns_resource_key_match_cname(const DnsResourceKey *key, const DnsResourceRecord *rr) {
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen if (rr->key->class != key->class && key->class != DNS_CLASS_ANY)
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen return dns_name_equal(DNS_RESOURCE_KEY_NAME(rr->key), DNS_RESOURCE_KEY_NAME(key));
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersenstatic unsigned long dns_resource_key_hash_func(const void *i, const uint8_t hash_key[HASH_KEY_SIZE]) {
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen unsigned long ul;
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 Gundersenstatic int dns_resource_key_compare_func(const void *a, const void *b) {
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen const DnsResourceKey *x = a, *y = b;
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen ret = dns_name_compare_func(DNS_RESOURCE_KEY_NAME(x), DNS_RESOURCE_KEY_NAME(y));
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
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;
a2a5291b3f5ab6ed4c92f51d0fd10a03047380d8Zbigniew Jędrzejewski-Szmek if (asprintf(&s, "%s %s %-5s", DNS_RESOURCE_KEY_NAME(key), c, t) < 0)
74df0fca09b3c31ed19e14ba80f996fdff772417Lennart PoetteringDnsResourceRecord* dns_resource_record_new(DnsResourceKey *key) {
a2a5291b3f5ab6ed4c92f51d0fd10a03047380d8Zbigniew Jędrzejewski-Szmek rr = new0(DnsResourceRecord, 1);
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 key = dns_resource_key_new(class, type, name);
2ad8416dd057e7e3185169609ca3006e7649f576Zbigniew Jędrzejewski-SzmekDnsResourceRecord* dns_resource_record_ref(DnsResourceRecord *rr) {
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom GundersenDnsResourceRecord* dns_resource_record_unref(DnsResourceRecord *rr) {
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;
3c9b886068d99e5d3cbabcac32a4decf37244c54Tom Gundersen key = dns_resource_key_new_consume(DNS_CLASS_IN, DNS_TYPE_PTR, ptr);
04b67d49254d956d31bcfe80340fb9df7ed332d3Tom Gundersenint dns_resource_record_equal(const DnsResourceRecord *a, const DnsResourceRecord *b) {
9bf3b53533cdc9b95c921b71da755401f223f765Lennart Poettering switch (a->unparseable ? _DNS_TYPE_INVALID : a->key->type) {
9bf3b53533cdc9b95c921b71da755401f223f765Lennart Poettering return a->srv.priority == b->srv.priority &&
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen return dns_name_equal(a->ptr.name, b->ptr.name);
464cf22f17e0cf2d8bfa6d72b5e7a662d634f149Tom Gundersen return strcaseeq(a->hinfo.cpu, b->hinfo.cpu) &&
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen case DNS_TYPE_SPF: /* exactly the same as TXT */
04b67d49254d956d31bcfe80340fb9df7ed332d3Tom Gundersen return strv_equal(a->txt.strings, b->txt.strings);
3e137a1b9a0eac2bf43d493d3302c3c959b6ccdbTom Gundersen return memcmp(&a->a.in_addr, &b->a.in_addr, sizeof(struct in_addr)) == 0;
3e137a1b9a0eac2bf43d493d3302c3c959b6ccdbTom Gundersen return memcmp(&a->aaaa.in6_addr, &b->aaaa.in6_addr, sizeof(struct in6_addr)) == 0;
3e137a1b9a0eac2bf43d493d3302c3c959b6ccdbTom Gundersen r = dns_name_equal(a->soa.mname, b->soa.mname);
dab495dc23bf9a5ba0487a057bb594355555a0e9Tom Gundersen r = dns_name_equal(a->soa.rname, b->soa.rname);
43b3a5ef61859f06cdbaf26765cab8e1adac4296Tom Gundersen return dns_name_equal(a->mx.exchange, b->mx.exchange);
e51660ae56bb747ece2cab8fe6eec37f4d06a438Tom Gundersen return a->sshfp.algorithm == b->sshfp.algorithm &&
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen memcmp(a->sshfp.key, b->sshfp.key, a->sshfp.key_size) == 0;
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen return a->dnskey.zone_key_flag == b->dnskey.zone_key_flag &&
daeb71a36a98834664e4d95773a3629b746f4db8Tom Gundersen memcmp(a->dnskey.key, b->dnskey.key, a->dnskey.key_size) == 0;
daeb71a36a98834664e4d95773a3629b746f4db8Tom Gundersen /* do the fast comparisons first */
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen if (a->rrsig.type_covered != b->rrsig.type_covered ||
daeb71a36a98834664e4d95773a3629b746f4db8Tom Gundersen a->rrsig.original_ttl != b->rrsig.original_ttl ||
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 return dns_name_equal(a->rrsig.signer, b->rrsig.signer);
92d927f850d4b668b44f3e5f41e266d934d03726Tom Gundersen memcmp(a->generic.data, b->generic.data, a->generic.size) == 0;
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) {
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));
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen if (asprintf(&s, "%d %d %.3f %c %d %d %.3f %c %.2fm %.2fm %.2fm %.2fm",
847a8a5fed4d265dfa659917515c6f9bd1b8d5c4Tom Gundersenstatic int format_timestamp_dns(char *buf, size_t l, time_t sec) {
aedca89268ed4fd6be41e55a605f011033ad1fb5Tom Gundersen if (strftime(buf, l, "%Y%m%d%H%M%S", &tm) <= 0)
847a8a5fed4d265dfa659917515c6f9bd1b8d5c4Tom Gundersenint dns_resource_record_to_string(const DnsResourceRecord *rr, char **ret) {
be32eb9b7fbcb22e4b648086d644135e38279633Tom Gundersen switch (rr->unparseable ? _DNS_TYPE_INVALID : rr->key->type) {
case DNS_TYPE_NS:
case DNS_TYPE_CNAME:
case DNS_TYPE_DNAME:
return -ENOMEM;
case DNS_TYPE_HINFO:
return -ENOMEM;
case DNS_TYPE_TXT:
return -ENOMEM;
return -ENOMEM;
case DNS_TYPE_A: {
return -ENOMEM;
case DNS_TYPE_AAAA:
return -ENOMEM;
case DNS_TYPE_SOA:
return -ENOMEM;
case DNS_TYPE_MX:
return -ENOMEM;
case DNS_TYPE_LOC:
return -ENOMEM;
return -ENOMEM;
case DNS_TYPE_SSHFP:
return -ENOMEM;
return -ENOMEM;
case DNS_TYPE_DNSKEY: {
const char *alg;
return -ENOMEM;
return -ENOMEM;
case DNS_TYPE_RRSIG: {
return -ENOMEM;
* http://tools.ietf.org/html/rfc3597#section-5 */
return -ENOMEM;
return -ENOMEM;
return -ENOMEM;
*ret = s;
switch (class) {
case DNS_CLASS_IN:
case DNS_CLASS_ANY:
return NULL;
assert(s);
return -EINVAL;