]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/resolve/resolved-dns-transaction.c
resolved: short-cut jitter callbacks for LLMNR and mDNS
[thirdparty/systemd.git] / src / resolve / resolved-dns-transaction.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4 This file is part of systemd.
5
6 Copyright 2014 Lennart Poettering
7
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
12
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22 #include "af-list.h"
23 #include "alloc-util.h"
24 #include "dns-domain.h"
25 #include "fd-util.h"
26 #include "random-util.h"
27 #include "resolved-dns-transaction.h"
28 #include "resolved-llmnr.h"
29 #include "string-table.h"
30
31 DnsTransaction* dns_transaction_free(DnsTransaction *t) {
32 DnsQueryCandidate *c;
33 DnsZoneItem *i;
34
35 if (!t)
36 return NULL;
37
38 sd_event_source_unref(t->timeout_event_source);
39
40 dns_packet_unref(t->sent);
41 dns_packet_unref(t->received);
42
43 dns_answer_unref(t->answer);
44
45 sd_event_source_unref(t->dns_udp_event_source);
46 safe_close(t->dns_udp_fd);
47
48 dns_server_unref(t->server);
49 dns_stream_free(t->stream);
50
51 if (t->scope) {
52 hashmap_remove_value(t->scope->transactions_by_key, t->key, t);
53 LIST_REMOVE(transactions_by_scope, t->scope->transactions, t);
54
55 if (t->id != 0)
56 hashmap_remove(t->scope->manager->dns_transactions, UINT_TO_PTR(t->id));
57 }
58
59 dns_resource_key_unref(t->key);
60
61 while ((c = set_steal_first(t->query_candidates)))
62 set_remove(c->transactions, t);
63
64 set_free(t->query_candidates);
65
66 while ((i = set_steal_first(t->zone_items)))
67 i->probe_transaction = NULL;
68 set_free(t->zone_items);
69
70 free(t);
71 return NULL;
72 }
73
74 DEFINE_TRIVIAL_CLEANUP_FUNC(DnsTransaction*, dns_transaction_free);
75
76 void dns_transaction_gc(DnsTransaction *t) {
77 assert(t);
78
79 if (t->block_gc > 0)
80 return;
81
82 if (set_isempty(t->query_candidates) && set_isempty(t->zone_items))
83 dns_transaction_free(t);
84 }
85
86 int dns_transaction_new(DnsTransaction **ret, DnsScope *s, DnsResourceKey *key) {
87 _cleanup_(dns_transaction_freep) DnsTransaction *t = NULL;
88 int r;
89
90 assert(ret);
91 assert(s);
92 assert(key);
93
94 r = hashmap_ensure_allocated(&s->manager->dns_transactions, NULL);
95 if (r < 0)
96 return r;
97
98 r = hashmap_ensure_allocated(&s->transactions_by_key, &dns_resource_key_hash_ops);
99 if (r < 0)
100 return r;
101
102 t = new0(DnsTransaction, 1);
103 if (!t)
104 return -ENOMEM;
105
106 t->dns_udp_fd = -1;
107 t->answer_source = _DNS_TRANSACTION_SOURCE_INVALID;
108 t->key = dns_resource_key_ref(key);
109
110 /* Find a fresh, unused transaction id */
111 do
112 random_bytes(&t->id, sizeof(t->id));
113 while (t->id == 0 ||
114 hashmap_get(s->manager->dns_transactions, UINT_TO_PTR(t->id)));
115
116 r = hashmap_put(s->manager->dns_transactions, UINT_TO_PTR(t->id), t);
117 if (r < 0) {
118 t->id = 0;
119 return r;
120 }
121
122 r = hashmap_replace(s->transactions_by_key, t->key, t);
123 if (r < 0) {
124 hashmap_remove(s->manager->dns_transactions, UINT_TO_PTR(t->id));
125 return r;
126 }
127
128 LIST_PREPEND(transactions_by_scope, s->transactions, t);
129 t->scope = s;
130
131 if (ret)
132 *ret = t;
133
134 t = NULL;
135
136 return 0;
137 }
138
139 static void dns_transaction_stop(DnsTransaction *t) {
140 assert(t);
141
142 t->timeout_event_source = sd_event_source_unref(t->timeout_event_source);
143 t->stream = dns_stream_free(t->stream);
144
145 /* Note that we do not drop the UDP socket here, as we want to
146 * reuse it to repeat the interaction. */
147 }
148
149 static void dns_transaction_tentative(DnsTransaction *t, DnsPacket *p) {
150 _cleanup_free_ char *pretty = NULL;
151 DnsZoneItem *z;
152
153 assert(t);
154 assert(p);
155
156 if (manager_our_packet(t->scope->manager, p) != 0)
157 return;
158
159 in_addr_to_string(p->family, &p->sender, &pretty);
160
161 log_debug("Transaction on scope %s on %s/%s got tentative packet from %s",
162 dns_protocol_to_string(t->scope->protocol),
163 t->scope->link ? t->scope->link->name : "*",
164 t->scope->family == AF_UNSPEC ? "*" : af_to_name(t->scope->family),
165 pretty);
166
167 /* RFC 4795, Section 4.1 says that the peer with the
168 * lexicographically smaller IP address loses */
169 if (memcmp(&p->sender, &p->destination, FAMILY_ADDRESS_SIZE(p->family)) >= 0) {
170 log_debug("Peer has lexicographically larger IP address and thus lost in the conflict.");
171 return;
172 }
173
174 log_debug("We have the lexicographically larger IP address and thus lost in the conflict.");
175
176 t->block_gc++;
177 while ((z = set_first(t->zone_items))) {
178 /* First, make sure the zone item drops the reference
179 * to us */
180 dns_zone_item_probe_stop(z);
181
182 /* Secondly, report this as conflict, so that we might
183 * look for a different hostname */
184 dns_zone_item_conflict(z);
185 }
186 t->block_gc--;
187
188 dns_transaction_gc(t);
189 }
190
191 void dns_transaction_complete(DnsTransaction *t, DnsTransactionState state) {
192 DnsQueryCandidate *c;
193 DnsZoneItem *z;
194 Iterator i;
195
196 assert(t);
197 assert(!IN_SET(state, DNS_TRANSACTION_NULL, DNS_TRANSACTION_PENDING));
198
199 /* Note that this call might invalidate the query. Callers
200 * should hence not attempt to access the query or transaction
201 * after calling this function. */
202
203 log_debug("Transaction on scope %s on %s/%s now complete with <%s> from %s",
204 dns_protocol_to_string(t->scope->protocol),
205 t->scope->link ? t->scope->link->name : "*",
206 t->scope->family == AF_UNSPEC ? "*" : af_to_name(t->scope->family),
207 dns_transaction_state_to_string(state),
208 t->answer_source < 0 ? "none" : dns_transaction_source_to_string(t->answer_source));
209
210 t->state = state;
211
212 dns_transaction_stop(t);
213
214 /* Notify all queries that are interested, but make sure the
215 * transaction isn't freed while we are still looking at it */
216 t->block_gc++;
217 SET_FOREACH(c, t->query_candidates, i)
218 dns_query_candidate_ready(c);
219 SET_FOREACH(z, t->zone_items, i)
220 dns_zone_item_ready(z);
221 t->block_gc--;
222
223 dns_transaction_gc(t);
224 }
225
226 static int on_stream_complete(DnsStream *s, int error) {
227 _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
228 DnsTransaction *t;
229
230 assert(s);
231 assert(s->transaction);
232
233 /* Copy the data we care about out of the stream before we
234 * destroy it. */
235 t = s->transaction;
236 p = dns_packet_ref(s->read_packet);
237
238 t->stream = dns_stream_free(t->stream);
239
240 if (error != 0) {
241 dns_transaction_complete(t, DNS_TRANSACTION_RESOURCES);
242 return 0;
243 }
244
245 if (dns_packet_validate_reply(p) <= 0) {
246 log_debug("Invalid LLMNR TCP packet.");
247 dns_transaction_complete(t, DNS_TRANSACTION_INVALID_REPLY);
248 return 0;
249 }
250
251 dns_scope_check_conflicts(t->scope, p);
252
253 t->block_gc++;
254 dns_transaction_process_reply(t, p);
255 t->block_gc--;
256
257 /* If the response wasn't useful, then complete the transition now */
258 if (t->state == DNS_TRANSACTION_PENDING)
259 dns_transaction_complete(t, DNS_TRANSACTION_INVALID_REPLY);
260
261 return 0;
262 }
263
264 static int dns_transaction_open_tcp(DnsTransaction *t) {
265 DnsServer *server = NULL;
266 _cleanup_close_ int fd = -1;
267 int r;
268
269 assert(t);
270
271 if (t->stream)
272 return 0;
273
274 switch (t->scope->protocol) {
275 case DNS_PROTOCOL_DNS:
276 fd = dns_scope_tcp_socket(t->scope, AF_UNSPEC, NULL, 53, &server);
277 break;
278
279 case DNS_PROTOCOL_LLMNR:
280 /* When we already received a reply to this (but it was truncated), send to its sender address */
281 if (t->received)
282 fd = dns_scope_tcp_socket(t->scope, t->received->family, &t->received->sender, t->received->sender_port, NULL);
283 else {
284 union in_addr_union address;
285 int family = AF_UNSPEC;
286
287 /* Otherwise, try to talk to the owner of a
288 * the IP address, in case this is a reverse
289 * PTR lookup */
290
291 r = dns_name_address(DNS_RESOURCE_KEY_NAME(t->key), &family, &address);
292 if (r < 0)
293 return r;
294 if (r == 0)
295 return -EINVAL;
296 if (family != t->scope->family)
297 return -ESRCH;
298
299 fd = dns_scope_tcp_socket(t->scope, family, &address, LLMNR_PORT, NULL);
300 }
301
302 break;
303
304 default:
305 return -EAFNOSUPPORT;
306 }
307
308 if (fd < 0)
309 return fd;
310
311 r = dns_stream_new(t->scope->manager, &t->stream, t->scope->protocol, fd);
312 if (r < 0)
313 return r;
314
315 fd = -1;
316
317 r = dns_stream_write_packet(t->stream, t->sent);
318 if (r < 0) {
319 t->stream = dns_stream_free(t->stream);
320 return r;
321 }
322
323 dns_server_unref(t->server);
324 t->server = dns_server_ref(server);
325 t->received = dns_packet_unref(t->received);
326 t->answer = dns_answer_unref(t->answer);
327 t->answer_rcode = 0;
328 t->stream->complete = on_stream_complete;
329 t->stream->transaction = t;
330
331 /* The interface index is difficult to determine if we are
332 * connecting to the local host, hence fill this in right away
333 * instead of determining it from the socket */
334 if (t->scope->link)
335 t->stream->ifindex = t->scope->link->ifindex;
336
337 return 0;
338 }
339
340 static void dns_transaction_next_dns_server(DnsTransaction *t) {
341 assert(t);
342
343 t->server = dns_server_unref(t->server);
344 t->dns_udp_event_source = sd_event_source_unref(t->dns_udp_event_source);
345 t->dns_udp_fd = safe_close(t->dns_udp_fd);
346
347 dns_scope_next_dns_server(t->scope);
348 }
349
350 void dns_transaction_process_reply(DnsTransaction *t, DnsPacket *p) {
351 usec_t ts;
352 int r;
353
354 assert(t);
355 assert(p);
356 assert(t->state == DNS_TRANSACTION_PENDING);
357 assert(t->scope);
358 assert(t->scope->manager);
359
360 /* Note that this call might invalidate the query. Callers
361 * should hence not attempt to access the query or transaction
362 * after calling this function. */
363
364 switch (t->scope->protocol) {
365 case DNS_PROTOCOL_LLMNR:
366 assert(t->scope->link);
367
368 /* For LLMNR we will not accept any packets from other
369 * interfaces */
370
371 if (p->ifindex != t->scope->link->ifindex)
372 return;
373
374 if (p->family != t->scope->family)
375 return;
376
377 /* Tentative packets are not full responses but still
378 * useful for identifying uniqueness conflicts during
379 * probing. */
380 if (DNS_PACKET_LLMNR_T(p)) {
381 dns_transaction_tentative(t, p);
382 return;
383 }
384
385 break;
386
387 case DNS_PROTOCOL_MDNS:
388 assert(t->scope->link);
389
390 /* For mDNS we will not accept any packets from other interfaces */
391 if (p->ifindex != t->scope->link->ifindex)
392 return;
393
394 if (p->family != t->scope->family)
395 return;
396
397 break;
398
399 case DNS_PROTOCOL_DNS:
400 break;
401
402 default:
403 assert_not_reached("Invalid DNS protocol.");
404 }
405
406 if (t->received != p) {
407 dns_packet_unref(t->received);
408 t->received = dns_packet_ref(p);
409 }
410
411 t->answer_source = DNS_TRANSACTION_NETWORK;
412
413 if (p->ipproto == IPPROTO_TCP) {
414 if (DNS_PACKET_TC(p)) {
415 /* Truncated via TCP? Somebody must be fucking with us */
416 dns_transaction_complete(t, DNS_TRANSACTION_INVALID_REPLY);
417 return;
418 }
419
420 if (DNS_PACKET_ID(p) != t->id) {
421 /* Not the reply to our query? Somebody must be fucking with us */
422 dns_transaction_complete(t, DNS_TRANSACTION_INVALID_REPLY);
423 return;
424 }
425 }
426
427 assert_se(sd_event_now(t->scope->manager->event, clock_boottime_or_monotonic(), &ts) >= 0);
428
429 switch (t->scope->protocol) {
430 case DNS_PROTOCOL_DNS:
431 assert(t->server);
432
433 if (IN_SET(DNS_PACKET_RCODE(p), DNS_RCODE_FORMERR, DNS_RCODE_SERVFAIL, DNS_RCODE_NOTIMP)) {
434
435 /* request failed, immediately try again with reduced features */
436 log_debug("Server returned error: %s", dns_rcode_to_string(DNS_PACKET_RCODE(p)));
437
438 dns_server_packet_failed(t->server, t->current_features);
439
440 r = dns_transaction_go(t);
441 if (r < 0) {
442 dns_transaction_complete(t, DNS_TRANSACTION_RESOURCES);
443 return;
444 }
445
446 return;
447 } else
448 dns_server_packet_received(t->server, t->current_features, ts - t->start_usec, p->size);
449
450 break;
451 case DNS_PROTOCOL_LLMNR:
452 case DNS_PROTOCOL_MDNS:
453 dns_scope_packet_received(t->scope, ts - t->start_usec);
454
455 break;
456 default:
457 break;
458 }
459
460 if (DNS_PACKET_TC(p)) {
461 /* Response was truncated, let's try again with good old TCP */
462 r = dns_transaction_open_tcp(t);
463 if (r == -ESRCH) {
464 /* No servers found? Damn! */
465 dns_transaction_complete(t, DNS_TRANSACTION_NO_SERVERS);
466 return;
467 }
468 if (r < 0) {
469 /* On LLMNR, if we cannot connect to the host,
470 * we immediately give up */
471 if (t->scope->protocol == DNS_PROTOCOL_LLMNR) {
472 dns_transaction_complete(t, DNS_TRANSACTION_RESOURCES);
473 return;
474 }
475
476 /* On DNS, couldn't send? Try immediately again, with a new server */
477 dns_transaction_next_dns_server(t);
478
479 r = dns_transaction_go(t);
480 if (r < 0) {
481 dns_transaction_complete(t, DNS_TRANSACTION_RESOURCES);
482 return;
483 }
484
485 return;
486 }
487 }
488
489 /* Parse and update the cache */
490 r = dns_packet_extract(p);
491 if (r < 0) {
492 dns_transaction_complete(t, DNS_TRANSACTION_INVALID_REPLY);
493 return;
494 }
495
496 /* Only consider responses with equivalent query section to the request */
497 if (p->question->n_keys != 1 || dns_resource_key_equal(p->question->keys[0], t->key) <= 0) {
498 dns_transaction_complete(t, DNS_TRANSACTION_INVALID_REPLY);
499 return;
500 }
501
502 /* Install the answer as answer to the transaction */
503 dns_answer_unref(t->answer);
504 t->answer = dns_answer_ref(p->answer);
505 t->answer_rcode = DNS_PACKET_RCODE(p);
506 t->answer_authenticated = t->scope->dnssec_mode == DNSSEC_TRUST && DNS_PACKET_AD(p);
507
508 /* According to RFC 4795, section 2.9. only the RRs from the answer section shall be cached */
509 if (DNS_PACKET_SHALL_CACHE(p))
510 dns_cache_put(&t->scope->cache,
511 t->key,
512 DNS_PACKET_RCODE(p),
513 p->answer,
514 DNS_PACKET_ANCOUNT(p),
515 t->answer_authenticated,
516 0,
517 p->family,
518 &p->sender);
519
520 if (DNS_PACKET_RCODE(p) == DNS_RCODE_SUCCESS)
521 dns_transaction_complete(t, DNS_TRANSACTION_SUCCESS);
522 else
523 dns_transaction_complete(t, DNS_TRANSACTION_FAILURE);
524 }
525
526 static int on_dns_packet(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
527 _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
528 DnsTransaction *t = userdata;
529 int r;
530
531 assert(t);
532 assert(t->scope);
533
534 r = manager_recv(t->scope->manager, fd, DNS_PROTOCOL_DNS, &p);
535 if (r <= 0)
536 return r;
537
538 if (dns_packet_validate_reply(p) > 0 &&
539 DNS_PACKET_ID(p) == t->id)
540 dns_transaction_process_reply(t, p);
541 else
542 log_debug("Invalid DNS packet.");
543
544 return 0;
545 }
546
547 static int dns_transaction_emit(DnsTransaction *t) {
548 int r;
549
550 assert(t);
551
552 if (t->scope->protocol == DNS_PROTOCOL_DNS && !t->server) {
553 DnsServer *server = NULL;
554 _cleanup_close_ int fd = -1;
555
556 fd = dns_scope_udp_dns_socket(t->scope, &server);
557 if (fd < 0)
558 return fd;
559
560 r = sd_event_add_io(t->scope->manager->event, &t->dns_udp_event_source, fd, EPOLLIN, on_dns_packet, t);
561 if (r < 0)
562 return r;
563
564 t->dns_udp_fd = fd;
565 fd = -1;
566 t->server = dns_server_ref(server);
567 }
568
569 r = dns_scope_emit(t->scope, t->dns_udp_fd, t->server, t->sent);
570 if (r < 0)
571 return r;
572
573 if (t->server)
574 t->current_features = t->server->possible_features;
575
576 return 0;
577 }
578
579 static int on_transaction_timeout(sd_event_source *s, usec_t usec, void *userdata) {
580 DnsTransaction *t = userdata;
581 int r;
582
583 assert(s);
584 assert(t);
585
586 if (!t->initial_jitter_scheduled || t->initial_jitter_elapsed) {
587 /* Timeout reached? Increase the timeout for the server used */
588 switch (t->scope->protocol) {
589 case DNS_PROTOCOL_DNS:
590 assert(t->server);
591
592 dns_server_packet_lost(t->server, t->current_features, usec - t->start_usec);
593
594 break;
595 case DNS_PROTOCOL_LLMNR:
596 case DNS_PROTOCOL_MDNS:
597 dns_scope_packet_lost(t->scope, usec - t->start_usec);
598
599 break;
600 default:
601 assert_not_reached("Invalid DNS protocol.");
602 }
603
604 if (t->initial_jitter_scheduled)
605 t->initial_jitter_elapsed = true;
606 }
607
608 /* ...and try again with a new server */
609 dns_transaction_next_dns_server(t);
610
611 r = dns_transaction_go(t);
612 if (r < 0)
613 dns_transaction_complete(t, DNS_TRANSACTION_RESOURCES);
614
615 return 0;
616 }
617
618 static int dns_transaction_make_packet(DnsTransaction *t) {
619 _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
620 int r;
621
622 assert(t);
623
624 if (t->sent)
625 return 0;
626
627 r = dns_packet_new_query(&p, t->scope->protocol, 0, t->scope->dnssec_mode == DNSSEC_YES);
628 if (r < 0)
629 return r;
630
631 r = dns_scope_good_key(t->scope, t->key);
632 if (r < 0)
633 return r;
634 if (r == 0)
635 return -EDOM;
636
637 r = dns_packet_append_key(p, t->key, NULL);
638 if (r < 0)
639 return r;
640
641 DNS_PACKET_HEADER(p)->qdcount = htobe16(1);
642 DNS_PACKET_HEADER(p)->id = t->id;
643
644 t->sent = p;
645 p = NULL;
646
647 return 0;
648 }
649
650 static usec_t transaction_get_resend_timeout(DnsTransaction *t) {
651 assert(t);
652 assert(t->scope);
653
654 switch (t->scope->protocol) {
655 case DNS_PROTOCOL_DNS:
656 assert(t->server);
657
658 return t->server->resend_timeout;
659 case DNS_PROTOCOL_LLMNR:
660 case DNS_PROTOCOL_MDNS:
661 return t->scope->resend_timeout;
662 default:
663 assert_not_reached("Invalid DNS protocol.");
664 }
665 }
666
667 int dns_transaction_go(DnsTransaction *t) {
668 bool had_stream;
669 usec_t ts;
670 int r;
671
672 assert(t);
673
674 had_stream = !!t->stream;
675
676 dns_transaction_stop(t);
677
678 log_debug("Excercising transaction on scope %s on %s/%s",
679 dns_protocol_to_string(t->scope->protocol),
680 t->scope->link ? t->scope->link->name : "*",
681 t->scope->family == AF_UNSPEC ? "*" : af_to_name(t->scope->family));
682
683 if (t->n_attempts >= TRANSACTION_ATTEMPTS_MAX(t->scope->protocol)) {
684 dns_transaction_complete(t, DNS_TRANSACTION_ATTEMPTS_MAX_REACHED);
685 return 0;
686 }
687
688 if (t->scope->protocol == DNS_PROTOCOL_LLMNR && had_stream) {
689 /* If we already tried via a stream, then we don't
690 * retry on LLMNR. See RFC 4795, Section 2.7. */
691 dns_transaction_complete(t, DNS_TRANSACTION_ATTEMPTS_MAX_REACHED);
692 return 0;
693 }
694
695 assert_se(sd_event_now(t->scope->manager->event, clock_boottime_or_monotonic(), &ts) >= 0);
696
697 t->n_attempts++;
698 t->start_usec = ts;
699 t->received = dns_packet_unref(t->received);
700 t->answer = dns_answer_unref(t->answer);
701 t->answer_rcode = 0;
702 t->answer_source = _DNS_TRANSACTION_SOURCE_INVALID;
703
704 /* Check the trust anchor. Do so only on classic DNS, since DNSSEC does not apply otherwise. */
705 if (t->scope->protocol == DNS_PROTOCOL_DNS) {
706 r = dns_trust_anchor_lookup(&t->scope->manager->trust_anchor, t->key, &t->answer);
707 if (r < 0)
708 return r;
709 if (r > 0) {
710 t->answer_rcode = DNS_RCODE_SUCCESS;
711 t->answer_source = DNS_TRANSACTION_TRUST_ANCHOR;
712 t->answer_authenticated = true;
713 dns_transaction_complete(t, DNS_TRANSACTION_SUCCESS);
714 return 0;
715 }
716 }
717
718 /* Check the zone, but only if this transaction is not used
719 * for probing or verifying a zone item. */
720 if (set_isempty(t->zone_items)) {
721
722 r = dns_zone_lookup(&t->scope->zone, t->key, &t->answer, NULL, NULL);
723 if (r < 0)
724 return r;
725 if (r > 0) {
726 t->answer_rcode = DNS_RCODE_SUCCESS;
727 t->answer_source = DNS_TRANSACTION_ZONE;
728 t->answer_authenticated = true;
729 dns_transaction_complete(t, DNS_TRANSACTION_SUCCESS);
730 return 0;
731 }
732 }
733
734 /* Check the cache, but only if this transaction is not used
735 * for probing or verifying a zone item. */
736 if (set_isempty(t->zone_items)) {
737
738 /* Before trying the cache, let's make sure we figured out a
739 * server to use. Should this cause a change of server this
740 * might flush the cache. */
741 dns_scope_get_dns_server(t->scope);
742
743 /* Let's then prune all outdated entries */
744 dns_cache_prune(&t->scope->cache);
745
746 r = dns_cache_lookup(&t->scope->cache, t->key, &t->answer_rcode, &t->answer, &t->answer_authenticated);
747 if (r < 0)
748 return r;
749 if (r > 0) {
750 t->answer_source = DNS_TRANSACTION_CACHE;
751 if (t->answer_rcode == DNS_RCODE_SUCCESS)
752 dns_transaction_complete(t, DNS_TRANSACTION_SUCCESS);
753 else
754 dns_transaction_complete(t, DNS_TRANSACTION_FAILURE);
755 return 0;
756 }
757 }
758
759 if (!t->initial_jitter_scheduled &&
760 (t->scope->protocol == DNS_PROTOCOL_LLMNR ||
761 t->scope->protocol == DNS_PROTOCOL_MDNS)) {
762 usec_t jitter, accuracy;
763
764 /* RFC 4795 Section 2.7 suggests all queries should be
765 * delayed by a random time from 0 to JITTER_INTERVAL. */
766
767 t->initial_jitter_scheduled = true;
768
769 random_bytes(&jitter, sizeof(jitter));
770
771 switch (t->scope->protocol) {
772 case DNS_PROTOCOL_LLMNR:
773 jitter %= LLMNR_JITTER_INTERVAL_USEC;
774 accuracy = LLMNR_JITTER_INTERVAL_USEC;
775 break;
776 case DNS_PROTOCOL_MDNS:
777 jitter %= MDNS_JITTER_RANGE_USEC;
778 jitter += MDNS_JITTER_MIN_USEC;
779 accuracy = MDNS_JITTER_RANGE_USEC;
780 break;
781 default:
782 assert_not_reached("bad protocol");
783 }
784
785 r = sd_event_add_time(
786 t->scope->manager->event,
787 &t->timeout_event_source,
788 clock_boottime_or_monotonic(),
789 ts + jitter, accuracy,
790 on_transaction_timeout, t);
791 if (r < 0)
792 return r;
793
794 t->n_attempts = 0;
795 t->state = DNS_TRANSACTION_PENDING;
796
797 log_debug("Delaying %s transaction for " USEC_FMT "us.", dns_protocol_to_string(t->scope->protocol), jitter);
798 return 0;
799 }
800
801 /* Otherwise, we need to ask the network */
802 r = dns_transaction_make_packet(t);
803 if (r == -EDOM) {
804 /* Not the right request to make on this network?
805 * (i.e. an A request made on IPv6 or an AAAA request
806 * made on IPv4, on LLMNR or mDNS.) */
807 dns_transaction_complete(t, DNS_TRANSACTION_NO_SERVERS);
808 return 0;
809 }
810 if (r < 0)
811 return r;
812
813 if (t->scope->protocol == DNS_PROTOCOL_LLMNR &&
814 (dns_name_endswith(DNS_RESOURCE_KEY_NAME(t->key), "in-addr.arpa") > 0 ||
815 dns_name_endswith(DNS_RESOURCE_KEY_NAME(t->key), "ip6.arpa") > 0)) {
816
817 /* RFC 4795, Section 2.4. says reverse lookups shall
818 * always be made via TCP on LLMNR */
819 r = dns_transaction_open_tcp(t);
820 } else {
821 /* Try via UDP, and if that fails due to large size or lack of
822 * support try via TCP */
823 r = dns_transaction_emit(t);
824 if (r == -EMSGSIZE || r == -EAGAIN)
825 r = dns_transaction_open_tcp(t);
826 }
827
828 if (r == -ESRCH) {
829 /* No servers to send this to? */
830 dns_transaction_complete(t, DNS_TRANSACTION_NO_SERVERS);
831 return 0;
832 } else if (r < 0) {
833 if (t->scope->protocol != DNS_PROTOCOL_DNS) {
834 dns_transaction_complete(t, DNS_TRANSACTION_RESOURCES);
835 return 0;
836 }
837
838 /* Couldn't send? Try immediately again, with a new server */
839 dns_transaction_next_dns_server(t);
840
841 return dns_transaction_go(t);
842 }
843
844 r = sd_event_add_time(
845 t->scope->manager->event,
846 &t->timeout_event_source,
847 clock_boottime_or_monotonic(),
848 ts + transaction_get_resend_timeout(t), 0,
849 on_transaction_timeout, t);
850 if (r < 0)
851 return r;
852
853 t->state = DNS_TRANSACTION_PENDING;
854 return 1;
855 }
856
857 static const char* const dns_transaction_state_table[_DNS_TRANSACTION_STATE_MAX] = {
858 [DNS_TRANSACTION_NULL] = "null",
859 [DNS_TRANSACTION_PENDING] = "pending",
860 [DNS_TRANSACTION_FAILURE] = "failure",
861 [DNS_TRANSACTION_SUCCESS] = "success",
862 [DNS_TRANSACTION_NO_SERVERS] = "no-servers",
863 [DNS_TRANSACTION_TIMEOUT] = "timeout",
864 [DNS_TRANSACTION_ATTEMPTS_MAX_REACHED] = "attempts-max-reached",
865 [DNS_TRANSACTION_INVALID_REPLY] = "invalid-reply",
866 [DNS_TRANSACTION_RESOURCES] = "resources",
867 [DNS_TRANSACTION_ABORTED] = "aborted",
868 };
869 DEFINE_STRING_TABLE_LOOKUP(dns_transaction_state, DnsTransactionState);
870
871 static const char* const dns_transaction_source_table[_DNS_TRANSACTION_SOURCE_MAX] = {
872 [DNS_TRANSACTION_NETWORK] = "network",
873 [DNS_TRANSACTION_CACHE] = "cache",
874 [DNS_TRANSACTION_ZONE] = "zone",
875 [DNS_TRANSACTION_TRUST_ANCHOR] = "trust-anchor",
876 };
877 DEFINE_STRING_TABLE_LOOKUP(dns_transaction_source, DnsTransactionSource);