1
0
mirror of https://github.com/systemd/systemd.git synced 2024-10-31 16:21:26 +03:00

resolved: add dns_resource_record_get_cname_target() helper

This determines the redirection target from a CNAME or DNAME RR given it
matches some given RR key.
This commit is contained in:
Lennart Poettering 2021-02-22 23:07:01 +01:00
parent 990e7e87ad
commit d1f8fbea9f
3 changed files with 79 additions and 0 deletions

View 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;

View 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);

View 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;
}