From 6e0684729420912df019cc64d3f8a3c8290cc5f1 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 5 Aug 2014 17:01:33 +0200 Subject: [PATCH] resolved: add 100ms initial jitter to all LLMNR requests --- src/resolve/resolved-dns-scope.c | 5 +++++ src/resolve/resolved-dns-transaction.c | 27 ++++++++++++++++++++++++++ src/resolve/resolved-dns-transaction.h | 4 +++- 3 files changed, 35 insertions(+), 1 deletion(-) diff --git a/src/resolve/resolved-dns-scope.c b/src/resolve/resolved-dns-scope.c index 8d16101dc7..40c326a81d 100644 --- a/src/resolve/resolved-dns-scope.c +++ b/src/resolve/resolved-dns-scope.c @@ -549,6 +549,11 @@ void dns_scope_process_query(DnsScope *s, DnsStream *stream, DnsPacket *p) { return; } + /* Note that we always immediately reply to all LLMNR + * requests, and do not wait any time, since we + * verified uniqueness for all records. Also see RFC + * 4795, Section 2.7 */ + r = manager_send(s->manager, fd, p->ifindex, p->family, &p->sender, p->sender_port, reply); } diff --git a/src/resolve/resolved-dns-transaction.c b/src/resolve/resolved-dns-transaction.c index ad1b277555..53d6e18dc5 100644 --- a/src/resolve/resolved-dns-transaction.c +++ b/src/resolve/resolved-dns-transaction.c @@ -490,6 +490,33 @@ int dns_transaction_go(DnsTransaction *t) { } } + if (t->scope->protocol == DNS_PROTOCOL_LLMNR && !t->initial_jitter) { + usec_t jitter; + + /* RFC 4795 Section 2.7 suggests all queries should be + * delayed by a random time from 0 to JITTER_INTERVAL. */ + + t->initial_jitter = true; + + random_bytes(&jitter, sizeof(jitter)); + jitter %= LLMNR_JITTER_INTERVAL_USEC; + + r = sd_event_add_time( + t->scope->manager->event, + &t->timeout_event_source, + clock_boottime_or_monotonic(), + now(clock_boottime_or_monotonic()) + jitter, LLMNR_JITTER_INTERVAL_USEC, + on_transaction_timeout, t); + if (r < 0) + return r; + + t->n_attempts = 0; + t->state = DNS_TRANSACTION_PENDING; + + log_debug("Delaying LLMNR transaction for " USEC_FMT "us.", jitter); + return 0; + } + log_debug("Cache miss!"); /* Otherwise, we need to ask the network */ diff --git a/src/resolve/resolved-dns-transaction.h b/src/resolve/resolved-dns-transaction.h index d825b3ec85..182fb7714c 100644 --- a/src/resolve/resolved-dns-transaction.h +++ b/src/resolve/resolved-dns-transaction.h @@ -54,6 +54,8 @@ struct DnsTransaction { DnsTransactionState state; uint16_t id; + bool initial_jitter; + DnsPacket *sent, *received; DnsAnswer *cached; int cached_rcode; @@ -96,7 +98,7 @@ DnsTransactionState dns_transaction_state_from_string(const char *s) _pure_; #define LLMNR_TRANSACTION_TIMEOUT_USEC (1 * USEC_PER_SEC) /* LLMNR Jitter interval, see RFC 4795 Section 7 */ -#define LLMNR_TRANSACTION_JITTER_INTERVAL_USEC (100 * USEC_PER_MSEC) +#define LLMNR_JITTER_INTERVAL_USEC (100 * USEC_PER_MSEC) /* Maximum attempts to send DNS requests, across all DNS servers */ #define DNS_TRANSACTION_ATTEMPTS_MAX 8