chiark / gitweb /
resolved: add 100ms initial jitter to all LLMNR requests
authorLennart Poettering <lennart@poettering.net>
Tue, 5 Aug 2014 15:01:33 +0000 (17:01 +0200)
committerLennart Poettering <lennart@poettering.net>
Tue, 5 Aug 2014 15:02:46 +0000 (17:02 +0200)
src/resolve/resolved-dns-scope.c
src/resolve/resolved-dns-transaction.c
src/resolve/resolved-dns-transaction.h

index 8d16101dc7042bd84ff9ecce84b6ec179d8aff59..40c326a81d249913f741fc68cefc8711ff34e22d 100644 (file)
@@ -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);
         }
 
index ad1b277555254a4b92efff9520cda20a4750235d..53d6e18dc53b492d72cae392147c546a2d09f39d 100644 (file)
@@ -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 */
index d825b3ec8591daf177f4d4012708280d099a3601..182fb7714c5cb60a3e449b583bad61f5228dc554 100644 (file)
@@ -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