summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/resolve/resolved-dns-answer.c23
-rw-r--r--src/resolve/resolved-dns-answer.h1
-rw-r--r--src/resolve/resolved-dns-cache.c9
-rw-r--r--src/resolve/resolved-dns-question.c2
-rw-r--r--src/resolve/resolved-dns-rr.c22
-rw-r--r--src/resolve/resolved-dns-rr.h2
-rw-r--r--src/resolve/resolved-dns-transaction.c2
7 files changed, 47 insertions, 14 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;
diff --git a/src/resolve/resolved-dns-answer.h b/src/resolve/resolved-dns-answer.h
index 8d95131dbe..56b462ed7e 100644
--- a/src/resolve/resolved-dns-answer.h
+++ b/src/resolve/resolved-dns-answer.h
@@ -57,6 +57,7 @@ int dns_answer_match_key(DnsAnswer *a, const DnsResourceKey *key);
int dns_answer_contains_rr(DnsAnswer *a, DnsResourceRecord *rr);
int dns_answer_find_soa(DnsAnswer *a, const DnsResourceKey *key, DnsResourceRecord **ret);
+int dns_answer_find_cname_or_dname(DnsAnswer *a, const DnsResourceKey *key, DnsResourceRecord **ret);
int dns_answer_merge(DnsAnswer *a, DnsAnswer *b, DnsAnswer **ret);
int dns_answer_extend(DnsAnswer **a, DnsAnswer *b);
diff --git a/src/resolve/resolved-dns-cache.c b/src/resolve/resolved-dns-cache.c
index 4aacc268e2..008277ab09 100644
--- a/src/resolve/resolved-dns-cache.c
+++ b/src/resolve/resolved-dns-cache.c
@@ -479,6 +479,15 @@ int dns_cache_put(
if (r > 0)
return 0;
+ /* But not if it has a matching CNAME/DNAME (the negative
+ * caching will be done on the canonical name, not on the
+ * alias) */
+ r = dns_answer_find_cname_or_dname(answer, key, NULL);
+ if (r < 0)
+ goto fail;
+ if (r > 0)
+ return 0;
+
/* See https://tools.ietf.org/html/rfc2308, which say that a
* matching SOA record in the packet is used to to enable
* negative caching. */
diff --git a/src/resolve/resolved-dns-question.c b/src/resolve/resolved-dns-question.c
index 3249448d3b..4ed7434d3c 100644
--- a/src/resolve/resolved-dns-question.c
+++ b/src/resolve/resolved-dns-question.c
@@ -117,7 +117,7 @@ int dns_question_matches_cname(DnsQuestion *q, DnsResourceRecord *rr, const char
return 0;
for (i = 0; i < q->n_keys; i++) {
- r = dns_resource_key_match_cname(q->keys[i], rr, search_domain);
+ r = dns_resource_key_match_cname_or_dname(q->keys[i], rr->key, search_domain);
if (r != 0)
return r;
}
diff --git a/src/resolve/resolved-dns-rr.c b/src/resolve/resolved-dns-rr.c
index 55e85eec2b..74c9d87319 100644
--- a/src/resolve/resolved-dns-rr.c
+++ b/src/resolve/resolved-dns-rr.c
@@ -220,19 +220,19 @@ int dns_resource_key_match_rr(const DnsResourceKey *key, const DnsResourceRecord
return 0;
}
-int dns_resource_key_match_cname(const DnsResourceKey *key, const DnsResourceRecord *rr, const char *search_domain) {
+int dns_resource_key_match_cname_or_dname(const DnsResourceKey *key, const DnsResourceKey *cname, const char *search_domain) {
int r;
assert(key);
- assert(rr);
+ assert(cname);
- if (rr->key->class != key->class && key->class != DNS_CLASS_ANY)
+ if (cname->class != key->class && key->class != DNS_CLASS_ANY)
return 0;
- if (rr->key->type == DNS_TYPE_CNAME)
- r = dns_name_equal(DNS_RESOURCE_KEY_NAME(key), DNS_RESOURCE_KEY_NAME(rr->key));
- else if (rr->key->type == DNS_TYPE_DNAME)
- r = dns_name_endswith(DNS_RESOURCE_KEY_NAME(key), DNS_RESOURCE_KEY_NAME(rr->key));
+ if (cname->type == DNS_TYPE_CNAME)
+ r = dns_name_equal(DNS_RESOURCE_KEY_NAME(key), DNS_RESOURCE_KEY_NAME(cname));
+ else if (cname->type == DNS_TYPE_DNAME)
+ r = dns_name_endswith(DNS_RESOURCE_KEY_NAME(key), DNS_RESOURCE_KEY_NAME(cname));
else
return 0;
@@ -246,10 +246,10 @@ int dns_resource_key_match_cname(const DnsResourceKey *key, const DnsResourceRec
if (r < 0)
return r;
- if (rr->key->type == DNS_TYPE_CNAME)
- return dns_name_equal(joined, DNS_RESOURCE_KEY_NAME(rr->key));
- else if (rr->key->type == DNS_TYPE_DNAME)
- return dns_name_endswith(joined, DNS_RESOURCE_KEY_NAME(rr->key));
+ if (cname->type == DNS_TYPE_CNAME)
+ return dns_name_equal(joined, DNS_RESOURCE_KEY_NAME(cname));
+ else if (cname->type == DNS_TYPE_DNAME)
+ return dns_name_endswith(joined, DNS_RESOURCE_KEY_NAME(cname));
}
return 0;
diff --git a/src/resolve/resolved-dns-rr.h b/src/resolve/resolved-dns-rr.h
index 4c0f72eea3..632ee59994 100644
--- a/src/resolve/resolved-dns-rr.h
+++ b/src/resolve/resolved-dns-rr.h
@@ -246,7 +246,7 @@ DnsResourceKey* dns_resource_key_unref(DnsResourceKey *key);
bool dns_resource_key_is_address(const DnsResourceKey *key);
int dns_resource_key_equal(const DnsResourceKey *a, const DnsResourceKey *b);
int dns_resource_key_match_rr(const DnsResourceKey *key, const DnsResourceRecord *rr, const char *search_domain);
-int dns_resource_key_match_cname(const DnsResourceKey *key, const DnsResourceRecord *rr, const char *search_domain);
+int dns_resource_key_match_cname_or_dname(const DnsResourceKey *key, const DnsResourceKey *cname, const char *search_domain);
int dns_resource_key_match_soa(const DnsResourceKey *key, const DnsResourceKey *soa);
int dns_resource_key_to_string(const DnsResourceKey *key, char **ret);
DEFINE_TRIVIAL_CLEANUP_FUNC(DnsResourceKey*, dns_resource_key_unref);
diff --git a/src/resolve/resolved-dns-transaction.c b/src/resolve/resolved-dns-transaction.c
index efed761001..61be38a6cd 100644
--- a/src/resolve/resolved-dns-transaction.c
+++ b/src/resolve/resolved-dns-transaction.c
@@ -1390,7 +1390,7 @@ int dns_transaction_validate_dnssec(DnsTransaction *t) {
}
/* Is this a CNAME for a record we were looking for? If so, it's also fatal for the whole transaction */
- r = dns_resource_key_match_cname(t->key, rr, NULL);
+ r = dns_resource_key_match_cname_or_dname(t->key, rr->key, NULL);
if (r < 0)
return r;
if (r > 0) {