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