From 1086182d83d4c02a75f96f0184d5e8e5d3af6528 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 28 Jul 2015 18:38:54 +0200 Subject: resolved: compare dns question arrays properly Let's optimize things a bit and properly compare DNS question arrays, instead of checking if they are mutual supersets. This also makes ANY query handling more accurate. --- src/resolve/resolved-dns-question.c | 40 ++++++++++++++++++++++++++++++++++ src/resolve/resolved-dns-question.h | 2 ++ src/resolve/resolved-dns-transaction.c | 4 ++-- 3 files changed, 44 insertions(+), 2 deletions(-) (limited to 'src/resolve') diff --git a/src/resolve/resolved-dns-question.c b/src/resolve/resolved-dns-question.c index 4d71f5e3d4..0efe740d1a 100644 --- a/src/resolve/resolved-dns-question.c +++ b/src/resolve/resolved-dns-question.c @@ -188,6 +188,46 @@ int dns_question_is_superset(DnsQuestion *q, DnsQuestion *other) { return 1; } +int dns_question_contains(DnsQuestion *a, DnsResourceKey *k) { + unsigned j; + int r; + + assert(a); + assert(k); + + for (j = 0; j < a->n_keys; j++) { + r = dns_resource_key_equal(a->keys[j], k); + if (r != 0) + return r; + } + + return 0; +} + +int dns_question_is_equal(DnsQuestion *a, DnsQuestion *b) { + unsigned j; + int r; + + assert(a); + assert(b); + + /* Checks if all keys in a are also contained b, and vice versa */ + + for (j = 0; j < a->n_keys; j++) { + r = dns_question_contains(b, a->keys[j]); + if (r <= 0) + return r; + } + + for (j = 0; j < b->n_keys; j++) { + r = dns_question_contains(a, b->keys[j]); + if (r <= 0) + return r; + } + + return 1; +} + int dns_question_cname_redirect(DnsQuestion *q, const char *name, DnsQuestion **ret) { _cleanup_(dns_question_unrefp) DnsQuestion *n = NULL; bool same = true; diff --git a/src/resolve/resolved-dns-question.h b/src/resolve/resolved-dns-question.h index 4ba2fe9f0e..fc98677798 100644 --- a/src/resolve/resolved-dns-question.h +++ b/src/resolve/resolved-dns-question.h @@ -43,6 +43,8 @@ int dns_question_matches_rr(DnsQuestion *q, DnsResourceRecord *rr); int dns_question_matches_cname(DnsQuestion *q, DnsResourceRecord *rr); int dns_question_is_valid(DnsQuestion *q); int dns_question_is_superset(DnsQuestion *q, DnsQuestion *other); +int dns_question_contains(DnsQuestion *a, DnsResourceKey *k); +int dns_question_is_equal(DnsQuestion *a, DnsQuestion *b); int dns_question_cname_redirect(DnsQuestion *q, const char *name, DnsQuestion **ret); diff --git a/src/resolve/resolved-dns-transaction.c b/src/resolve/resolved-dns-transaction.c index b235fda3d2..8a93b265c6 100644 --- a/src/resolve/resolved-dns-transaction.c +++ b/src/resolve/resolved-dns-transaction.c @@ -406,8 +406,8 @@ void dns_transaction_process_reply(DnsTransaction *t, DnsPacket *p) { } /* Only consider responses with equivalent query section to the request */ - if (!dns_question_is_superset(p->question, t->question) || - !dns_question_is_superset(t->question, p->question)) { + r = dns_question_is_equal(p->question, t->question); + if (r <= 0) { dns_transaction_complete(t, DNS_TRANSACTION_INVALID_REPLY); return; } -- cgit v1.2.3-54-g00ecf