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.
This commit is contained in:
Lennart Poettering 2015-07-28 18:38:54 +02:00
parent 87b46c575a
commit 1086182d83
3 changed files with 44 additions and 2 deletions

View File

@ -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;

View File

@ -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);

View File

@ -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;
}