]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/resolve/resolved-dns-transaction.c
resolved: flush keys when DNS_RESOURCE_KEY_CACHE_FLUSH is set
[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"
27#include "resolved-dns-transaction.h"
28#include "resolved-llmnr.h"
8b43440b 29#include "string-table.h"
ec2c5e43
LP
30
31DnsTransaction* dns_transaction_free(DnsTransaction *t) {
801ad6a6 32 DnsQueryCandidate *c;
ec2c5e43
LP
33 DnsZoneItem *i;
34
35 if (!t)
36 return NULL;
37
38 sd_event_source_unref(t->timeout_event_source);
39
ec2c5e43
LP
40 dns_packet_unref(t->sent);
41 dns_packet_unref(t->received);
ae6a4bbf
LP
42
43 dns_answer_unref(t->answer);
ec2c5e43 44
4667e00a
LP
45 sd_event_source_unref(t->dns_udp_event_source);
46 safe_close(t->dns_udp_fd);
d20b1667 47
8300ba21 48 dns_server_unref(t->server);
ec2c5e43
LP
49 dns_stream_free(t->stream);
50
51 if (t->scope) {
f9ebb22a
LP
52 hashmap_remove_value(t->scope->transactions_by_key, t->key, t);
53 LIST_REMOVE(transactions_by_scope, t->scope->transactions, t);
ec2c5e43
LP
54
55 if (t->id != 0)
56 hashmap_remove(t->scope->manager->dns_transactions, UINT_TO_PTR(t->id));
57 }
58
da0c630e
LP
59 dns_resource_key_unref(t->key);
60
801ad6a6
LP
61 while ((c = set_steal_first(t->query_candidates)))
62 set_remove(c->transactions, t);
63
64 set_free(t->query_candidates);
ec2c5e43
LP
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
74DEFINE_TRIVIAL_CLEANUP_FUNC(DnsTransaction*, dns_transaction_free);
75
76void dns_transaction_gc(DnsTransaction *t) {
77 assert(t);
78
79 if (t->block_gc > 0)
80 return;
81
801ad6a6 82 if (set_isempty(t->query_candidates) && set_isempty(t->zone_items))
ec2c5e43
LP
83 dns_transaction_free(t);
84}
85
f52e61da 86int dns_transaction_new(DnsTransaction **ret, DnsScope *s, DnsResourceKey *key) {
ec2c5e43
LP
87 _cleanup_(dns_transaction_freep) DnsTransaction *t = NULL;
88 int r;
89
90 assert(ret);
91 assert(s);
f52e61da 92 assert(key);
ec2c5e43 93
d5099efc 94 r = hashmap_ensure_allocated(&s->manager->dns_transactions, NULL);
ec2c5e43
LP
95 if (r < 0)
96 return r;
97
f9ebb22a 98 r = hashmap_ensure_allocated(&s->transactions_by_key, &dns_resource_key_hash_ops);
da0c630e
LP
99 if (r < 0)
100 return r;
101
ec2c5e43
LP
102 t = new0(DnsTransaction, 1);
103 if (!t)
104 return -ENOMEM;
105
4667e00a 106 t->dns_udp_fd = -1;
c3bc53e6 107 t->answer_source = _DNS_TRANSACTION_SOURCE_INVALID;
f52e61da 108 t->key = dns_resource_key_ref(key);
ec2c5e43 109
da0c630e 110 /* Find a fresh, unused transaction id */
ec2c5e43
LP
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
f9ebb22a 122 r = hashmap_replace(s->transactions_by_key, t->key, t);
da0c630e
LP
123 if (r < 0) {
124 hashmap_remove(s->manager->dns_transactions, UINT_TO_PTR(t->id));
125 return r;
126 }
127
f9ebb22a 128 LIST_PREPEND(transactions_by_scope, s->transactions, t);
ec2c5e43
LP
129 t->scope = s;
130
131 if (ret)
132 *ret = t;
133
134 t = NULL;
135
136 return 0;
137}
138
139static 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);
ae6a4bbf
LP
144
145 /* Note that we do not drop the UDP socket here, as we want to
146 * reuse it to repeat the interaction. */
ec2c5e43
LP
147}
148
149static void dns_transaction_tentative(DnsTransaction *t, DnsPacket *p) {
2fb3034c 150 _cleanup_free_ char *pretty = NULL;
ec2c5e43 151 DnsZoneItem *z;
ec2c5e43
LP
152
153 assert(t);
154 assert(p);
155
156 if (manager_our_packet(t->scope->manager, p) != 0)
157 return;
158
2fb3034c
LP
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",
ec2c5e43
LP
162 dns_protocol_to_string(t->scope->protocol),
163 t->scope->link ? t->scope->link->name : "*",
2fb3034c
LP
164 t->scope->family == AF_UNSPEC ? "*" : af_to_name(t->scope->family),
165 pretty);
ec2c5e43 166
a4076574
LP
167 /* RFC 4795, Section 4.1 says that the peer with the
168 * lexicographically smaller IP address loses */
4d91eec4
LP
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.");
a4076574
LP
171 return;
172 }
173
4d91eec4 174 log_debug("We have the lexicographically larger IP address and thus lost in the conflict.");
a4076574 175
ec2c5e43 176 t->block_gc++;
3ef64445
LP
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 */
ec2c5e43 184 dns_zone_item_conflict(z);
3ef64445 185 }
ec2c5e43
LP
186 t->block_gc--;
187
188 dns_transaction_gc(t);
189}
190
191void dns_transaction_complete(DnsTransaction *t, DnsTransactionState state) {
801ad6a6 192 DnsQueryCandidate *c;
ec2c5e43
LP
193 DnsZoneItem *z;
194 Iterator i;
195
196 assert(t);
197 assert(!IN_SET(state, DNS_TRANSACTION_NULL, DNS_TRANSACTION_PENDING));
e56187ca 198
ec2c5e43
LP
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
c3bc53e6 203 log_debug("Transaction on scope %s on %s/%s now complete with <%s> from %s",
ec2c5e43
LP
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),
c3bc53e6
LP
207 dns_transaction_state_to_string(state),
208 t->answer_source < 0 ? "none" : dns_transaction_source_to_string(t->answer_source));
ec2c5e43
LP
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++;
801ad6a6
LP
217 SET_FOREACH(c, t->query_candidates, i)
218 dns_query_candidate_ready(c);
ec2c5e43
LP
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
226static 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
a4076574
LP
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
ec2c5e43
LP
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
264static int dns_transaction_open_tcp(DnsTransaction *t) {
088480fa 265 DnsServer *server = NULL;
ec2c5e43
LP
266 _cleanup_close_ int fd = -1;
267 int r;
268
269 assert(t);
270
271 if (t->stream)
272 return 0;
273
106784eb
DM
274 switch (t->scope->protocol) {
275 case DNS_PROTOCOL_DNS:
8300ba21 276 fd = dns_scope_tcp_socket(t->scope, AF_UNSPEC, NULL, 53, &server);
106784eb 277 break;
ec2c5e43 278
106784eb 279 case DNS_PROTOCOL_LLMNR:
a8f6397f 280 /* When we already received a reply to this (but it was truncated), send to its sender address */
ec2c5e43 281 if (t->received)
8300ba21 282 fd = dns_scope_tcp_socket(t->scope, t->received->family, &t->received->sender, t->received->sender_port, NULL);
ec2c5e43
LP
283 else {
284 union in_addr_union address;
a7f7d1bd 285 int family = AF_UNSPEC;
ec2c5e43
LP
286
287 /* Otherwise, try to talk to the owner of a
288 * the IP address, in case this is a reverse
289 * PTR lookup */
f52e61da
LP
290
291 r = dns_name_address(DNS_RESOURCE_KEY_NAME(t->key), &family, &address);
ec2c5e43
LP
292 if (r < 0)
293 return r;
294 if (r == 0)
295 return -EINVAL;
9e08a6e0 296 if (family != t->scope->family)
9318cdd3 297 return -ESRCH;
ec2c5e43 298
8300ba21 299 fd = dns_scope_tcp_socket(t->scope, family, &address, LLMNR_PORT, NULL);
ec2c5e43 300 }
106784eb
DM
301
302 break;
303
304 default:
ec2c5e43 305 return -EAFNOSUPPORT;
106784eb 306 }
ec2c5e43
LP
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
8300ba21
TG
323 dns_server_unref(t->server);
324 t->server = dns_server_ref(server);
ec2c5e43 325 t->received = dns_packet_unref(t->received);
ae6a4bbf
LP
326 t->answer = dns_answer_unref(t->answer);
327 t->answer_rcode = 0;
ec2c5e43
LP
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
647f6aa8
TG
340static void dns_transaction_next_dns_server(DnsTransaction *t) {
341 assert(t);
342
343 t->server = dns_server_unref(t->server);
4667e00a
LP
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);
647f6aa8
TG
346
347 dns_scope_next_dns_server(t->scope);
348}
349
ec2c5e43 350void dns_transaction_process_reply(DnsTransaction *t, DnsPacket *p) {
9df3ba6c 351 usec_t ts;
ec2c5e43
LP
352 int r;
353
354 assert(t);
355 assert(p);
356 assert(t->state == DNS_TRANSACTION_PENDING);
9df3ba6c
TG
357 assert(t->scope);
358 assert(t->scope->manager);
ec2c5e43
LP
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
106784eb
DM
364 switch (t->scope->protocol) {
365 case DNS_PROTOCOL_LLMNR:
ec2c5e43
LP
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. */
8b757a38 380 if (DNS_PACKET_LLMNR_T(p)) {
ec2c5e43
LP
381 dns_transaction_tentative(t, p);
382 return;
383 }
106784eb
DM
384
385 break;
386
4e5bf5e1
DM
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
106784eb
DM
399 case DNS_PROTOCOL_DNS:
400 break;
401
402 default:
9c56a6f3 403 assert_not_reached("Invalid DNS protocol.");
ec2c5e43
LP
404 }
405
ec2c5e43
LP
406 if (t->received != p) {
407 dns_packet_unref(t->received);
408 t->received = dns_packet_ref(p);
409 }
410
c3bc53e6
LP
411 t->answer_source = DNS_TRANSACTION_NETWORK;
412
ec2c5e43
LP
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
38a03f06 427 assert_se(sd_event_now(t->scope->manager->event, clock_boottime_or_monotonic(), &ts) >= 0);
9df3ba6c
TG
428
429 switch (t->scope->protocol) {
430 case DNS_PROTOCOL_DNS:
431 assert(t->server);
432
4e0b8b17
TG
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
d74fb368 448 dns_server_packet_received(t->server, t->current_features, ts - t->start_usec, p->size);
9df3ba6c
TG
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:
9c56a6f3 457 break;
9df3ba6c
TG
458 }
459
ec2c5e43
LP
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 */
647f6aa8 477 dns_transaction_next_dns_server(t);
ec2c5e43
LP
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
29815b6c 496 /* Only consider responses with equivalent query section to the request */
f52e61da 497 if (p->question->n_keys != 1 || dns_resource_key_equal(p->question->keys[0], t->key) <= 0) {
29815b6c 498 dns_transaction_complete(t, DNS_TRANSACTION_INVALID_REPLY);
6709eb94
TG
499 return;
500 }
29815b6c 501
931851e8
LP
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
ec2c5e43 508 /* According to RFC 4795, section 2.9. only the RRs from the answer section shall be cached */
d830ebbd 509 if (DNS_PACKET_SHALL_CACHE(p))
931851e8
LP
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);
ec2c5e43
LP
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
c19ffd9f
TG
526static 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 &&
9df3ba6c 539 DNS_PACKET_ID(p) == t->id)
c19ffd9f 540 dns_transaction_process_reply(t, p);
9df3ba6c 541 else
c19ffd9f
TG
542 log_debug("Invalid DNS packet.");
543
544 return 0;
545}
546
471d40d9 547static int dns_transaction_emit(DnsTransaction *t) {
c19ffd9f
TG
548 int r;
549
550 assert(t);
c19ffd9f 551
471d40d9
TG
552 if (t->scope->protocol == DNS_PROTOCOL_DNS && !t->server) {
553 DnsServer *server = NULL;
554 _cleanup_close_ int fd = -1;
c19ffd9f 555
471d40d9
TG
556 fd = dns_scope_udp_dns_socket(t->scope, &server);
557 if (fd < 0)
558 return fd;
c19ffd9f 559
4667e00a 560 r = sd_event_add_io(t->scope->manager->event, &t->dns_udp_event_source, fd, EPOLLIN, on_dns_packet, t);
471d40d9
TG
561 if (r < 0)
562 return r;
c19ffd9f 563
4667e00a 564 t->dns_udp_fd = fd;
471d40d9
TG
565 fd = -1;
566 t->server = dns_server_ref(server);
567 }
c19ffd9f 568
9c5e12a4 569 r = dns_scope_emit(t->scope, t->dns_udp_fd, t->server, t->sent);
471d40d9
TG
570 if (r < 0)
571 return r;
c19ffd9f 572
be808ea0
TG
573 if (t->server)
574 t->current_features = t->server->possible_features;
575
471d40d9 576 return 0;
c19ffd9f
TG
577}
578
ec2c5e43
LP
579static 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
be808ea0
TG
586 /* Timeout reached? Increase the timeout for the server used */
587 switch (t->scope->protocol) {
588 case DNS_PROTOCOL_DNS:
589 assert(t->server);
ec2c5e43 590
be808ea0
TG
591 dns_server_packet_lost(t->server, t->current_features, usec - t->start_usec);
592
593 break;
594 case DNS_PROTOCOL_LLMNR:
595 case DNS_PROTOCOL_MDNS:
9df3ba6c
TG
596 dns_scope_packet_lost(t->scope, usec - t->start_usec);
597
be808ea0
TG
598 break;
599 default:
600 assert_not_reached("Invalid DNS protocol.");
601 }
602
603 /* ...and try again with a new server */
604 dns_transaction_next_dns_server(t);
605
ec2c5e43
LP
606 r = dns_transaction_go(t);
607 if (r < 0)
608 dns_transaction_complete(t, DNS_TRANSACTION_RESOURCES);
609
610 return 0;
611}
612
613static int dns_transaction_make_packet(DnsTransaction *t) {
614 _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
ec2c5e43
LP
615 int r;
616
617 assert(t);
618
619 if (t->sent)
620 return 0;
621
24710c48 622 r = dns_packet_new_query(&p, t->scope->protocol, 0, t->scope->dnssec_mode == DNSSEC_YES);
ec2c5e43
LP
623 if (r < 0)
624 return r;
625
f52e61da
LP
626 r = dns_scope_good_key(t->scope, t->key);
627 if (r < 0)
628 return r;
629 if (r == 0)
ec2c5e43
LP
630 return -EDOM;
631
f52e61da
LP
632 r = dns_packet_append_key(p, t->key, NULL);
633 if (r < 0)
634 return r;
635
636 DNS_PACKET_HEADER(p)->qdcount = htobe16(1);
ec2c5e43
LP
637 DNS_PACKET_HEADER(p)->id = t->id;
638
639 t->sent = p;
640 p = NULL;
641
642 return 0;
643}
644
9df3ba6c
TG
645static usec_t transaction_get_resend_timeout(DnsTransaction *t) {
646 assert(t);
647 assert(t->scope);
648
649 switch (t->scope->protocol) {
650 case DNS_PROTOCOL_DNS:
651 assert(t->server);
652
653 return t->server->resend_timeout;
654 case DNS_PROTOCOL_LLMNR:
655 case DNS_PROTOCOL_MDNS:
656 return t->scope->resend_timeout;
657 default:
658 assert_not_reached("Invalid DNS protocol.");
659 }
660}
661
ec2c5e43
LP
662int dns_transaction_go(DnsTransaction *t) {
663 bool had_stream;
9df3ba6c 664 usec_t ts;
ec2c5e43
LP
665 int r;
666
667 assert(t);
668
669 had_stream = !!t->stream;
670
671 dns_transaction_stop(t);
672
e56187ca 673 log_debug("Excercising transaction on scope %s on %s/%s",
ec2c5e43
LP
674 dns_protocol_to_string(t->scope->protocol),
675 t->scope->link ? t->scope->link->name : "*",
676 t->scope->family == AF_UNSPEC ? "*" : af_to_name(t->scope->family));
677
678 if (t->n_attempts >= TRANSACTION_ATTEMPTS_MAX(t->scope->protocol)) {
679 dns_transaction_complete(t, DNS_TRANSACTION_ATTEMPTS_MAX_REACHED);
680 return 0;
681 }
682
683 if (t->scope->protocol == DNS_PROTOCOL_LLMNR && had_stream) {
684 /* If we already tried via a stream, then we don't
685 * retry on LLMNR. See RFC 4795, Section 2.7. */
686 dns_transaction_complete(t, DNS_TRANSACTION_ATTEMPTS_MAX_REACHED);
687 return 0;
688 }
689
38a03f06 690 assert_se(sd_event_now(t->scope->manager->event, clock_boottime_or_monotonic(), &ts) >= 0);
9df3ba6c 691
ec2c5e43 692 t->n_attempts++;
9df3ba6c 693 t->start_usec = ts;
ec2c5e43 694 t->received = dns_packet_unref(t->received);
ae6a4bbf
LP
695 t->answer = dns_answer_unref(t->answer);
696 t->answer_rcode = 0;
c3bc53e6 697 t->answer_source = _DNS_TRANSACTION_SOURCE_INVALID;
ec2c5e43 698
0d2cd476
LP
699 /* Check the trust anchor. Do so only on classic DNS, since DNSSEC does not apply otherwise. */
700 if (t->scope->protocol == DNS_PROTOCOL_DNS) {
701 r = dns_trust_anchor_lookup(&t->scope->manager->trust_anchor, t->key, &t->answer);
702 if (r < 0)
703 return r;
704 if (r > 0) {
705 t->answer_rcode = DNS_RCODE_SUCCESS;
706 t->answer_source = DNS_TRANSACTION_TRUST_ANCHOR;
931851e8 707 t->answer_authenticated = true;
0d2cd476
LP
708 dns_transaction_complete(t, DNS_TRANSACTION_SUCCESS);
709 return 0;
710 }
711 }
712
713 /* Check the zone, but only if this transaction is not used
d746bb3e
LP
714 * for probing or verifying a zone item. */
715 if (set_isempty(t->zone_items)) {
716
ae6a4bbf 717 r = dns_zone_lookup(&t->scope->zone, t->key, &t->answer, NULL, NULL);
d746bb3e
LP
718 if (r < 0)
719 return r;
720 if (r > 0) {
ae6a4bbf 721 t->answer_rcode = DNS_RCODE_SUCCESS;
c3bc53e6 722 t->answer_source = DNS_TRANSACTION_ZONE;
931851e8 723 t->answer_authenticated = true;
d746bb3e
LP
724 dns_transaction_complete(t, DNS_TRANSACTION_SUCCESS);
725 return 0;
726 }
727 }
728
4d926a69
LP
729 /* Check the cache, but only if this transaction is not used
730 * for probing or verifying a zone item. */
731 if (set_isempty(t->zone_items)) {
2c27fbca 732
4d926a69
LP
733 /* Before trying the cache, let's make sure we figured out a
734 * server to use. Should this cause a change of server this
735 * might flush the cache. */
736 dns_scope_get_dns_server(t->scope);
2c27fbca 737
4d926a69
LP
738 /* Let's then prune all outdated entries */
739 dns_cache_prune(&t->scope->cache);
740
931851e8 741 r = dns_cache_lookup(&t->scope->cache, t->key, &t->answer_rcode, &t->answer, &t->answer_authenticated);
4d926a69
LP
742 if (r < 0)
743 return r;
744 if (r > 0) {
c3bc53e6 745 t->answer_source = DNS_TRANSACTION_CACHE;
ae6a4bbf 746 if (t->answer_rcode == DNS_RCODE_SUCCESS)
4d926a69
LP
747 dns_transaction_complete(t, DNS_TRANSACTION_SUCCESS);
748 else
749 dns_transaction_complete(t, DNS_TRANSACTION_FAILURE);
750 return 0;
751 }
ec2c5e43
LP
752 }
753
ea12bcc7
DM
754 if (!t->initial_jitter &&
755 (t->scope->protocol == DNS_PROTOCOL_LLMNR ||
756 t->scope->protocol == DNS_PROTOCOL_MDNS)) {
757 usec_t jitter, accuracy;
6e068472
LP
758
759 /* RFC 4795 Section 2.7 suggests all queries should be
760 * delayed by a random time from 0 to JITTER_INTERVAL. */
761
762 t->initial_jitter = true;
763
764 random_bytes(&jitter, sizeof(jitter));
ea12bcc7
DM
765
766 switch (t->scope->protocol) {
767 case DNS_PROTOCOL_LLMNR:
768 jitter %= LLMNR_JITTER_INTERVAL_USEC;
769 accuracy = LLMNR_JITTER_INTERVAL_USEC;
770 break;
771 case DNS_PROTOCOL_MDNS:
772 jitter %= MDNS_JITTER_RANGE_USEC;
773 jitter += MDNS_JITTER_MIN_USEC;
774 accuracy = MDNS_JITTER_RANGE_USEC;
775 break;
776 default:
777 assert_not_reached("bad protocol");
778 }
6e068472
LP
779
780 r = sd_event_add_time(
781 t->scope->manager->event,
782 &t->timeout_event_source,
783 clock_boottime_or_monotonic(),
ea12bcc7 784 ts + jitter, accuracy,
6e068472
LP
785 on_transaction_timeout, t);
786 if (r < 0)
787 return r;
788
789 t->n_attempts = 0;
790 t->state = DNS_TRANSACTION_PENDING;
791
ea12bcc7 792 log_debug("Delaying %s transaction for " USEC_FMT "us.", dns_protocol_to_string(t->scope->protocol), jitter);
6e068472
LP
793 return 0;
794 }
795
ec2c5e43
LP
796 /* Otherwise, we need to ask the network */
797 r = dns_transaction_make_packet(t);
798 if (r == -EDOM) {
799 /* Not the right request to make on this network?
800 * (i.e. an A request made on IPv6 or an AAAA request
801 * made on IPv4, on LLMNR or mDNS.) */
802 dns_transaction_complete(t, DNS_TRANSACTION_NO_SERVERS);
803 return 0;
804 }
805 if (r < 0)
806 return r;
807
808 if (t->scope->protocol == DNS_PROTOCOL_LLMNR &&
f52e61da
LP
809 (dns_name_endswith(DNS_RESOURCE_KEY_NAME(t->key), "in-addr.arpa") > 0 ||
810 dns_name_endswith(DNS_RESOURCE_KEY_NAME(t->key), "ip6.arpa") > 0)) {
ec2c5e43
LP
811
812 /* RFC 4795, Section 2.4. says reverse lookups shall
813 * always be made via TCP on LLMNR */
814 r = dns_transaction_open_tcp(t);
815 } else {
be808ea0
TG
816 /* Try via UDP, and if that fails due to large size or lack of
817 * support try via TCP */
471d40d9 818 r = dns_transaction_emit(t);
be808ea0 819 if (r == -EMSGSIZE || r == -EAGAIN)
ec2c5e43
LP
820 r = dns_transaction_open_tcp(t);
821 }
be808ea0 822
ec2c5e43
LP
823 if (r == -ESRCH) {
824 /* No servers to send this to? */
825 dns_transaction_complete(t, DNS_TRANSACTION_NO_SERVERS);
826 return 0;
8300ba21 827 } else if (r < 0) {
13b551ac
LP
828 if (t->scope->protocol != DNS_PROTOCOL_DNS) {
829 dns_transaction_complete(t, DNS_TRANSACTION_RESOURCES);
830 return 0;
831 }
832
ec2c5e43 833 /* Couldn't send? Try immediately again, with a new server */
647f6aa8 834 dns_transaction_next_dns_server(t);
ec2c5e43
LP
835
836 return dns_transaction_go(t);
837 }
838
9a015429
LP
839 r = sd_event_add_time(
840 t->scope->manager->event,
841 &t->timeout_event_source,
842 clock_boottime_or_monotonic(),
9df3ba6c 843 ts + transaction_get_resend_timeout(t), 0,
9a015429 844 on_transaction_timeout, t);
ec2c5e43
LP
845 if (r < 0)
846 return r;
847
848 t->state = DNS_TRANSACTION_PENDING;
849 return 1;
850}
851
852static const char* const dns_transaction_state_table[_DNS_TRANSACTION_STATE_MAX] = {
853 [DNS_TRANSACTION_NULL] = "null",
854 [DNS_TRANSACTION_PENDING] = "pending",
855 [DNS_TRANSACTION_FAILURE] = "failure",
856 [DNS_TRANSACTION_SUCCESS] = "success",
857 [DNS_TRANSACTION_NO_SERVERS] = "no-servers",
858 [DNS_TRANSACTION_TIMEOUT] = "timeout",
859 [DNS_TRANSACTION_ATTEMPTS_MAX_REACHED] = "attempts-max-reached",
860 [DNS_TRANSACTION_INVALID_REPLY] = "invalid-reply",
861 [DNS_TRANSACTION_RESOURCES] = "resources",
862 [DNS_TRANSACTION_ABORTED] = "aborted",
863};
864DEFINE_STRING_TABLE_LOOKUP(dns_transaction_state, DnsTransactionState);
c3bc53e6
LP
865
866static const char* const dns_transaction_source_table[_DNS_TRANSACTION_SOURCE_MAX] = {
867 [DNS_TRANSACTION_NETWORK] = "network",
868 [DNS_TRANSACTION_CACHE] = "cache",
869 [DNS_TRANSACTION_ZONE] = "zone",
0d2cd476 870 [DNS_TRANSACTION_TRUST_ANCHOR] = "trust-anchor",
c3bc53e6
LP
871};
872DEFINE_STRING_TABLE_LOOKUP(dns_transaction_source, DnsTransactionSource);