]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
resolved: fix the canonical name returned by hosts lookup by name 28370/head
authorDmitry V. Levin <ldv@strace.io>
Tue, 11 Jul 2023 08:00:00 +0000 (08:00 +0000)
committerDmitry V. Levin <ldv@strace.io>
Fri, 14 Jul 2023 13:13:53 +0000 (13:13 +0000)
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

src/resolve/resolved-etc-hosts.c
test/units/testsuite-75.sh

index fd5c6b78148794ea2c40c2e734c71d68c8509084..6af160a477fa02b2ecd8e69f61b6ea1c19bb661f 100644 (file)
@@ -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;
         }
index 504d1038e5e648ed3ed1fa27cd2b127120aff860..5445c152c97c2f099a170c910cf00ec3485bef41 100755 (executable)
@@ -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