]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
resolved: add dns_resource_record_get_cname_target() helper
authorLennart Poettering <lennart@poettering.net>
Mon, 22 Feb 2021 22:07:01 +0000 (23:07 +0100)
committerLennart Poettering <lennart@poettering.net>
Mon, 22 Feb 2021 22:55:13 +0000 (23:55 +0100)
This determines the redirection target from a CNAME or DNAME RR given it
matches some given RR key.

src/resolve/resolved-dns-rr.c
src/resolve/resolved-dns-rr.h
src/resolve/test-dns-packet.c

index d844f7c9aa93268c3e1c88b6b93a95ca41b7dc40..9b94ab59eabbae6b32bd9a497d4e4d336b403c9b 100644 (file)
@@ -1722,6 +1722,7 @@ int dns_resource_record_clamp_ttl(DnsResourceRecord **rr, uint32_t max_ttl) {
 }
 
 bool dns_resource_record_is_link_local_address(DnsResourceRecord *rr) {
+        assert(rr);
 
         if (rr->key->class != DNS_CLASS_IN)
                 return false;
@@ -1735,6 +1736,47 @@ bool dns_resource_record_is_link_local_address(DnsResourceRecord *rr) {
         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;
 
index d788d797fc8fd30a10bf8a3695d9ae0f1354b291..d3edcadf675384f8ed5fdf349f0ecbe00d772648 100644 (file)
@@ -326,6 +326,8 @@ int dns_resource_record_clamp_ttl(DnsResourceRecord **rr, uint32_t max_ttl);
 
 bool dns_resource_record_is_link_local_address(DnsResourceRecord *rr);
 
+int dns_resource_record_get_cname_target(DnsResourceKey *key, DnsResourceRecord *cname, char **ret);
+
 DnsTxtItem *dns_txt_item_free_all(DnsTxtItem *i);
 bool dns_txt_item_equal(DnsTxtItem *a, DnsTxtItem *b);
 DnsTxtItem *dns_txt_item_copy(DnsTxtItem *i);
index 47c7d671cd3733fb2795d1c510eb417b5558866d..72b6d4a657662cb9e649449b2a2d01c2e5c0c04a 100644 (file)
@@ -90,6 +90,39 @@ static void test_packet_from_file(const char* filename, bool canonical) {
         }
 }
 
+static void test_dns_resource_record_get_cname_target(void) {
+        _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *cname = NULL;
+        _cleanup_free_ char *target = NULL;
+
+        assert_se(cname = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_CNAME, "quux.foobar"));
+        assert_se(cname->cname.name = strdup("wuff.wuff"));
+
+        assert_se(dns_resource_record_get_cname_target(&DNS_RESOURCE_KEY_CONST(DNS_CLASS_IN, DNS_TYPE_A, "waldo"), cname, &target) == -EUNATCH);
+        assert_se(dns_resource_record_get_cname_target(&DNS_RESOURCE_KEY_CONST(DNS_CLASS_IN, DNS_TYPE_A, "foobar"), cname, &target) == -EUNATCH);
+        assert_se(dns_resource_record_get_cname_target(&DNS_RESOURCE_KEY_CONST(DNS_CLASS_IN, DNS_TYPE_A, "quux"), cname, &target) == -EUNATCH);
+        assert_se(dns_resource_record_get_cname_target(&DNS_RESOURCE_KEY_CONST(DNS_CLASS_IN, DNS_TYPE_A, ""), cname, &target) == -EUNATCH);
+        assert_se(dns_resource_record_get_cname_target(&DNS_RESOURCE_KEY_CONST(DNS_CLASS_IN, DNS_TYPE_A, "."), cname, &target) == -EUNATCH);
+        assert_se(dns_resource_record_get_cname_target(&DNS_RESOURCE_KEY_CONST(DNS_CLASS_IN, DNS_TYPE_A, "nope.quux.foobar"), cname, &target) == -EUNATCH);
+        assert_se(dns_resource_record_get_cname_target(&DNS_RESOURCE_KEY_CONST(DNS_CLASS_IN, DNS_TYPE_A, "quux.foobar"), cname, &target) == 0);
+        assert_se(streq(target, "wuff.wuff"));
+        target = mfree(target);
+
+        assert_se(cname = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_DNAME, "quux.foobar"));
+        assert_se(cname->dname.name = strdup("wuff.wuff"));
+
+        assert_se(dns_resource_record_get_cname_target(&DNS_RESOURCE_KEY_CONST(DNS_CLASS_IN, DNS_TYPE_A, "waldo"), cname, &target) == -EUNATCH);
+        assert_se(dns_resource_record_get_cname_target(&DNS_RESOURCE_KEY_CONST(DNS_CLASS_IN, DNS_TYPE_A, "foobar"), cname, &target) == -EUNATCH);
+        assert_se(dns_resource_record_get_cname_target(&DNS_RESOURCE_KEY_CONST(DNS_CLASS_IN, DNS_TYPE_A, "quux"), cname, &target) == -EUNATCH);
+        assert_se(dns_resource_record_get_cname_target(&DNS_RESOURCE_KEY_CONST(DNS_CLASS_IN, DNS_TYPE_A, ""), cname, &target) == -EUNATCH);
+        assert_se(dns_resource_record_get_cname_target(&DNS_RESOURCE_KEY_CONST(DNS_CLASS_IN, DNS_TYPE_A, "."), cname, &target) == -EUNATCH);
+        assert_se(dns_resource_record_get_cname_target(&DNS_RESOURCE_KEY_CONST(DNS_CLASS_IN, DNS_TYPE_A, "yupp.quux.foobar"), cname, &target) == 0);
+        assert_se(streq(target, "yupp.wuff.wuff"));
+        target = mfree(target);
+
+        assert_se(dns_resource_record_get_cname_target(&DNS_RESOURCE_KEY_CONST(DNS_CLASS_IN, DNS_TYPE_A, "quux.foobar"), cname, &target) == 0);
+        assert_se(streq(target, "wuff.wuff"));
+}
+
 int main(int argc, char **argv) {
         int i, N;
         _cleanup_globfree_ glob_t g = {};
@@ -116,5 +149,7 @@ int main(int argc, char **argv) {
                         puts("");
         }
 
+        test_dns_resource_record_get_cname_target();
+
         return EXIT_SUCCESS;
 }