assert(t);
assert(!IN_SET(state, DNS_TRANSACTION_NULL, DNS_TRANSACTION_PENDING));
- assert(IN_SET(t->state, DNS_TRANSACTION_NULL, DNS_TRANSACTION_PENDING));
+
+ if (!IN_SET(t->state, DNS_TRANSACTION_NULL, DNS_TRANSACTION_PENDING))
+ return;
/* Note that this call might invalidate the query. Callers
* should hence not attempt to access the query or transaction
dns_transaction_stop(t);
- log_debug("Beginning transaction on scope %s on %s/%s",
+ log_debug("Excercising transaction on scope %s on %s/%s",
dns_protocol_to_string(t->scope->protocol),
t->scope->link ? t->scope->link->name : "*",
t->scope->family == AF_UNSPEC ? "*" : af_to_name(t->scope->family));
}
}
+ 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 */
return 0;
}
if (r < 0) {
+ if (t->scope->protocol != DNS_PROTOCOL_DNS) {
+ dns_transaction_complete(t, DNS_TRANSACTION_RESOURCES);
+ return 0;
+ }
+
/* Couldn't send? Try immediately again, with a new server */
dns_scope_next_dns_server(t->scope);