]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/resolve/resolved-dns-rr.c
tree-wide: use UINT64_MAX or friends
[thirdparty/systemd.git] / src / resolve / resolved-dns-rr.c
index 477d5170aadaac7dac796d35e603b4e0d41b3aad..823117e5c92d3e0d752e89dc5b6cf2df1db2344e 100644 (file)
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: LGPL-2.1+ */
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
 
 #include <math.h>
 
@@ -7,6 +7,7 @@
 #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"
@@ -96,14 +97,16 @@ DnsResourceKey* dns_resource_key_new_consume(uint16_t class, uint16_t type, char
 
         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;
 }
@@ -115,7 +118,7 @@ DnsResourceKey* dns_resource_key_ref(DnsResourceKey *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++;
@@ -127,7 +130,7 @@ DnsResourceKey* dns_resource_key_unref(DnsResourceKey *k) {
         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) {
@@ -291,21 +294,17 @@ static void dns_resource_key_hash_func(const DnsResourceKey *k, struct siphash *
 }
 
 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);
@@ -343,9 +342,9 @@ bool dns_resource_key_reduce(DnsResourceKey **a, DnsResourceKey **b) {
                 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? */
@@ -371,14 +370,17 @@ bool dns_resource_key_reduce(DnsResourceKey **a, DnsResourceKey **b) {
 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;
 }
@@ -473,11 +475,11 @@ static DnsResourceRecord* dns_resource_record_free(DnsResourceRecord *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);
@@ -555,25 +557,17 @@ int dns_resource_record_new_address(DnsResourceRecord **ret, int family, const u
 
 #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);
@@ -692,6 +686,22 @@ int dns_resource_record_equal(const DnsResourceRecord *a, const DnsResourceRecor
         }
 }
 
+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;
@@ -741,11 +751,10 @@ static int format_timestamp_dns(char *buf, size_t l, time_t sec) {
 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)
@@ -819,7 +828,7 @@ const char *dns_resource_record_to_string(DnsResourceRecord *rr) {
 
         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",
@@ -1166,7 +1175,7 @@ ssize_t dns_resource_record_payload(DnsResourceRecord *rr, void **out) {
         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:
@@ -1256,7 +1265,7 @@ int dns_resource_record_signer(DnsResourceRecord *rr, const char **ret) {
 
         /* 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);
@@ -1279,7 +1288,7 @@ int dns_resource_record_source(DnsResourceRecord *rr, const char **ret) {
 
         /* 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);
@@ -1313,7 +1322,7 @@ int dns_resource_record_is_synthetic(DnsResourceRecord *rr) {
 
         /* 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)
@@ -1334,7 +1343,7 @@ void dns_resource_record_hash_func(const DnsResourceRecord *rr, struct siphash *
 
         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);
@@ -1360,7 +1369,7 @@ void dns_resource_record_hash_func(const DnsResourceRecord *rr, struct siphash *
                 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 "". */
@@ -1405,14 +1414,14 @@ void dns_resource_record_hash_func(const DnsResourceRecord *rr, struct siphash *
         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:
@@ -1424,7 +1433,7 @@ void dns_resource_record_hash_func(const DnsResourceRecord *rr, struct siphash *
                 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:
@@ -1438,15 +1447,15 @@ void dns_resource_record_hash_func(const DnsResourceRecord *rr, struct siphash *
                 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;
 
@@ -1454,30 +1463,30 @@ void dns_resource_record_hash_func(const DnsResourceRecord *rr, struct siphash *
                 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
@@ -1501,9 +1510,9 @@ DnsResourceRecord *dns_resource_record_copy(DnsResourceRecord *rr) {
         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;
@@ -1637,7 +1646,7 @@ DnsResourceRecord *dns_resource_record_copy(DnsResourceRecord *rr) {
                         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);
@@ -1712,6 +1721,62 @@ int dns_resource_record_clamp_ttl(DnsResourceRecord **rr, uint32_t max_ttl) {
         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;