summaryrefslogtreecommitdiff
path: root/src/resolve
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2015-12-09 17:49:05 +0100
committerLennart Poettering <lennart@poettering.net>2015-12-10 11:35:52 +0100
commit8af5b883227ac8dfa796742b9edcc1647a5d4d6c (patch)
tree17f4a76584218ae8f126e8d6e95b98b189359c1f /src/resolve
parent8b5b5649474ca1d4c1f27f41ed767f16a7a2f14c (diff)
resolved: split out check whether reply matches our question
It's complicated enough, it deserves its own call. (Also contains some unrelated whitespace, comment and assertion changes)
Diffstat (limited to 'src/resolve')
-rw-r--r--src/resolve/resolved-dns-packet.c24
-rw-r--r--src/resolve/resolved-dns-packet.h2
-rw-r--r--src/resolve/resolved-dns-transaction.c21
3 files changed, 40 insertions, 7 deletions
diff --git a/src/resolve/resolved-dns-packet.c b/src/resolve/resolved-dns-packet.c
index b9c2dee557..399ba59749 100644
--- a/src/resolve/resolved-dns-packet.c
+++ b/src/resolve/resolved-dns-packet.c
@@ -2021,6 +2021,30 @@ finish:
return r;
}
+int dns_packet_is_reply_for(DnsPacket *p, const DnsResourceKey *key) {
+ int r;
+
+ assert(p);
+ assert(key);
+
+ /* Checks if the specified packet is a reply for the specified
+ * key and the specified key is the only one in the question
+ * section. */
+
+ if (DNS_PACKET_QR(p) != 1)
+ return 0;
+
+ /* Let's unpack the packet, if that hasn't happened yet. */
+ r = dns_packet_extract(p);
+ if (r < 0)
+ return r;
+
+ if (p->question->n_keys != 1)
+ return 0;
+
+ return dns_resource_key_equal(p->question->keys[0], key);
+}
+
static const char* const dns_rcode_table[_DNS_RCODE_MAX_DEFINED] = {
[DNS_RCODE_SUCCESS] = "SUCCESS",
[DNS_RCODE_FORMERR] = "FORMERR",
diff --git a/src/resolve/resolved-dns-packet.h b/src/resolve/resolved-dns-packet.h
index b0b8600232..5b6a71dc01 100644
--- a/src/resolve/resolved-dns-packet.h
+++ b/src/resolve/resolved-dns-packet.h
@@ -161,6 +161,8 @@ int dns_packet_validate(DnsPacket *p);
int dns_packet_validate_reply(DnsPacket *p);
int dns_packet_validate_query(DnsPacket *p);
+int dns_packet_is_reply_for(DnsPacket *p, const DnsResourceKey *key);
+
int dns_packet_append_blob(DnsPacket *p, const void *d, size_t sz, size_t *start);
int dns_packet_append_uint8(DnsPacket *p, uint8_t v, size_t *start);
int dns_packet_append_uint16(DnsPacket *p, uint16_t v, size_t *start);
diff --git a/src/resolve/resolved-dns-transaction.c b/src/resolve/resolved-dns-transaction.c
index 90f07e6c4b..b83aef5f35 100644
--- a/src/resolve/resolved-dns-transaction.c
+++ b/src/resolve/resolved-dns-transaction.c
@@ -428,12 +428,13 @@ void dns_transaction_process_reply(DnsTransaction *t, DnsPacket *p) {
assert_se(sd_event_now(t->scope->manager->event, clock_boottime_or_monotonic(), &ts) >= 0);
switch (t->scope->protocol) {
+
case DNS_PROTOCOL_DNS:
assert(t->server);
if (IN_SET(DNS_PACKET_RCODE(p), DNS_RCODE_FORMERR, DNS_RCODE_SERVFAIL, DNS_RCODE_NOTIMP)) {
- /* request failed, immediately try again with reduced features */
+ /* Request failed, immediately try again with reduced features */
log_debug("Server returned error: %s", dns_rcode_to_string(DNS_PACKET_RCODE(p)));
dns_server_packet_failed(t->server, t->current_features);
@@ -449,13 +450,14 @@ void dns_transaction_process_reply(DnsTransaction *t, DnsPacket *p) {
dns_server_packet_received(t->server, t->current_features, ts - t->start_usec, p->size);
break;
+
case DNS_PROTOCOL_LLMNR:
case DNS_PROTOCOL_MDNS:
dns_scope_packet_received(t->scope, ts - t->start_usec);
-
break;
+
default:
- break;
+ assert_not_reached("Invalid DNS protocol.");
}
if (DNS_PACKET_TC(p)) {
@@ -474,7 +476,7 @@ void dns_transaction_process_reply(DnsTransaction *t, DnsPacket *p) {
return;
}
if (r < 0) {
- /* On LLMNR and mDNS, if we cannot connect to the host,
+ /* On LLMNR, if we cannot connect to the host,
* we immediately give up */
if (t->scope->protocol == DNS_PROTOCOL_LLMNR) {
dns_transaction_complete(t, DNS_TRANSACTION_RESOURCES);
@@ -494,7 +496,7 @@ void dns_transaction_process_reply(DnsTransaction *t, DnsPacket *p) {
}
}
- /* Parse and update the cache */
+ /* Parse message, if it isn't parsed yet. */
r = dns_packet_extract(p);
if (r < 0) {
dns_transaction_complete(t, DNS_TRANSACTION_INVALID_REPLY);
@@ -503,7 +505,12 @@ void dns_transaction_process_reply(DnsTransaction *t, DnsPacket *p) {
if (t->scope->protocol == DNS_PROTOCOL_DNS) {
/* Only consider responses with equivalent query section to the request */
- if (p->question->n_keys != 1 || dns_resource_key_equal(p->question->keys[0], t->key) <= 0) {
+ r = dns_packet_is_reply_for(p, t->key);
+ if (r < 0) {
+ dns_transaction_complete(t, DNS_TRANSACTION_RESOURCES);
+ return;
+ }
+ if (r == 0) {
dns_transaction_complete(t, DNS_TRANSACTION_INVALID_REPLY);
return;
}
@@ -549,7 +556,7 @@ static int on_dns_packet(sd_event_source *s, int fd, uint32_t revents, void *use
DNS_PACKET_ID(p) == t->id)
dns_transaction_process_reply(t, p);
else
- log_debug("Invalid DNS packet.");
+ log_debug("Invalid DNS packet, ignoring.");
return 0;
}