summaryrefslogtreecommitdiff
path: root/src/resolve/resolved-dns-answer.c
diff options
context:
space:
mode:
authorTom Gundersen <teg@jklm.no>2015-12-02 18:46:32 +0100
committerTom Gundersen <teg@jklm.no>2015-12-10 17:04:42 +0100
commit5d27351f8546530cf779847b0b04b0172c09f9d0 (patch)
tree62e92deaf7a4a8c604d4c9905d3b2c1e87ba082e /src/resolve/resolved-dns-answer.c
parent553947b77c3232d5795cbb2cd1129e74cb11c86d (diff)
resolved: cache - do negative caching only on the canonical name
Apart from dropping redundant information, this fixes an issue where, due to broken DNS servers, we can only be certain of whether an apparent NODATA response is in fact an NXDOMAIN response after explicitly resolving the canonical name. This issue is outlined in RFC2308. Moreover, by caching NXDOMAIN for an existing name, we would mistakenly return NXDOMAIN for types which should not be redirected. I.e., a query for AAAA on test-nx-1.jklm.no correctly returns NXDOMAIN, but a query for CNAME should return the record and a query for DNAME should return NODATA. Note that this means we will not cache an NXDOMAIN response in the presence of redirection, meaning one redundant roundtrip in case the name is queried again.
Diffstat (limited to 'src/resolve/resolved-dns-answer.c')
-rw-r--r--src/resolve/resolved-dns-answer.c23
1 files changed, 23 insertions, 0 deletions
diff --git a/src/resolve/resolved-dns-answer.c b/src/resolve/resolved-dns-answer.c
index de8c4d9dd3..55e6ffbad7 100644
--- a/src/resolve/resolved-dns-answer.c
+++ b/src/resolve/resolved-dns-answer.c
@@ -249,6 +249,29 @@ int dns_answer_find_soa(DnsAnswer *a, const DnsResourceKey *key, DnsResourceReco
return 0;
}
+int dns_answer_find_cname_or_dname(DnsAnswer *a, const DnsResourceKey *key, DnsResourceRecord **ret) {
+ DnsResourceRecord *rr;
+
+ assert(key);
+
+ if (!a)
+ return 0;
+
+ /* For a {C,D}NAME record we can never find a matching {C,D}NAME record */
+ if (key->type == DNS_TYPE_CNAME || key->type == DNS_TYPE_DNAME)
+ return 0;
+
+ DNS_ANSWER_FOREACH(rr, a) {
+ if (dns_resource_key_match_cname_or_dname(key, rr->key, NULL)) {
+ if (ret)
+ *ret = rr;
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
int dns_answer_merge(DnsAnswer *a, DnsAnswer *b, DnsAnswer **ret) {
_cleanup_(dns_answer_unrefp) DnsAnswer *k = NULL;
int r;