summaryrefslogtreecommitdiff
path: root/src/resolve
diff options
context:
space:
mode:
Diffstat (limited to 'src/resolve')
-rw-r--r--src/resolve/dns-type.c2
-rw-r--r--src/resolve/resolved-dns-packet.c51
-rw-r--r--src/resolve/resolved-dns-question.c40
-rw-r--r--src/resolve/resolved-dns-question.h2
-rw-r--r--src/resolve/resolved-dns-transaction.c4
5 files changed, 69 insertions, 30 deletions
diff --git a/src/resolve/dns-type.c b/src/resolve/dns-type.c
index e1087b3219..63b4b36e88 100644
--- a/src/resolve/dns-type.c
+++ b/src/resolve/dns-type.c
@@ -44,7 +44,7 @@ int dns_type_from_string(const char *s) {
return sc->id;
}
-/* XXX: find an authorotative list of all pseudo types? */
+/* XXX: find an authoritative list of all pseudo types? */
bool dns_type_is_pseudo(int n) {
return IN_SET(n, DNS_TYPE_ANY, DNS_TYPE_AXFR, DNS_TYPE_IXFR, DNS_TYPE_OPT);
}
diff --git a/src/resolve/resolved-dns-packet.c b/src/resolve/resolved-dns-packet.c
index 649e8b74e1..39951a362c 100644
--- a/src/resolve/resolved-dns-packet.c
+++ b/src/resolve/resolved-dns-packet.c
@@ -508,23 +508,21 @@ static int dns_packet_append_type_window(DnsPacket *p, uint8_t window, uint8_t l
assert(p);
assert(types);
+ assert(length > 0);
saved_size = p->size;
- if (length != 0) {
-
- r = dns_packet_append_uint8(p, window, NULL);
- if (r < 0)
- goto fail;
+ r = dns_packet_append_uint8(p, window, NULL);
+ if (r < 0)
+ goto fail;
- r = dns_packet_append_uint8(p, length, NULL);
- if (r < 0)
- goto fail;
+ r = dns_packet_append_uint8(p, length, NULL);
+ if (r < 0)
+ goto fail;
- r = dns_packet_append_blob(p, types, length, NULL);
- if (r < 0)
- goto fail;
- }
+ r = dns_packet_append_blob(p, types, length, NULL);
+ if (r < 0)
+ goto fail;
if (start)
*start = saved_size;
@@ -538,7 +536,7 @@ fail:
static int dns_packet_append_types(DnsPacket *p, Bitmap *types, size_t *start) {
Iterator i;
uint8_t window = 0;
- uint8_t len = 0;
+ uint8_t entry = 0;
uint8_t bitmaps[32] = {};
unsigned n;
size_t saved_size;
@@ -550,30 +548,24 @@ static int dns_packet_append_types(DnsPacket *p, Bitmap *types, size_t *start) {
saved_size = p->size;
BITMAP_FOREACH(n, types, i) {
- uint8_t entry;
-
assert(n <= 0xffff);
- if ((n << 8) != window) {
- r = dns_packet_append_type_window(p, window, len, bitmaps, NULL);
+ if ((n >> 8) != window && bitmaps[entry / 8] != 0) {
+ r = dns_packet_append_type_window(p, window, entry / 8 + 1, bitmaps, NULL);
if (r < 0)
goto fail;
- if (len > 0) {
- len = 0;
- zero(bitmaps);
- }
+ zero(bitmaps);
}
- window = n << 8;
- len ++;
+ window = n >> 8;
entry = n & 255;
bitmaps[entry / 8] |= 1 << (7 - (entry % 8));
}
- r = dns_packet_append_type_window(p, window, len, bitmaps, NULL);
+ r = dns_packet_append_type_window(p, window, entry / 8 + 1, bitmaps, NULL);
if (r < 0)
goto fail;
@@ -1164,6 +1156,7 @@ static int dns_packet_read_type_window(DnsPacket *p, Bitmap **types, size_t *sta
uint8_t window;
uint8_t length;
const uint8_t *bitmap;
+ uint8_t bit = 0;
unsigned i;
bool found = false;
size_t saved_rindex;
@@ -1195,10 +1188,10 @@ static int dns_packet_read_type_window(DnsPacket *p, Bitmap **types, size_t *sta
for (i = 0; i < length; i++) {
uint8_t bitmask = 1 << 7;
- uint8_t bit = 0;
if (!bitmap[i]) {
found = false;
+ bit += 8;
continue;
}
@@ -1673,8 +1666,12 @@ int dns_packet_read_rr(DnsPacket *p, DnsResourceRecord **ret, size_t *start) {
if (r < 0)
goto fail;
- /* NSEC RRs with empty bitmpas makes no sense, but the RFC does not explicitly forbid them
- so we allow it */
+ /* The types bitmap must contain at least the NSEC record itself, so an empty bitmap means
+ something went wrong */
+ if (bitmap_isclear(rr->nsec.types)) {
+ r = -EBADMSG;
+ goto fail;
+ }
break;
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;
}