summaryrefslogtreecommitdiff
path: root/src/resolve/resolved-dns-answer.c
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2014-07-23 00:57:25 +0200
committerLennart Poettering <lennart@poettering.net>2014-07-23 02:00:40 +0200
commit7e8e0422aeb16f2a09a40546c61df753d10029b6 (patch)
treec5fd640ba84c1b3c92367aa4540e90c69c557a0b /src/resolve/resolved-dns-answer.c
parentfaa133f3aa7a18f26563dc5d6b95898cb315c37a (diff)
resolved: implement negative caching
Diffstat (limited to 'src/resolve/resolved-dns-answer.c')
-rw-r--r--src/resolve/resolved-dns-answer.c64
1 files changed, 64 insertions, 0 deletions
diff --git a/src/resolve/resolved-dns-answer.c b/src/resolve/resolved-dns-answer.c
index fbc282550e..34c854cb3a 100644
--- a/src/resolve/resolved-dns-answer.c
+++ b/src/resolve/resolved-dns-answer.c
@@ -20,6 +20,7 @@
***/
#include "resolved-dns-answer.h"
+#include "resolved-dns-domain.h"
DnsAnswer *dns_answer_new(unsigned n) {
DnsAnswer *a;
@@ -65,12 +66,75 @@ DnsAnswer *dns_answer_unref(DnsAnswer *a) {
}
int dns_answer_add(DnsAnswer *a, DnsResourceRecord *rr) {
+ unsigned i;
+ int r;
+
assert(a);
assert(rr);
+ for (i = 0; i < a->n_rrs; i++) {
+ r = dns_resource_record_equal(a->rrs[i], rr);
+ if (r < 0)
+ return r;
+ if (r > 0) {
+ /* Entry already exists, keep the entry with
+ * the higher RR, or the one with TTL 0 */
+
+ if (rr->ttl == 0 || (rr->ttl > a->rrs[i]->ttl && a->rrs[i]->ttl != 0)) {
+ dns_resource_record_ref(rr);
+ dns_resource_record_unref(a->rrs[i]);
+ a->rrs[i] = rr;
+ }
+
+ return 0;
+ }
+ }
+
if (a->n_rrs >= a->n_allocated)
return -ENOSPC;
a->rrs[a->n_rrs++] = dns_resource_record_ref(rr);
+ return 1;
+}
+
+int dns_answer_contains(DnsAnswer *a, DnsResourceKey *key) {
+ unsigned i;
+ int r;
+
+ assert(a);
+ assert(key);
+
+ for (i = 0; i < a->n_rrs; i++) {
+ r = dns_resource_key_match_rr(key, a->rrs[i]);
+ if (r < 0)
+ return r;
+ if (r > 0)
+ return 1;
+ }
+
+ return 0;
+}
+
+int dns_answer_find_soa(DnsAnswer *a, DnsResourceKey *key, DnsResourceRecord **ret) {
+ unsigned i;
+
+ assert(a);
+ assert(key);
+ assert(ret);
+
+ for (i = 0; i < a->n_rrs; i++) {
+
+ if (a->rrs[i]->key->class != DNS_CLASS_IN)
+ continue;
+
+ if (a->rrs[i]->key->type != DNS_TYPE_SOA)
+ continue;
+
+ if (dns_name_endswith(DNS_RESOURCE_KEY_NAME(key), DNS_RESOURCE_KEY_NAME(a->rrs[i]->key))) {
+ *ret = a->rrs[i];
+ return 1;
+ }
+ }
+
return 0;
}