summaryrefslogtreecommitdiff
path: root/src/resolve/resolved-dns-transaction.c
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2014-08-06 16:15:35 +0200
committerLennart Poettering <lennart@poettering.net>2014-08-11 15:06:22 +0200
commita407657425a3e47fd2b559cd3bc800f791303f63 (patch)
tree9d7dd0f9a286eb364769d9d39c6cdfce36e0a18a /src/resolve/resolved-dns-transaction.c
parent3ef77d0476046a660c1b4704140797c447e6ce3a (diff)
resolved: implement full LLMNR conflict detection logic
Diffstat (limited to 'src/resolve/resolved-dns-transaction.c')
-rw-r--r--src/resolve/resolved-dns-transaction.c24
1 files changed, 21 insertions, 3 deletions
diff --git a/src/resolve/resolved-dns-transaction.c b/src/resolve/resolved-dns-transaction.c
index a2e4f2ce95..e76940e18e 100644
--- a/src/resolve/resolved-dns-transaction.c
+++ b/src/resolve/resolved-dns-transaction.c
@@ -132,6 +132,15 @@ static void dns_transaction_tentative(DnsTransaction *t, DnsPacket *p) {
t->scope->link ? t->scope->link->name : "*",
t->scope->family == AF_UNSPEC ? "*" : af_to_name(t->scope->family));
+ /* RFC 4795, Section 4.1 says that the peer with the
+ * lexicographically smaller IP address loses */
+ if (memcmp(&p->sender, &p->destination, FAMILY_ADDRESS_SIZE(p->family)) < 0) {
+ log_debug("Peer has lexicographically smaller IP address and thus lost in the conflict.");
+ return;
+ }
+
+ log_debug("We have the lexicographically smaller IP address and thus lost in the conflict.");
+
t->block_gc++;
SET_FOREACH(z, t->zone_items, i)
dns_zone_item_conflict(z);
@@ -196,6 +205,14 @@ static int on_stream_complete(DnsStream *s, int error) {
return 0;
}
+ if (dns_packet_validate_reply(p) <= 0) {
+ log_debug("Invalid LLMNR TCP packet.");
+ dns_transaction_complete(t, DNS_TRANSACTION_INVALID_REPLY);
+ return 0;
+ }
+
+ dns_scope_check_conflicts(t->scope, p);
+
t->block_gc++;
dns_transaction_process_reply(t, p);
t->block_gc--;
@@ -370,7 +387,7 @@ void dns_transaction_process_reply(DnsTransaction *t, DnsPacket *p) {
}
/* According to RFC 4795, section 2.9. only the RRs from the answer section shall be cached */
- dns_cache_put(&t->scope->cache, p->question, DNS_PACKET_RCODE(p), p->answer, DNS_PACKET_ANCOUNT(p), 0);
+ dns_cache_put(&t->scope->cache, p->question, DNS_PACKET_RCODE(p), p->answer, DNS_PACKET_ANCOUNT(p), 0, p->family, &p->sender);
if (DNS_PACKET_RCODE(p) == DNS_RCODE_SUCCESS)
dns_transaction_complete(t, DNS_TRANSACTION_SUCCESS);
@@ -507,7 +524,8 @@ int dns_transaction_go(DnsTransaction *t) {
t->scope->manager->event,
&t->timeout_event_source,
clock_boottime_or_monotonic(),
- now(clock_boottime_or_monotonic()) + jitter, LLMNR_JITTER_INTERVAL_USEC,
+ now(clock_boottime_or_monotonic()) + jitter,
+ LLMNR_JITTER_INTERVAL_USEC,
on_transaction_timeout, t);
if (r < 0)
return r;
@@ -542,7 +560,7 @@ int dns_transaction_go(DnsTransaction *t) {
r = dns_transaction_open_tcp(t);
} else {
/* Try via UDP, and if that fails due to large size try via TCP */
- r = dns_scope_send(t->scope, t->sent);
+ r = dns_scope_emit(t->scope, t->sent);
if (r == -EMSGSIZE)
r = dns_transaction_open_tcp(t);
}