-/* SPDX-License-Identifier: LGPL-2.1+ */
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include <math.h>
#include "dns-type.h"
#include "escape.h"
#include "hexdecoct.h"
+#include "memory-util.h"
#include "resolved-dns-dnssec.h"
#include "resolved-dns-packet.h"
#include "resolved-dns-rr.h"
assert(name);
- k = new0(DnsResourceKey, 1);
+ k = new(DnsResourceKey, 1);
if (!k)
return NULL;
- k->n_ref = 1;
- k->class = class;
- k->type = type;
- k->_name = name;
+ *k = (DnsResourceKey) {
+ .n_ref = 1,
+ .class = class,
+ .type = type,
+ ._name = name,
+ };
return k;
}
/* Static/const keys created with DNS_RESOURCE_KEY_CONST will
* set this to -1, they should not be reffed/unreffed */
- assert(k->n_ref != (unsigned) -1);
+ assert(k->n_ref != UINT_MAX);
assert(k->n_ref > 0);
k->n_ref++;
if (!k)
return NULL;
- assert(k->n_ref != (unsigned) -1);
+ assert(k->n_ref != UINT_MAX);
assert(k->n_ref > 0);
if (k->n_ref == 1) {
}
static int dns_resource_key_compare_func(const DnsResourceKey *x, const DnsResourceKey *y) {
- int ret;
-
- ret = dns_name_compare_func(dns_resource_key_name(x), dns_resource_key_name(y));
- if (ret != 0)
- return ret;
+ int r;
- ret = CMP(x->type, y->type);
- if (ret != 0)
- return ret;
+ r = dns_name_compare_func(dns_resource_key_name(x), dns_resource_key_name(y));
+ if (r != 0)
+ return r;
- ret = CMP(x->class, y->class);
- if (ret != 0)
- return ret;
+ r = CMP(x->type, y->type);
+ if (r != 0)
+ return r;
- return 0;
+ return CMP(x->class, y->class);
}
DEFINE_HASH_OPS(dns_resource_key_hash_ops, DnsResourceKey, dns_resource_key_hash_func, dns_resource_key_compare_func);
return false;
/* We refuse merging const keys */
- if ((*a)->n_ref == (unsigned) -1)
+ if ((*a)->n_ref == UINT_MAX)
return false;
- if ((*b)->n_ref == (unsigned) -1)
+ if ((*b)->n_ref == UINT_MAX)
return false;
/* Already the same? */
DnsResourceRecord* dns_resource_record_new(DnsResourceKey *key) {
DnsResourceRecord *rr;
- rr = new0(DnsResourceRecord, 1);
+ rr = new(DnsResourceRecord, 1);
if (!rr)
return NULL;
- rr->n_ref = 1;
- rr->key = dns_resource_key_ref(key);
- rr->expiry = USEC_INFINITY;
- rr->n_skip_labels_signer = rr->n_skip_labels_source = (unsigned) -1;
+ *rr = (DnsResourceRecord) {
+ .n_ref = 1,
+ .key = dns_resource_key_ref(key),
+ .expiry = USEC_INFINITY,
+ .n_skip_labels_signer = UINT_MAX,
+ .n_skip_labels_source = UINT_MAX,
+ };
return rr;
}
case DNS_TYPE_OPENPGPKEY:
default:
- if (!rr->unparseable)
+ if (!rr->unparsable)
free(rr->generic.data);
}
- if (rr->unparseable)
+ if (rr->unparsable)
free(rr->generic.data);
free(rr->wire_format);
#define FIELD_EQUAL(a, b, field) \
((a).field ## _size == (b).field ## _size && \
- memcmp((a).field, (b).field, (a).field ## _size) == 0)
+ memcmp_safe((a).field, (b).field, (a).field ## _size) == 0)
-int dns_resource_record_equal(const DnsResourceRecord *a, const DnsResourceRecord *b) {
+int dns_resource_record_payload_equal(const DnsResourceRecord *a, const DnsResourceRecord *b) {
int r;
- assert(a);
- assert(b);
+ /* Check if a and b are the same, but don't look at their keys */
- if (a == b)
- return 1;
-
- r = dns_resource_key_equal(a->key, b->key);
- if (r <= 0)
- return r;
-
- if (a->unparseable != b->unparseable)
+ if (a->unparsable != b->unparsable)
return 0;
- switch (a->unparseable ? _DNS_TYPE_INVALID : a->key->type) {
+ switch (a->unparsable ? _DNS_TYPE_INVALID : a->key->type) {
case DNS_TYPE_SRV:
r = dns_name_equal(a->srv.name, b->srv.name);
}
}
+int dns_resource_record_equal(const DnsResourceRecord *a, const DnsResourceRecord *b) {
+ int r;
+
+ assert(a);
+ assert(b);
+
+ if (a == b)
+ return 1;
+
+ r = dns_resource_key_equal(a->key, b->key);
+ if (r <= 0)
+ return r;
+
+ return dns_resource_record_payload_equal(a, b);
+}
+
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;
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) {
+ BITMAP_FOREACH(type, types) {
if (dns_type_to_string(type)) {
r = strv_extend(&strv, dns_type_to_string(type));
if (r < 0)
dns_resource_key_to_string(rr->key, k, sizeof(k));
- switch (rr->unparseable ? _DNS_TYPE_INVALID : rr->key->type) {
+ switch (rr->unparsable ? _DNS_TYPE_INVALID : rr->key->type) {
case DNS_TYPE_SRV:
r = asprintf(&s, "%s %u %u %u %s",
assert(rr);
assert(out);
- switch(rr->unparseable ? _DNS_TYPE_INVALID : rr->key->type) {
+ switch(rr->unparsable ? _DNS_TYPE_INVALID : rr->key->type) {
case DNS_TYPE_SRV:
case DNS_TYPE_PTR:
case DNS_TYPE_NS:
/* Returns the RRset's signer, if it is known. */
- if (rr->n_skip_labels_signer == (unsigned) -1)
+ if (rr->n_skip_labels_signer == UINT_MAX)
return -ENODATA;
n = dns_resource_key_name(rr->key);
/* Returns the RRset's synthesizing source, if it is known. */
- if (rr->n_skip_labels_source == (unsigned) -1)
+ if (rr->n_skip_labels_source == UINT_MAX)
return -ENODATA;
n = dns_resource_key_name(rr->key);
/* Returns > 0 if the RR is generated from a wildcard, and is not the asterisk name itself */
- if (rr->n_skip_labels_source == (unsigned) -1)
+ if (rr->n_skip_labels_source == UINT_MAX)
return -ENODATA;
if (rr->n_skip_labels_source == 0)
dns_resource_key_hash_func(rr->key, state);
- switch (rr->unparseable ? _DNS_TYPE_INVALID : rr->key->type) {
+ switch (rr->unparsable ? _DNS_TYPE_INVALID : rr->key->type) {
case DNS_TYPE_SRV:
siphash24_compress(&rr->srv.priority, sizeof(rr->srv.priority), state);
DnsTxtItem *j;
LIST_FOREACH(items, j, rr->txt.items) {
- siphash24_compress(j->data, j->length, state);
+ siphash24_compress_safe(j->data, j->length, state);
/* Add an extra NUL byte, so that "a" followed by "b" doesn't result in the same hash as "ab"
* followed by "". */
case DNS_TYPE_SSHFP:
siphash24_compress(&rr->sshfp.algorithm, sizeof(rr->sshfp.algorithm), state);
siphash24_compress(&rr->sshfp.fptype, sizeof(rr->sshfp.fptype), state);
- siphash24_compress(rr->sshfp.fingerprint, rr->sshfp.fingerprint_size, state);
+ siphash24_compress_safe(rr->sshfp.fingerprint, rr->sshfp.fingerprint_size, state);
break;
case DNS_TYPE_DNSKEY:
siphash24_compress(&rr->dnskey.flags, sizeof(rr->dnskey.flags), state);
siphash24_compress(&rr->dnskey.protocol, sizeof(rr->dnskey.protocol), state);
siphash24_compress(&rr->dnskey.algorithm, sizeof(rr->dnskey.algorithm), state);
- siphash24_compress(rr->dnskey.key, rr->dnskey.key_size, state);
+ siphash24_compress_safe(rr->dnskey.key, rr->dnskey.key_size, state);
break;
case DNS_TYPE_RRSIG:
siphash24_compress(&rr->rrsig.inception, sizeof(rr->rrsig.inception), state);
siphash24_compress(&rr->rrsig.key_tag, sizeof(rr->rrsig.key_tag), state);
dns_name_hash_func(rr->rrsig.signer, state);
- siphash24_compress(rr->rrsig.signature, rr->rrsig.signature_size, state);
+ siphash24_compress_safe(rr->rrsig.signature, rr->rrsig.signature_size, state);
break;
case DNS_TYPE_NSEC:
siphash24_compress(&rr->ds.key_tag, sizeof(rr->ds.key_tag), state);
siphash24_compress(&rr->ds.algorithm, sizeof(rr->ds.algorithm), state);
siphash24_compress(&rr->ds.digest_type, sizeof(rr->ds.digest_type), state);
- siphash24_compress(rr->ds.digest, rr->ds.digest_size, state);
+ siphash24_compress_safe(rr->ds.digest, rr->ds.digest_size, state);
break;
case DNS_TYPE_NSEC3:
siphash24_compress(&rr->nsec3.algorithm, sizeof(rr->nsec3.algorithm), state);
siphash24_compress(&rr->nsec3.flags, sizeof(rr->nsec3.flags), state);
siphash24_compress(&rr->nsec3.iterations, sizeof(rr->nsec3.iterations), state);
- siphash24_compress(rr->nsec3.salt, rr->nsec3.salt_size, state);
- siphash24_compress(rr->nsec3.next_hashed_name, rr->nsec3.next_hashed_name_size, state);
+ siphash24_compress_safe(rr->nsec3.salt, rr->nsec3.salt_size, state);
+ siphash24_compress_safe(rr->nsec3.next_hashed_name, rr->nsec3.next_hashed_name_size, state);
/* FIXME: We leave the bitmaps out */
break;
siphash24_compress(&rr->tlsa.cert_usage, sizeof(rr->tlsa.cert_usage), state);
siphash24_compress(&rr->tlsa.selector, sizeof(rr->tlsa.selector), state);
siphash24_compress(&rr->tlsa.matching_type, sizeof(rr->tlsa.matching_type), state);
- siphash24_compress(rr->tlsa.data, rr->tlsa.data_size, state);
+ siphash24_compress_safe(rr->tlsa.data, rr->tlsa.data_size, state);
break;
case DNS_TYPE_CAA:
siphash24_compress(&rr->caa.flags, sizeof(rr->caa.flags), state);
string_hash_func(rr->caa.tag, state);
- siphash24_compress(rr->caa.value, rr->caa.value_size, state);
+ siphash24_compress_safe(rr->caa.value, rr->caa.value_size, state);
break;
case DNS_TYPE_OPENPGPKEY:
default:
- siphash24_compress(rr->generic.data, rr->generic.data_size, state);
+ siphash24_compress_safe(rr->generic.data, rr->generic.data_size, state);
break;
}
}
-static int dns_resource_record_compare_func(const DnsResourceRecord *x, const DnsResourceRecord *y) {
+int dns_resource_record_compare_func(const DnsResourceRecord *x, const DnsResourceRecord *y) {
int r;
r = dns_resource_key_compare_func(x->key, y->key);
if (r != 0)
return r;
- if (dns_resource_record_equal(x, y))
+ if (dns_resource_record_payload_equal(x, y) > 0)
return 0;
/* We still use CMP() here, even though don't implement proper
copy->expiry = rr->expiry;
copy->n_skip_labels_signer = rr->n_skip_labels_signer;
copy->n_skip_labels_source = rr->n_skip_labels_source;
- copy->unparseable = rr->unparseable;
+ copy->unparsable = rr->unparsable;
- switch (rr->unparseable ? _DNS_TYPE_INVALID : rr->key->type) {
+ switch (rr->unparsable ? _DNS_TYPE_INVALID : rr->key->type) {
case DNS_TYPE_SRV:
copy->srv.priority = rr->srv.priority;
return NULL;
copy->nsec3.salt_size = rr->nsec3.salt_size;
copy->nsec3.next_hashed_name = memdup(rr->nsec3.next_hashed_name, rr->nsec3.next_hashed_name_size);
- if (!copy->nsec3.next_hashed_name_size)
+ if (!copy->nsec3.next_hashed_name)
return NULL;
copy->nsec3.next_hashed_name_size = rr->nsec3.next_hashed_name_size;
copy->nsec3.types = bitmap_copy(rr->nsec3.types);
return 1;
}
+bool dns_resource_record_is_link_local_address(DnsResourceRecord *rr) {
+ assert(rr);
+
+ if (rr->key->class != DNS_CLASS_IN)
+ return false;
+
+ if (rr->key->type == DNS_TYPE_A)
+ return in4_addr_is_link_local(&rr->a.in_addr);
+
+ if (rr->key->type == DNS_TYPE_AAAA)
+ return in6_addr_is_link_local(&rr->aaaa.in6_addr);
+
+ return false;
+}
+
+int dns_resource_record_get_cname_target(DnsResourceKey *key, DnsResourceRecord *cname, char **ret) {
+ _cleanup_free_ char *d = NULL;
+ int r;
+
+ assert(key);
+ assert(cname);
+
+ if (key->class != cname->key->class && key->class != DNS_CLASS_ANY)
+ return -EUNATCH;
+
+ if (cname->key->type == DNS_TYPE_CNAME) {
+ r = dns_name_equal(dns_resource_key_name(key),
+ dns_resource_key_name(cname->key));
+ if (r < 0)
+ return r;
+ if (r == 0)
+ return -EUNATCH; /* CNAME RR key doesn't actually match the original key */
+
+ d = strdup(cname->cname.name);
+ if (!d)
+ return -ENOMEM;
+
+ } else if (cname->key->type == DNS_TYPE_DNAME) {
+
+ r = dns_name_change_suffix(
+ dns_resource_key_name(key),
+ dns_resource_key_name(cname->key),
+ cname->dname.name,
+ &d);
+ if (r < 0)
+ return r;
+ if (r == 0)
+ return -EUNATCH; /* DNAME RR key doesn't actually match the original key */
+
+ } else
+ return -EUNATCH; /* Not a CNAME/DNAME RR, hence doesn't match the proposition either */
+
+ *ret = TAKE_PTR(d);
+ return 0;
+}
+
DnsTxtItem *dns_txt_item_free_all(DnsTxtItem *i) {
DnsTxtItem *n;