From: Dmitry V. Levin Date: Tue, 11 Jul 2023 08:00:00 +0000 (+0000) Subject: resolved: fix the canonical name returned by hosts lookup by name X-Git-Tag: v254-rc2~11^2 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=refs%2Fpull%2F28370%2Fhead;p=thirdparty%2Fsystemd.git resolved: fix the canonical name returned by hosts lookup by name In etc_hosts_lookup_by_name(), return the canonical name of the resolved address instead of the name used to obtain that address. Resolves: #20158 --- diff --git a/src/resolve/resolved-etc-hosts.c b/src/resolve/resolved-etc-hosts.c index fd5c6b78148..6af160a477f 100644 --- a/src/resolve/resolved-etc-hosts.c +++ b/src/resolve/resolved-etc-hosts.c @@ -395,6 +395,31 @@ static int answer_add_ptr(DnsAnswer *answer, DnsResourceKey *key, const char *na return dns_answer_add(answer, rr, 0, DNS_ANSWER_AUTHENTICATED, NULL); } +static int answer_add_cname(DnsAnswer *answer, const char *name, const char *cname) { + _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL; + + rr = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_CNAME, name); + if (!rr) + return -ENOMEM; + + rr->cname.name = strdup(cname); + if (!rr->cname.name) + return -ENOMEM; + + return dns_answer_add(answer, rr, 0, DNS_ANSWER_AUTHENTICATED, NULL); +} + +static int answer_add_addr(DnsAnswer *answer, const char *name, const struct in_addr_data *a) { + _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL; + int r; + + r = dns_resource_record_new_address(&rr, a->family, &a->address, name); + if (r < 0) + return r; + + return dns_answer_add(answer, rr, 0, DNS_ANSWER_AUTHENTICATED, NULL); +} + static int etc_hosts_lookup_by_address( EtcHosts *hosts, DnsQuestion *q, @@ -510,17 +535,26 @@ static int etc_hosts_lookup_by_name( } SET_FOREACH(a, item ? item->addresses : NULL) { - _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL; + EtcHostsItemByAddress *item_by_addr; + const char *canonical_name; if ((!found_a && a->family == AF_INET) || (!found_aaaa && a->family == AF_INET6)) continue; - r = dns_resource_record_new_address(&rr, a->family, &a->address, item->name); - if (r < 0) - return r; + item_by_addr = hashmap_get(hosts->by_address, a); + if (item_by_addr && item_by_addr->canonical_name) + canonical_name = item_by_addr->canonical_name; + else + canonical_name = item->name; + + if (!streq(item->name, canonical_name)) { + r = answer_add_cname(*answer, item->name, canonical_name); + if (r < 0) + return r; + } - r = dns_answer_add(*answer, rr, 0, DNS_ANSWER_AUTHENTICATED, NULL); + r = answer_add_addr(*answer, canonical_name, a); if (r < 0) return r; } diff --git a/test/units/testsuite-75.sh b/test/units/testsuite-75.sh index 504d1038e5e..5445c152c97 100755 --- a/test/units/testsuite-75.sh +++ b/test/units/testsuite-75.sh @@ -300,6 +300,15 @@ run getent -s resolve hosts 127.128.0.5 grep -qEx '127\.128\.0\.5\s+localhost5(\s+localhost5?\.localdomain[45]?){4}' "$RUN_OUT" [ "$(wc -l <"$RUN_OUT")" -eq 1 ] +# Issue: https://github.com/systemd/systemd/issues/20158 +run dig +noall +answer +additional localhost5. +grep -qEx 'localhost5\.\s+0\s+IN\s+A\s+127\.128\.0\.5' "$RUN_OUT" +[ "$(wc -l <"$RUN_OUT")" -eq 1 ] +run dig +noall +answer +additional localhost5.localdomain4. +grep -qEx 'localhost5\.localdomain4\.\s+0\s+IN\s+CNAME\s+localhost5\.' "$RUN_OUT" +grep -qEx 'localhost5\.\s+0\s+IN\s+A\s+127\.128\.0\.5' "$RUN_OUT" +[ "$(wc -l <"$RUN_OUT")" -eq 2 ] + : "--- Basic resolved tests ---" # Issue: https://github.com/systemd/systemd/issues/22229 # PR: https://github.com/systemd/systemd/pull/22231