]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/resolve/resolved-dns-transaction.c
Merge pull request #2152 from evverx/respect-disable-tests
[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 34 DnsZoneItem *i;
547973de 35 DnsTransaction *z;
ec2c5e43
LP
36
37 if (!t)
38 return NULL;
39
40 sd_event_source_unref(t->timeout_event_source);
41
ec2c5e43
LP
42 dns_packet_unref(t->sent);
43 dns_packet_unref(t->received);
ae6a4bbf
LP
44
45 dns_answer_unref(t->answer);
ec2c5e43 46
4667e00a
LP
47 sd_event_source_unref(t->dns_udp_event_source);
48 safe_close(t->dns_udp_fd);
d20b1667 49
8300ba21 50 dns_server_unref(t->server);
ec2c5e43
LP
51 dns_stream_free(t->stream);
52
53 if (t->scope) {
f9ebb22a
LP
54 hashmap_remove_value(t->scope->transactions_by_key, t->key, t);
55 LIST_REMOVE(transactions_by_scope, t->scope->transactions, t);
ec2c5e43
LP
56
57 if (t->id != 0)
58 hashmap_remove(t->scope->manager->dns_transactions, UINT_TO_PTR(t->id));
59 }
60
da0c630e
LP
61 dns_resource_key_unref(t->key);
62
547973de 63 while ((c = set_steal_first(t->notify_query_candidates)))
801ad6a6 64 set_remove(c->transactions, t);
547973de 65 set_free(t->notify_query_candidates);
801ad6a6 66
547973de 67 while ((i = set_steal_first(t->notify_zone_items)))
ec2c5e43 68 i->probe_transaction = NULL;
547973de
LP
69 set_free(t->notify_zone_items);
70
71 while ((z = set_steal_first(t->notify_transactions)))
72 set_remove(z->dnssec_transactions, t);
73 set_free(t->notify_transactions);
74
75 while ((z = set_steal_first(t->dnssec_transactions))) {
76 set_remove(z->notify_transactions, t);
77 dns_transaction_gc(z);
78 }
79 set_free(t->dnssec_transactions);
80
81 dns_answer_unref(t->validated_keys);
ec2c5e43
LP
82
83 free(t);
84 return NULL;
85}
86
87DEFINE_TRIVIAL_CLEANUP_FUNC(DnsTransaction*, dns_transaction_free);
88
89void dns_transaction_gc(DnsTransaction *t) {
90 assert(t);
91
92 if (t->block_gc > 0)
93 return;
94
547973de
LP
95 if (set_isempty(t->notify_query_candidates) &&
96 set_isempty(t->notify_zone_items) &&
97 set_isempty(t->notify_transactions))
ec2c5e43
LP
98 dns_transaction_free(t);
99}
100
f52e61da 101int dns_transaction_new(DnsTransaction **ret, DnsScope *s, DnsResourceKey *key) {
ec2c5e43
LP
102 _cleanup_(dns_transaction_freep) DnsTransaction *t = NULL;
103 int r;
104
105 assert(ret);
106 assert(s);
f52e61da 107 assert(key);
ec2c5e43 108
9eae2bf3 109 /* Don't allow looking up invalid or pseudo RRs */
c463eb78 110 if (!dns_type_is_valid_query(key->type))
9eae2bf3
LP
111 return -EINVAL;
112
113 /* We only support the IN class */
c463eb78 114 if (key->class != DNS_CLASS_IN && key->class != DNS_CLASS_ANY)
9eae2bf3
LP
115 return -EOPNOTSUPP;
116
d5099efc 117 r = hashmap_ensure_allocated(&s->manager->dns_transactions, NULL);
ec2c5e43
LP
118 if (r < 0)
119 return r;
120
f9ebb22a 121 r = hashmap_ensure_allocated(&s->transactions_by_key, &dns_resource_key_hash_ops);
da0c630e
LP
122 if (r < 0)
123 return r;
124
ec2c5e43
LP
125 t = new0(DnsTransaction, 1);
126 if (!t)
127 return -ENOMEM;
128
4667e00a 129 t->dns_udp_fd = -1;
c3bc53e6 130 t->answer_source = _DNS_TRANSACTION_SOURCE_INVALID;
547973de 131 t->dnssec_result = _DNSSEC_RESULT_INVALID;
f52e61da 132 t->key = dns_resource_key_ref(key);
ec2c5e43 133
da0c630e 134 /* Find a fresh, unused transaction id */
ec2c5e43
LP
135 do
136 random_bytes(&t->id, sizeof(t->id));
137 while (t->id == 0 ||
138 hashmap_get(s->manager->dns_transactions, UINT_TO_PTR(t->id)));
139
140 r = hashmap_put(s->manager->dns_transactions, UINT_TO_PTR(t->id), t);
141 if (r < 0) {
142 t->id = 0;
143 return r;
144 }
145
f9ebb22a 146 r = hashmap_replace(s->transactions_by_key, t->key, t);
da0c630e
LP
147 if (r < 0) {
148 hashmap_remove(s->manager->dns_transactions, UINT_TO_PTR(t->id));
149 return r;
150 }
151
f9ebb22a 152 LIST_PREPEND(transactions_by_scope, s->transactions, t);
ec2c5e43
LP
153 t->scope = s;
154
155 if (ret)
156 *ret = t;
157
158 t = NULL;
159
160 return 0;
161}
162
163static void dns_transaction_stop(DnsTransaction *t) {
164 assert(t);
165
166 t->timeout_event_source = sd_event_source_unref(t->timeout_event_source);
167 t->stream = dns_stream_free(t->stream);
ae6a4bbf
LP
168
169 /* Note that we do not drop the UDP socket here, as we want to
170 * reuse it to repeat the interaction. */
ec2c5e43
LP
171}
172
173static void dns_transaction_tentative(DnsTransaction *t, DnsPacket *p) {
2fb3034c 174 _cleanup_free_ char *pretty = NULL;
ec2c5e43 175 DnsZoneItem *z;
ec2c5e43
LP
176
177 assert(t);
178 assert(p);
179
180 if (manager_our_packet(t->scope->manager, p) != 0)
181 return;
182
2fb3034c
LP
183 in_addr_to_string(p->family, &p->sender, &pretty);
184
185 log_debug("Transaction on scope %s on %s/%s got tentative packet from %s",
ec2c5e43
LP
186 dns_protocol_to_string(t->scope->protocol),
187 t->scope->link ? t->scope->link->name : "*",
2fb3034c
LP
188 t->scope->family == AF_UNSPEC ? "*" : af_to_name(t->scope->family),
189 pretty);
ec2c5e43 190
a4076574
LP
191 /* RFC 4795, Section 4.1 says that the peer with the
192 * lexicographically smaller IP address loses */
4d91eec4
LP
193 if (memcmp(&p->sender, &p->destination, FAMILY_ADDRESS_SIZE(p->family)) >= 0) {
194 log_debug("Peer has lexicographically larger IP address and thus lost in the conflict.");
a4076574
LP
195 return;
196 }
197
4d91eec4 198 log_debug("We have the lexicographically larger IP address and thus lost in the conflict.");
a4076574 199
ec2c5e43 200 t->block_gc++;
547973de 201 while ((z = set_first(t->notify_zone_items))) {
3ef64445
LP
202 /* First, make sure the zone item drops the reference
203 * to us */
204 dns_zone_item_probe_stop(z);
205
206 /* Secondly, report this as conflict, so that we might
207 * look for a different hostname */
ec2c5e43 208 dns_zone_item_conflict(z);
3ef64445 209 }
ec2c5e43
LP
210 t->block_gc--;
211
212 dns_transaction_gc(t);
213}
214
215void dns_transaction_complete(DnsTransaction *t, DnsTransactionState state) {
801ad6a6 216 DnsQueryCandidate *c;
ec2c5e43 217 DnsZoneItem *z;
547973de 218 DnsTransaction *d;
ec2c5e43
LP
219 Iterator i;
220
221 assert(t);
547973de 222 assert(!DNS_TRANSACTION_IS_LIVE(state));
e56187ca 223
ec2c5e43
LP
224 /* Note that this call might invalidate the query. Callers
225 * should hence not attempt to access the query or transaction
226 * after calling this function. */
227
c3bc53e6 228 log_debug("Transaction on scope %s on %s/%s now complete with <%s> from %s",
ec2c5e43
LP
229 dns_protocol_to_string(t->scope->protocol),
230 t->scope->link ? t->scope->link->name : "*",
231 t->scope->family == AF_UNSPEC ? "*" : af_to_name(t->scope->family),
c3bc53e6
LP
232 dns_transaction_state_to_string(state),
233 t->answer_source < 0 ? "none" : dns_transaction_source_to_string(t->answer_source));
ec2c5e43
LP
234
235 t->state = state;
236
237 dns_transaction_stop(t);
238
239 /* Notify all queries that are interested, but make sure the
240 * transaction isn't freed while we are still looking at it */
241 t->block_gc++;
547973de
LP
242 SET_FOREACH(c, t->notify_query_candidates, i)
243 dns_query_candidate_notify(c);
244 SET_FOREACH(z, t->notify_zone_items, i)
245 dns_zone_item_notify(z);
246 SET_FOREACH(d, t->notify_transactions, i)
247 dns_transaction_notify(d, t);
ec2c5e43
LP
248 t->block_gc--;
249
250 dns_transaction_gc(t);
251}
252
253static int on_stream_complete(DnsStream *s, int error) {
254 _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
255 DnsTransaction *t;
256
257 assert(s);
258 assert(s->transaction);
259
260 /* Copy the data we care about out of the stream before we
261 * destroy it. */
262 t = s->transaction;
263 p = dns_packet_ref(s->read_packet);
264
265 t->stream = dns_stream_free(t->stream);
266
267 if (error != 0) {
268 dns_transaction_complete(t, DNS_TRANSACTION_RESOURCES);
269 return 0;
270 }
271
a4076574 272 if (dns_packet_validate_reply(p) <= 0) {
a20b9592 273 log_debug("Invalid TCP reply packet.");
a4076574
LP
274 dns_transaction_complete(t, DNS_TRANSACTION_INVALID_REPLY);
275 return 0;
276 }
277
278 dns_scope_check_conflicts(t->scope, p);
279
ec2c5e43
LP
280 t->block_gc++;
281 dns_transaction_process_reply(t, p);
282 t->block_gc--;
283
284 /* If the response wasn't useful, then complete the transition now */
285 if (t->state == DNS_TRANSACTION_PENDING)
286 dns_transaction_complete(t, DNS_TRANSACTION_INVALID_REPLY);
287
288 return 0;
289}
290
291static int dns_transaction_open_tcp(DnsTransaction *t) {
088480fa 292 DnsServer *server = NULL;
ec2c5e43
LP
293 _cleanup_close_ int fd = -1;
294 int r;
295
296 assert(t);
297
298 if (t->stream)
299 return 0;
300
106784eb
DM
301 switch (t->scope->protocol) {
302 case DNS_PROTOCOL_DNS:
8300ba21 303 fd = dns_scope_tcp_socket(t->scope, AF_UNSPEC, NULL, 53, &server);
106784eb 304 break;
ec2c5e43 305
106784eb 306 case DNS_PROTOCOL_LLMNR:
a8f6397f 307 /* When we already received a reply to this (but it was truncated), send to its sender address */
ec2c5e43 308 if (t->received)
8300ba21 309 fd = dns_scope_tcp_socket(t->scope, t->received->family, &t->received->sender, t->received->sender_port, NULL);
ec2c5e43
LP
310 else {
311 union in_addr_union address;
a7f7d1bd 312 int family = AF_UNSPEC;
ec2c5e43
LP
313
314 /* Otherwise, try to talk to the owner of a
315 * the IP address, in case this is a reverse
316 * PTR lookup */
f52e61da
LP
317
318 r = dns_name_address(DNS_RESOURCE_KEY_NAME(t->key), &family, &address);
ec2c5e43
LP
319 if (r < 0)
320 return r;
321 if (r == 0)
322 return -EINVAL;
9e08a6e0 323 if (family != t->scope->family)
9318cdd3 324 return -ESRCH;
ec2c5e43 325
8300ba21 326 fd = dns_scope_tcp_socket(t->scope, family, &address, LLMNR_PORT, NULL);
ec2c5e43 327 }
106784eb
DM
328
329 break;
330
331 default:
ec2c5e43 332 return -EAFNOSUPPORT;
106784eb 333 }
ec2c5e43
LP
334
335 if (fd < 0)
336 return fd;
337
338 r = dns_stream_new(t->scope->manager, &t->stream, t->scope->protocol, fd);
339 if (r < 0)
340 return r;
341
342 fd = -1;
343
344 r = dns_stream_write_packet(t->stream, t->sent);
345 if (r < 0) {
346 t->stream = dns_stream_free(t->stream);
347 return r;
348 }
349
8300ba21
TG
350 dns_server_unref(t->server);
351 t->server = dns_server_ref(server);
ec2c5e43 352 t->received = dns_packet_unref(t->received);
ae6a4bbf 353 t->answer = dns_answer_unref(t->answer);
79e24931 354 t->n_answer_cacheable = 0;
ae6a4bbf 355 t->answer_rcode = 0;
ec2c5e43
LP
356 t->stream->complete = on_stream_complete;
357 t->stream->transaction = t;
358
359 /* The interface index is difficult to determine if we are
360 * connecting to the local host, hence fill this in right away
361 * instead of determining it from the socket */
362 if (t->scope->link)
363 t->stream->ifindex = t->scope->link->ifindex;
364
365 return 0;
366}
367
647f6aa8
TG
368static void dns_transaction_next_dns_server(DnsTransaction *t) {
369 assert(t);
370
371 t->server = dns_server_unref(t->server);
4667e00a
LP
372 t->dns_udp_event_source = sd_event_source_unref(t->dns_udp_event_source);
373 t->dns_udp_fd = safe_close(t->dns_udp_fd);
647f6aa8
TG
374
375 dns_scope_next_dns_server(t->scope);
376}
377
547973de 378static void dns_transaction_cache_answer(DnsTransaction *t) {
547973de
LP
379 assert(t);
380
381 /* For mDNS we cache whenever we get the packet, rather than
382 * in each transaction. */
383 if (!IN_SET(t->scope->protocol, DNS_PROTOCOL_DNS, DNS_PROTOCOL_LLMNR))
384 return;
385
386 /* We never cache if this packet is from the local host, under
387 * the assumption that a locally running DNS server would
388 * cache this anyway, and probably knows better when to flush
389 * the cache then we could. */
390 if (!DNS_PACKET_SHALL_CACHE(t->received))
391 return;
392
547973de
LP
393 dns_cache_put(&t->scope->cache,
394 t->key,
395 t->answer_rcode,
396 t->answer,
79e24931 397 t->n_answer_cacheable,
547973de
LP
398 t->answer_authenticated,
399 0,
400 t->received->family,
401 &t->received->sender);
402}
403
404static void dns_transaction_process_dnssec(DnsTransaction *t) {
405 int r;
406
407 assert(t);
408
409 /* Are there ongoing DNSSEC transactions? If so, let's wait for them. */
410 if (!set_isempty(t->dnssec_transactions))
411 return;
412
413 /* All our auxiliary DNSSEC transactions are complete now. Try
414 * to validate our RRset now. */
415 r = dns_transaction_validate_dnssec(t);
416 if (r < 0) {
417 dns_transaction_complete(t, DNS_TRANSACTION_RESOURCES);
418 return;
419 }
420
421 if (!IN_SET(t->dnssec_result, _DNSSEC_RESULT_INVALID, DNSSEC_VALIDATED, DNSSEC_NO_SIGNATURE /* FOR NOW! */)) {
422 dns_transaction_complete(t, DNS_TRANSACTION_DNSSEC_FAILED);
423 return;
424 }
425
426 dns_transaction_cache_answer(t);
427
428 if (t->answer_rcode == DNS_RCODE_SUCCESS)
429 dns_transaction_complete(t, DNS_TRANSACTION_SUCCESS);
430 else
431 dns_transaction_complete(t, DNS_TRANSACTION_FAILURE);
432}
433
ec2c5e43 434void dns_transaction_process_reply(DnsTransaction *t, DnsPacket *p) {
9df3ba6c 435 usec_t ts;
ec2c5e43
LP
436 int r;
437
438 assert(t);
439 assert(p);
440 assert(t->state == DNS_TRANSACTION_PENDING);
9df3ba6c
TG
441 assert(t->scope);
442 assert(t->scope->manager);
ec2c5e43
LP
443
444 /* Note that this call might invalidate the query. Callers
445 * should hence not attempt to access the query or transaction
446 * after calling this function. */
447
b5efcf29
LP
448 log_debug("Processing incoming packet on transaction %" PRIu16".", t->id);
449
106784eb 450 switch (t->scope->protocol) {
b5efcf29 451
106784eb 452 case DNS_PROTOCOL_LLMNR:
ec2c5e43
LP
453 assert(t->scope->link);
454
455 /* For LLMNR we will not accept any packets from other
456 * interfaces */
457
458 if (p->ifindex != t->scope->link->ifindex)
459 return;
460
461 if (p->family != t->scope->family)
462 return;
463
464 /* Tentative packets are not full responses but still
465 * useful for identifying uniqueness conflicts during
466 * probing. */
8b757a38 467 if (DNS_PACKET_LLMNR_T(p)) {
ec2c5e43
LP
468 dns_transaction_tentative(t, p);
469 return;
470 }
106784eb
DM
471
472 break;
473
4e5bf5e1
DM
474 case DNS_PROTOCOL_MDNS:
475 assert(t->scope->link);
476
477 /* For mDNS we will not accept any packets from other interfaces */
478 if (p->ifindex != t->scope->link->ifindex)
479 return;
480
481 if (p->family != t->scope->family)
482 return;
483
484 break;
485
106784eb
DM
486 case DNS_PROTOCOL_DNS:
487 break;
488
489 default:
9c56a6f3 490 assert_not_reached("Invalid DNS protocol.");
ec2c5e43
LP
491 }
492
ec2c5e43
LP
493 if (t->received != p) {
494 dns_packet_unref(t->received);
495 t->received = dns_packet_ref(p);
496 }
497
c3bc53e6
LP
498 t->answer_source = DNS_TRANSACTION_NETWORK;
499
ec2c5e43
LP
500 if (p->ipproto == IPPROTO_TCP) {
501 if (DNS_PACKET_TC(p)) {
502 /* Truncated via TCP? Somebody must be fucking with us */
503 dns_transaction_complete(t, DNS_TRANSACTION_INVALID_REPLY);
504 return;
505 }
506
507 if (DNS_PACKET_ID(p) != t->id) {
508 /* Not the reply to our query? Somebody must be fucking with us */
509 dns_transaction_complete(t, DNS_TRANSACTION_INVALID_REPLY);
510 return;
511 }
512 }
513
38a03f06 514 assert_se(sd_event_now(t->scope->manager->event, clock_boottime_or_monotonic(), &ts) >= 0);
9df3ba6c
TG
515
516 switch (t->scope->protocol) {
8af5b883 517
9df3ba6c
TG
518 case DNS_PROTOCOL_DNS:
519 assert(t->server);
520
4e0b8b17
TG
521 if (IN_SET(DNS_PACKET_RCODE(p), DNS_RCODE_FORMERR, DNS_RCODE_SERVFAIL, DNS_RCODE_NOTIMP)) {
522
8af5b883 523 /* Request failed, immediately try again with reduced features */
4e0b8b17
TG
524 log_debug("Server returned error: %s", dns_rcode_to_string(DNS_PACKET_RCODE(p)));
525
526 dns_server_packet_failed(t->server, t->current_features);
527
528 r = dns_transaction_go(t);
529 if (r < 0) {
530 dns_transaction_complete(t, DNS_TRANSACTION_RESOURCES);
531 return;
532 }
533
534 return;
535 } else
d74fb368 536 dns_server_packet_received(t->server, t->current_features, ts - t->start_usec, p->size);
9df3ba6c
TG
537
538 break;
8af5b883 539
9df3ba6c
TG
540 case DNS_PROTOCOL_LLMNR:
541 case DNS_PROTOCOL_MDNS:
542 dns_scope_packet_received(t->scope, ts - t->start_usec);
9df3ba6c 543 break;
8af5b883 544
9df3ba6c 545 default:
8af5b883 546 assert_not_reached("Invalid DNS protocol.");
9df3ba6c
TG
547 }
548
ec2c5e43 549 if (DNS_PACKET_TC(p)) {
547493c5
DM
550
551 /* Truncated packets for mDNS are not allowed. Give up immediately. */
552 if (t->scope->protocol == DNS_PROTOCOL_MDNS) {
553 dns_transaction_complete(t, DNS_TRANSACTION_INVALID_REPLY);
554 return;
555 }
556
ec2c5e43
LP
557 /* Response was truncated, let's try again with good old TCP */
558 r = dns_transaction_open_tcp(t);
559 if (r == -ESRCH) {
560 /* No servers found? Damn! */
561 dns_transaction_complete(t, DNS_TRANSACTION_NO_SERVERS);
562 return;
563 }
564 if (r < 0) {
8af5b883 565 /* On LLMNR, if we cannot connect to the host,
ec2c5e43
LP
566 * we immediately give up */
567 if (t->scope->protocol == DNS_PROTOCOL_LLMNR) {
568 dns_transaction_complete(t, DNS_TRANSACTION_RESOURCES);
569 return;
570 }
571
572 /* On DNS, couldn't send? Try immediately again, with a new server */
647f6aa8 573 dns_transaction_next_dns_server(t);
ec2c5e43
LP
574
575 r = dns_transaction_go(t);
576 if (r < 0) {
577 dns_transaction_complete(t, DNS_TRANSACTION_RESOURCES);
578 return;
579 }
580
581 return;
582 }
583 }
584
8af5b883 585 /* Parse message, if it isn't parsed yet. */
ec2c5e43
LP
586 r = dns_packet_extract(p);
587 if (r < 0) {
588 dns_transaction_complete(t, DNS_TRANSACTION_INVALID_REPLY);
589 return;
590 }
591
b5efcf29
LP
592 if (IN_SET(t->scope->protocol, DNS_PROTOCOL_DNS, DNS_PROTOCOL_LLMNR)) {
593
547493c5 594 /* Only consider responses with equivalent query section to the request */
8af5b883
LP
595 r = dns_packet_is_reply_for(p, t->key);
596 if (r < 0) {
597 dns_transaction_complete(t, DNS_TRANSACTION_RESOURCES);
598 return;
599 }
600 if (r == 0) {
547493c5
DM
601 dns_transaction_complete(t, DNS_TRANSACTION_INVALID_REPLY);
602 return;
603 }
29815b6c 604
547493c5
DM
605 /* Install the answer as answer to the transaction */
606 dns_answer_unref(t->answer);
607 t->answer = dns_answer_ref(p->answer);
608 t->answer_rcode = DNS_PACKET_RCODE(p);
609 t->answer_authenticated = t->scope->dnssec_mode == DNSSEC_TRUST && DNS_PACKET_AD(p);
610
79e24931
LP
611 /* According to RFC 4795, section 2.9. only the RRs
612 * from the answer section shall be cached. However,
613 * if we know the message is authenticated, we might
614 * as well cache everything. */
615 if (t->answer_authenticated)
616 t->n_answer_cacheable = (unsigned) -1; /* everything! */
617 else
618 t->n_answer_cacheable = DNS_PACKET_ANCOUNT(t->received); /* only the answer section */
619
547973de
LP
620 r = dns_transaction_request_dnssec_keys(t);
621 if (r < 0) {
622 dns_transaction_complete(t, DNS_TRANSACTION_RESOURCES);
623 return;
624 }
625 if (r > 0) {
626 /* There are DNSSEC transactions pending now. Update the state accordingly. */
627 t->state = DNS_TRANSACTION_VALIDATING;
628 return;
629 }
547493c5 630 }
ec2c5e43 631
547973de 632 dns_transaction_process_dnssec(t);
ec2c5e43
LP
633}
634
c19ffd9f
TG
635static int on_dns_packet(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
636 _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
637 DnsTransaction *t = userdata;
638 int r;
639
640 assert(t);
641 assert(t->scope);
642
643 r = manager_recv(t->scope->manager, fd, DNS_PROTOCOL_DNS, &p);
644 if (r <= 0)
645 return r;
646
647 if (dns_packet_validate_reply(p) > 0 &&
9df3ba6c 648 DNS_PACKET_ID(p) == t->id)
c19ffd9f 649 dns_transaction_process_reply(t, p);
9df3ba6c 650 else
8af5b883 651 log_debug("Invalid DNS packet, ignoring.");
c19ffd9f
TG
652
653 return 0;
654}
655
471d40d9 656static int dns_transaction_emit(DnsTransaction *t) {
c19ffd9f
TG
657 int r;
658
659 assert(t);
c19ffd9f 660
471d40d9
TG
661 if (t->scope->protocol == DNS_PROTOCOL_DNS && !t->server) {
662 DnsServer *server = NULL;
663 _cleanup_close_ int fd = -1;
c19ffd9f 664
471d40d9
TG
665 fd = dns_scope_udp_dns_socket(t->scope, &server);
666 if (fd < 0)
667 return fd;
c19ffd9f 668
4667e00a 669 r = sd_event_add_io(t->scope->manager->event, &t->dns_udp_event_source, fd, EPOLLIN, on_dns_packet, t);
471d40d9
TG
670 if (r < 0)
671 return r;
c19ffd9f 672
4667e00a 673 t->dns_udp_fd = fd;
471d40d9
TG
674 fd = -1;
675 t->server = dns_server_ref(server);
676 }
c19ffd9f 677
9c5e12a4 678 r = dns_scope_emit(t->scope, t->dns_udp_fd, t->server, t->sent);
471d40d9
TG
679 if (r < 0)
680 return r;
c19ffd9f 681
be808ea0
TG
682 if (t->server)
683 t->current_features = t->server->possible_features;
684
471d40d9 685 return 0;
c19ffd9f
TG
686}
687
ec2c5e43
LP
688static int on_transaction_timeout(sd_event_source *s, usec_t usec, void *userdata) {
689 DnsTransaction *t = userdata;
690 int r;
691
692 assert(s);
693 assert(t);
694
ef7ce6df
DM
695 if (!t->initial_jitter_scheduled || t->initial_jitter_elapsed) {
696 /* Timeout reached? Increase the timeout for the server used */
697 switch (t->scope->protocol) {
698 case DNS_PROTOCOL_DNS:
699 assert(t->server);
ec2c5e43 700
ef7ce6df 701 dns_server_packet_lost(t->server, t->current_features, usec - t->start_usec);
be808ea0 702
ef7ce6df
DM
703 break;
704 case DNS_PROTOCOL_LLMNR:
705 case DNS_PROTOCOL_MDNS:
706 dns_scope_packet_lost(t->scope, usec - t->start_usec);
9df3ba6c 707
ef7ce6df
DM
708 break;
709 default:
710 assert_not_reached("Invalid DNS protocol.");
711 }
712
713 if (t->initial_jitter_scheduled)
714 t->initial_jitter_elapsed = true;
be808ea0
TG
715 }
716
717 /* ...and try again with a new server */
718 dns_transaction_next_dns_server(t);
719
ec2c5e43
LP
720 r = dns_transaction_go(t);
721 if (r < 0)
722 dns_transaction_complete(t, DNS_TRANSACTION_RESOURCES);
723
724 return 0;
725}
726
9df3ba6c
TG
727static usec_t transaction_get_resend_timeout(DnsTransaction *t) {
728 assert(t);
729 assert(t->scope);
730
731 switch (t->scope->protocol) {
732 case DNS_PROTOCOL_DNS:
733 assert(t->server);
734
735 return t->server->resend_timeout;
9df3ba6c 736 case DNS_PROTOCOL_MDNS:
11a27c2e
DM
737 assert(t->n_attempts > 0);
738 return (1 << (t->n_attempts - 1)) * USEC_PER_SEC;
739 case DNS_PROTOCOL_LLMNR:
9df3ba6c
TG
740 return t->scope->resend_timeout;
741 default:
742 assert_not_reached("Invalid DNS protocol.");
743 }
744}
745
c842ff24 746static int dns_transaction_prepare(DnsTransaction *t, usec_t ts) {
ec2c5e43
LP
747 bool had_stream;
748 int r;
749
750 assert(t);
751
752 had_stream = !!t->stream;
753
754 dns_transaction_stop(t);
755
ec2c5e43
LP
756 if (t->n_attempts >= TRANSACTION_ATTEMPTS_MAX(t->scope->protocol)) {
757 dns_transaction_complete(t, DNS_TRANSACTION_ATTEMPTS_MAX_REACHED);
758 return 0;
759 }
760
761 if (t->scope->protocol == DNS_PROTOCOL_LLMNR && had_stream) {
762 /* If we already tried via a stream, then we don't
763 * retry on LLMNR. See RFC 4795, Section 2.7. */
764 dns_transaction_complete(t, DNS_TRANSACTION_ATTEMPTS_MAX_REACHED);
765 return 0;
766 }
767
768 t->n_attempts++;
9df3ba6c 769 t->start_usec = ts;
ec2c5e43 770 t->received = dns_packet_unref(t->received);
ae6a4bbf 771 t->answer = dns_answer_unref(t->answer);
79e24931 772 t->n_answer_cacheable = 0;
ae6a4bbf 773 t->answer_rcode = 0;
c3bc53e6 774 t->answer_source = _DNS_TRANSACTION_SOURCE_INVALID;
ec2c5e43 775
0d2cd476
LP
776 /* Check the trust anchor. Do so only on classic DNS, since DNSSEC does not apply otherwise. */
777 if (t->scope->protocol == DNS_PROTOCOL_DNS) {
778 r = dns_trust_anchor_lookup(&t->scope->manager->trust_anchor, t->key, &t->answer);
779 if (r < 0)
780 return r;
781 if (r > 0) {
782 t->answer_rcode = DNS_RCODE_SUCCESS;
783 t->answer_source = DNS_TRANSACTION_TRUST_ANCHOR;
931851e8 784 t->answer_authenticated = true;
0d2cd476
LP
785 dns_transaction_complete(t, DNS_TRANSACTION_SUCCESS);
786 return 0;
787 }
788 }
789
790 /* Check the zone, but only if this transaction is not used
d746bb3e 791 * for probing or verifying a zone item. */
547973de 792 if (set_isempty(t->notify_zone_items)) {
d746bb3e 793
ae6a4bbf 794 r = dns_zone_lookup(&t->scope->zone, t->key, &t->answer, NULL, NULL);
d746bb3e
LP
795 if (r < 0)
796 return r;
797 if (r > 0) {
ae6a4bbf 798 t->answer_rcode = DNS_RCODE_SUCCESS;
c3bc53e6 799 t->answer_source = DNS_TRANSACTION_ZONE;
931851e8 800 t->answer_authenticated = true;
d746bb3e
LP
801 dns_transaction_complete(t, DNS_TRANSACTION_SUCCESS);
802 return 0;
803 }
804 }
805
4d926a69
LP
806 /* Check the cache, but only if this transaction is not used
807 * for probing or verifying a zone item. */
547973de 808 if (set_isempty(t->notify_zone_items)) {
2c27fbca 809
4d926a69
LP
810 /* Before trying the cache, let's make sure we figured out a
811 * server to use. Should this cause a change of server this
812 * might flush the cache. */
813 dns_scope_get_dns_server(t->scope);
2c27fbca 814
4d926a69
LP
815 /* Let's then prune all outdated entries */
816 dns_cache_prune(&t->scope->cache);
817
931851e8 818 r = dns_cache_lookup(&t->scope->cache, t->key, &t->answer_rcode, &t->answer, &t->answer_authenticated);
4d926a69
LP
819 if (r < 0)
820 return r;
821 if (r > 0) {
c3bc53e6 822 t->answer_source = DNS_TRANSACTION_CACHE;
ae6a4bbf 823 if (t->answer_rcode == DNS_RCODE_SUCCESS)
4d926a69
LP
824 dns_transaction_complete(t, DNS_TRANSACTION_SUCCESS);
825 else
826 dns_transaction_complete(t, DNS_TRANSACTION_FAILURE);
827 return 0;
828 }
ec2c5e43
LP
829 }
830
1effe965
DM
831 return 1;
832}
833
0afa57e2
DM
834static int dns_transaction_make_packet_mdns(DnsTransaction *t) {
835
836 _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
7778dfff 837 bool add_known_answers = false;
0afa57e2
DM
838 DnsTransaction *other;
839 unsigned qdcount;
840 usec_t ts;
841 int r;
842
843 assert(t);
844 assert(t->scope->protocol == DNS_PROTOCOL_MDNS);
845
846 /* Discard any previously prepared packet, so we can start over and coaleasce again */
847 t->sent = dns_packet_unref(t->sent);
848
849 r = dns_packet_new_query(&p, t->scope->protocol, 0, false);
850 if (r < 0)
851 return r;
852
853 r = dns_packet_append_key(p, t->key, NULL);
854 if (r < 0)
855 return r;
856
857 qdcount = 1;
858
7778dfff
DM
859 if (dns_key_is_shared(t->key))
860 add_known_answers = true;
861
0afa57e2
DM
862 /*
863 * For mDNS, we want to coalesce as many open queries in pending transactions into one single
864 * query packet on the wire as possible. To achieve that, we iterate through all pending transactions
865 * in our current scope, and see whether their timing contraints allow them to be sent.
866 */
867
868 assert_se(sd_event_now(t->scope->manager->event, clock_boottime_or_monotonic(), &ts) >= 0);
869
870 LIST_FOREACH(transactions_by_scope, other, t->scope->transactions) {
871
872 /* Skip ourselves */
873 if (other == t)
874 continue;
875
876 if (other->state != DNS_TRANSACTION_PENDING)
877 continue;
878
879 if (other->next_attempt_after > ts)
880 continue;
881
882 if (qdcount >= UINT16_MAX)
883 break;
884
885 r = dns_packet_append_key(p, other->key, NULL);
886
887 /*
888 * If we can't stuff more questions into the packet, just give up.
889 * One of the 'other' transactions will fire later and take care of the rest.
890 */
891 if (r == -EMSGSIZE)
892 break;
893
894 if (r < 0)
895 return r;
896
c842ff24 897 r = dns_transaction_prepare(other, ts);
0afa57e2
DM
898 if (r <= 0)
899 continue;
900
901 ts += transaction_get_resend_timeout(other);
902
903 r = sd_event_add_time(
904 other->scope->manager->event,
905 &other->timeout_event_source,
906 clock_boottime_or_monotonic(),
907 ts, 0,
908 on_transaction_timeout, other);
909 if (r < 0)
910 return r;
911
912 other->state = DNS_TRANSACTION_PENDING;
913 other->next_attempt_after = ts;
914
915 qdcount ++;
7778dfff
DM
916
917 if (dns_key_is_shared(other->key))
918 add_known_answers = true;
0afa57e2
DM
919 }
920
921 DNS_PACKET_HEADER(p)->qdcount = htobe16(qdcount);
0afa57e2 922
7778dfff
DM
923 /* Append known answer section if we're asking for any shared record */
924 if (add_known_answers) {
925 r = dns_cache_export_shared_to_packet(&t->scope->cache, p);
926 if (r < 0)
927 return r;
928 }
929
0afa57e2
DM
930 t->sent = p;
931 p = NULL;
932
933 return 0;
934}
935
936static int dns_transaction_make_packet(DnsTransaction *t) {
937 _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
938 int r;
939
940 assert(t);
941
942 if (t->scope->protocol == DNS_PROTOCOL_MDNS)
943 return dns_transaction_make_packet_mdns(t);
944
945 if (t->sent)
946 return 0;
947
948 r = dns_packet_new_query(&p, t->scope->protocol, 0, t->scope->dnssec_mode == DNSSEC_YES);
949 if (r < 0)
950 return r;
951
952 r = dns_scope_good_key(t->scope, t->key);
953 if (r < 0)
954 return r;
955 if (r == 0)
956 return -EDOM;
957
958 r = dns_packet_append_key(p, t->key, NULL);
959 if (r < 0)
960 return r;
961
962 DNS_PACKET_HEADER(p)->qdcount = htobe16(1);
963 DNS_PACKET_HEADER(p)->id = t->id;
964
965 t->sent = p;
966 p = NULL;
967
968 return 0;
969}
970
1effe965
DM
971int dns_transaction_go(DnsTransaction *t) {
972 usec_t ts;
973 int r;
974
975 assert(t);
976
977 assert_se(sd_event_now(t->scope->manager->event, clock_boottime_or_monotonic(), &ts) >= 0);
547973de 978
c842ff24 979 r = dns_transaction_prepare(t, ts);
1effe965
DM
980 if (r <= 0)
981 return r;
982
547973de
LP
983 if (log_get_max_level() >= LOG_DEBUG) {
984 _cleanup_free_ char *ks = NULL;
985
986 (void) dns_resource_key_to_string(t->key, &ks);
987
988 log_debug("Excercising transaction for <%s> on scope %s on %s/%s",
989 ks ? strstrip(ks) : "???",
990 dns_protocol_to_string(t->scope->protocol),
991 t->scope->link ? t->scope->link->name : "*",
992 t->scope->family == AF_UNSPEC ? "*" : af_to_name(t->scope->family));
993 }
1effe965 994
ef7ce6df 995 if (!t->initial_jitter_scheduled &&
ea12bcc7
DM
996 (t->scope->protocol == DNS_PROTOCOL_LLMNR ||
997 t->scope->protocol == DNS_PROTOCOL_MDNS)) {
998 usec_t jitter, accuracy;
6e068472
LP
999
1000 /* RFC 4795 Section 2.7 suggests all queries should be
1001 * delayed by a random time from 0 to JITTER_INTERVAL. */
1002
ef7ce6df 1003 t->initial_jitter_scheduled = true;
6e068472
LP
1004
1005 random_bytes(&jitter, sizeof(jitter));
ea12bcc7
DM
1006
1007 switch (t->scope->protocol) {
1008 case DNS_PROTOCOL_LLMNR:
1009 jitter %= LLMNR_JITTER_INTERVAL_USEC;
1010 accuracy = LLMNR_JITTER_INTERVAL_USEC;
1011 break;
1012 case DNS_PROTOCOL_MDNS:
1013 jitter %= MDNS_JITTER_RANGE_USEC;
1014 jitter += MDNS_JITTER_MIN_USEC;
1015 accuracy = MDNS_JITTER_RANGE_USEC;
1016 break;
1017 default:
1018 assert_not_reached("bad protocol");
1019 }
6e068472
LP
1020
1021 r = sd_event_add_time(
1022 t->scope->manager->event,
1023 &t->timeout_event_source,
1024 clock_boottime_or_monotonic(),
ea12bcc7 1025 ts + jitter, accuracy,
6e068472
LP
1026 on_transaction_timeout, t);
1027 if (r < 0)
1028 return r;
1029
1030 t->n_attempts = 0;
a9da14e1 1031 t->next_attempt_after = ts;
6e068472
LP
1032 t->state = DNS_TRANSACTION_PENDING;
1033
ea12bcc7 1034 log_debug("Delaying %s transaction for " USEC_FMT "us.", dns_protocol_to_string(t->scope->protocol), jitter);
6e068472
LP
1035 return 0;
1036 }
1037
ec2c5e43
LP
1038 /* Otherwise, we need to ask the network */
1039 r = dns_transaction_make_packet(t);
1040 if (r == -EDOM) {
1041 /* Not the right request to make on this network?
1042 * (i.e. an A request made on IPv6 or an AAAA request
1043 * made on IPv4, on LLMNR or mDNS.) */
1044 dns_transaction_complete(t, DNS_TRANSACTION_NO_SERVERS);
1045 return 0;
1046 }
1047 if (r < 0)
1048 return r;
1049
1050 if (t->scope->protocol == DNS_PROTOCOL_LLMNR &&
f52e61da
LP
1051 (dns_name_endswith(DNS_RESOURCE_KEY_NAME(t->key), "in-addr.arpa") > 0 ||
1052 dns_name_endswith(DNS_RESOURCE_KEY_NAME(t->key), "ip6.arpa") > 0)) {
ec2c5e43
LP
1053
1054 /* RFC 4795, Section 2.4. says reverse lookups shall
1055 * always be made via TCP on LLMNR */
1056 r = dns_transaction_open_tcp(t);
1057 } else {
be808ea0
TG
1058 /* Try via UDP, and if that fails due to large size or lack of
1059 * support try via TCP */
471d40d9 1060 r = dns_transaction_emit(t);
be808ea0 1061 if (r == -EMSGSIZE || r == -EAGAIN)
ec2c5e43
LP
1062 r = dns_transaction_open_tcp(t);
1063 }
be808ea0 1064
ec2c5e43
LP
1065 if (r == -ESRCH) {
1066 /* No servers to send this to? */
1067 dns_transaction_complete(t, DNS_TRANSACTION_NO_SERVERS);
1068 return 0;
8300ba21 1069 } else if (r < 0) {
13b551ac
LP
1070 if (t->scope->protocol != DNS_PROTOCOL_DNS) {
1071 dns_transaction_complete(t, DNS_TRANSACTION_RESOURCES);
1072 return 0;
1073 }
1074
ec2c5e43 1075 /* Couldn't send? Try immediately again, with a new server */
647f6aa8 1076 dns_transaction_next_dns_server(t);
ec2c5e43
LP
1077
1078 return dns_transaction_go(t);
1079 }
1080
a9da14e1
DM
1081 ts += transaction_get_resend_timeout(t);
1082
9a015429
LP
1083 r = sd_event_add_time(
1084 t->scope->manager->event,
1085 &t->timeout_event_source,
1086 clock_boottime_or_monotonic(),
a9da14e1 1087 ts, 0,
9a015429 1088 on_transaction_timeout, t);
ec2c5e43
LP
1089 if (r < 0)
1090 return r;
1091
1092 t->state = DNS_TRANSACTION_PENDING;
a9da14e1
DM
1093 t->next_attempt_after = ts;
1094
ec2c5e43
LP
1095 return 1;
1096}
1097
547973de
LP
1098static int dns_transaction_add_dnssec_transaction(DnsTransaction *t, DnsResourceKey *key, DnsTransaction **ret) {
1099 DnsTransaction *aux;
1100 int r;
1101
1102 assert(t);
1103 assert(ret);
1104 assert(key);
1105
1106 aux = dns_scope_find_transaction(t->scope, key, true);
1107 if (!aux) {
1108 r = dns_transaction_new(&aux, t->scope, key);
1109 if (r < 0)
1110 return r;
1111 } else {
1112 if (set_contains(t->dnssec_transactions, aux)) {
1113 *ret = aux;
1114 return 0;
1115 }
1116 }
1117
1118 r = set_ensure_allocated(&t->dnssec_transactions, NULL);
1119 if (r < 0)
1120 goto gc;
1121
1122 r = set_ensure_allocated(&aux->notify_transactions, NULL);
1123 if (r < 0)
1124 goto gc;
1125
1126 r = set_put(t->dnssec_transactions, aux);
1127 if (r < 0)
1128 goto gc;
1129
1130 r = set_put(aux->notify_transactions, t);
1131 if (r < 0) {
1132 (void) set_remove(t->dnssec_transactions, aux);
1133 goto gc;
1134 }
1135
1136 *ret = aux;
1137 return 1;
1138
1139gc:
1140 dns_transaction_gc(aux);
1141 return r;
1142}
1143
1144static int dns_transaction_request_dnssec_rr(DnsTransaction *t, DnsResourceKey *key) {
1145 _cleanup_(dns_answer_unrefp) DnsAnswer *a = NULL;
1146 DnsTransaction *aux;
1147 int r;
1148
1149 assert(t);
1150 assert(key);
1151
1152 /* Try to get the data from the trust anchor */
1153 r = dns_trust_anchor_lookup(&t->scope->manager->trust_anchor, key, &a);
1154 if (r < 0)
1155 return r;
1156 if (r > 0) {
1157 r = dns_answer_extend(&t->validated_keys, a);
1158 if (r < 0)
1159 return r;
1160
1161 return 0;
1162 }
1163
1164 /* This didn't work, ask for it via the network/cache then. */
1165 r = dns_transaction_add_dnssec_transaction(t, key, &aux);
1166 if (r < 0)
1167 return r;
1168
1169 if (aux->state == DNS_TRANSACTION_NULL) {
1170 r = dns_transaction_go(aux);
1171 if (r < 0)
1172 return r;
1173 }
1174
1175 return 0;
1176}
1177
1178int dns_transaction_request_dnssec_keys(DnsTransaction *t) {
1179 DnsResourceRecord *rr;
1180 int r;
1181
1182 assert(t);
1183
1184 if (t->scope->dnssec_mode != DNSSEC_YES)
1185 return 0;
1186
1187 DNS_ANSWER_FOREACH(rr, t->answer) {
1188
1189 switch (rr->key->type) {
1190
1191 case DNS_TYPE_RRSIG: {
1192 /* For each RRSIG we request the matching DNSKEY */
1193 _cleanup_(dns_resource_key_unrefp) DnsResourceKey *dnskey = NULL;
1194
1195 /* If this RRSIG is about a DNSKEY RR and the
1196 * signer is the same as the owner, then we
1197 * already have the DNSKEY, and we don't have
1198 * to look for more. */
1199 if (rr->rrsig.type_covered == DNS_TYPE_DNSKEY) {
1200 r = dns_name_equal(rr->rrsig.signer, DNS_RESOURCE_KEY_NAME(rr->key));
1201 if (r < 0)
1202 return r;
1203 if (r > 0)
1204 continue;
1205 }
1206
1207 /* If the signer is not a parent of the owner,
1208 * then the signature is bogus, let's ignore
1209 * it. */
1210 r = dns_name_endswith(DNS_RESOURCE_KEY_NAME(rr->key), rr->rrsig.signer);
1211 if (r < 0)
1212 return r;
1213 if (r == 0)
1214 continue;
1215
1216 dnskey = dns_resource_key_new(rr->key->class, DNS_TYPE_DNSKEY, rr->rrsig.signer);
1217 if (!dnskey)
1218 return -ENOMEM;
1219
1220 log_debug("Requesting DNSKEY to validate transaction %" PRIu16" (key tag: %" PRIu16 ").", t->id, rr->rrsig.key_tag);
1221
1222 r = dns_transaction_request_dnssec_rr(t, dnskey);
1223 if (r < 0)
1224 return r;
1225 break;
1226 }
1227
1228 case DNS_TYPE_DNSKEY: {
1229 /* For each DNSKEY we request the matching DS */
1230 _cleanup_(dns_resource_key_unrefp) DnsResourceKey *ds = NULL;
1231
1232 ds = dns_resource_key_new(rr->key->class, DNS_TYPE_DS, DNS_RESOURCE_KEY_NAME(rr->key));
1233 if (!ds)
1234 return -ENOMEM;
1235
1236 log_debug("Requesting DS to validate transaction %" PRIu16" (key tag: %" PRIu16 ").", t->id, dnssec_keytag(rr));
1237
1238 r = dns_transaction_request_dnssec_rr(t, ds);
1239 if (r < 0)
1240 return r;
1241
1242 break;
1243 }}
1244 }
1245
1246 return !set_isempty(t->dnssec_transactions);
1247}
1248
1249void dns_transaction_notify(DnsTransaction *t, DnsTransaction *source) {
1250 int r;
1251
1252 assert(t);
1253 assert(IN_SET(t->state, DNS_TRANSACTION_PENDING, DNS_TRANSACTION_VALIDATING));
1254 assert(source);
1255
1256 /* Invoked whenever any of our auxiliary DNSSEC transactions
1257 completed its work. We simply copy the answer from that
1258 transaction over. */
1259
1260 if (source->state != DNS_TRANSACTION_SUCCESS) {
1261 log_debug("Auxiliary DNSSEC RR query failed.");
1262 t->dnssec_result = DNSSEC_FAILED_AUXILIARY;
1263 } else {
1264 r = dns_answer_extend(&t->validated_keys, source->answer);
1265 if (r < 0) {
1266 log_error_errno(r, "Failed to merge validated DNSSEC key data: %m");
1267 t->dnssec_result = DNSSEC_FAILED_AUXILIARY;
1268 }
1269 }
1270
1271 /* Detach us from the DNSSEC transaction. */
1272 (void) set_remove(t->dnssec_transactions, source);
1273 (void) set_remove(source->notify_transactions, t);
1274
1275 /* If the state is still PENDING, we are still in the loop
1276 * that adds further DNSSEC transactions, hence don't check if
1277 * we are ready yet. If the state is VALIDATING however, we
1278 * should check if we are complete now. */
1279 if (t->state == DNS_TRANSACTION_VALIDATING)
1280 dns_transaction_process_dnssec(t);
1281}
1282
56352fe9
LP
1283static int dns_transaction_is_primary_response(DnsTransaction *t, DnsResourceRecord *rr) {
1284 int r;
1285
1286 assert(t);
1287 assert(rr);
1288
1289 /* Check if the specified RR is the "primary" response,
1290 * i.e. either matches the question precisely or is a
1291 * CNAME/DNAME for it */
1292
1293 r = dns_resource_key_match_rr(t->key, rr, NULL);
1294 if (r != 0)
1295 return r;
1296
1297 r = dns_resource_key_match_cname_or_dname(t->key, rr->key, NULL);
1298 if (r != 0)
1299 return r;
1300
1301 return 0;
1302}
1303
1304static int dns_transaction_validate_dnskey_by_ds(DnsTransaction *t) {
1305 DnsResourceRecord *rr;
1306 int ifindex, r;
1307
1308 assert(t);
1309
1310 /* Add all DNSKEY RRs from the answer that are validated by DS
1311 * RRs from the list of validated keys to the lis of validated
1312 * keys. */
1313
1314 DNS_ANSWER_FOREACH_IFINDEX(rr, ifindex, t->answer) {
1315
1316 r = dnssec_verify_dnskey_search(rr, t->validated_keys);
1317 if (r < 0)
1318 return r;
1319 if (r == 0)
1320 continue;
1321
1322 /* If so, the DNSKEY is validated too. */
1323 r = dns_answer_add_extend(&t->validated_keys, rr, ifindex);
1324 if (r < 0)
1325 return r;
1326 }
1327
1328 return 0;
1329}
1330
547973de
LP
1331int dns_transaction_validate_dnssec(DnsTransaction *t) {
1332 _cleanup_(dns_answer_unrefp) DnsAnswer *validated = NULL;
56352fe9 1333 bool dnskeys_finalized = false;
547973de 1334 DnsResourceRecord *rr;
56352fe9 1335 int r;
547973de
LP
1336
1337 assert(t);
1338
1339 /* We have now collected all DS and DNSKEY RRs in
1340 * t->validated_keys, let's see which RRs we can now
1341 * authenticate with that. */
1342
1343 if (t->scope->dnssec_mode != DNSSEC_YES)
1344 return 0;
1345
1346 /* Already validated */
1347 if (t->dnssec_result != _DNSSEC_RESULT_INVALID)
1348 return 0;
1349
1350 if (IN_SET(t->answer_source, DNS_TRANSACTION_ZONE, DNS_TRANSACTION_TRUST_ANCHOR)) {
1351 t->dnssec_result = DNSSEC_VALIDATED;
1352 t->answer_authenticated = true;
1353 return 0;
1354 }
1355
1356 if (log_get_max_level() >= LOG_DEBUG) {
1357 _cleanup_free_ char *ks = NULL;
1358
1359 (void) dns_resource_key_to_string(t->key, &ks);
1360 log_debug("Validating response from transaction %" PRIu16 " (%s).", t->id, ks ? strstrip(ks) : "???");
1361 }
1362
1363 /* First see if there are DNSKEYs we already known a validated DS for. */
56352fe9
LP
1364 r = dns_transaction_validate_dnskey_by_ds(t);
1365 if (r < 0)
1366 return r;
547973de
LP
1367
1368 for (;;) {
56352fe9 1369 bool changed = false;
547973de
LP
1370
1371 DNS_ANSWER_FOREACH(rr, t->answer) {
1372 DnssecResult result;
1373
1374 if (rr->key->type == DNS_TYPE_RRSIG)
1375 continue;
1376
1377 r = dnssec_verify_rrset_search(t->answer, rr->key, t->validated_keys, USEC_INFINITY, &result);
1378 if (r < 0)
1379 return r;
1380
1381 if (log_get_max_level() >= LOG_DEBUG) {
1382 _cleanup_free_ char *rrs = NULL;
1383
1384 (void) dns_resource_record_to_string(rr, &rrs);
1385 log_debug("Looking at %s: %s", rrs ? strstrip(rrs) : "???", dnssec_result_to_string(result));
1386 }
1387
56352fe9 1388 if (result == DNSSEC_VALIDATED) {
547973de
LP
1389
1390 /* Add the validated RRset to the new list of validated RRsets */
1391 r = dns_answer_copy_by_key(&validated, t->answer, rr->key);
1392 if (r < 0)
1393 return r;
1394
1395 if (rr->key->type == DNS_TYPE_DNSKEY) {
1396 /* If we just validated a
1397 * DNSKEY RRset, then let's
1398 * add these keys to the set
1399 * of validated keys for this
1400 * transaction. */
1401
1402 r = dns_answer_copy_by_key(&t->validated_keys, t->answer, rr->key);
1403 if (r < 0)
1404 return r;
1405 }
1406
1407 /* Now, remove this RRset from the RRs still to process */
1408 r = dns_answer_remove_by_key(&t->answer, rr->key);
1409 if (r < 0)
1410 return r;
1411
56352fe9 1412 /* Exit the loop, we dropped something from the answer, start from the beginning */
547973de
LP
1413 changed = true;
1414 break;
1415
56352fe9
LP
1416 } else if (dnskeys_finalized) {
1417 /* If we haven't read all DNSKEYs yet
1418 * a negative result of the validation
1419 * is irrelevant, as there might be
1420 * more DNSKEYs coming. */
547973de 1421
56352fe9 1422 r = dns_transaction_is_primary_response(t, rr);
547973de
LP
1423 if (r < 0)
1424 return r;
1425 if (r > 0) {
56352fe9
LP
1426 /* This is a primary response
1427 * to our question, and it
1428 * failed validation. That's
1429 * fatal. */
547973de
LP
1430 t->dnssec_result = result;
1431 return 0;
1432 }
1433
56352fe9
LP
1434 /* This is just some auxiliary
1435 * data. Just remove the RRset and
1436 * continue. */
547973de
LP
1437 r = dns_answer_remove_by_key(&t->answer, rr->key);
1438 if (r < 0)
1439 return r;
1440
56352fe9 1441 /* Exit the loop, we dropped something from the answer, start from the beginning */
547973de
LP
1442 changed = true;
1443 break;
547973de 1444 }
547973de
LP
1445 }
1446
1447 if (changed)
1448 continue;
1449
56352fe9
LP
1450 if (!dnskeys_finalized) {
1451 /* OK, now we know we have added all DNSKEYs
1452 * we possibly could to our validated
1453 * list. Now run the whole thing once more,
1454 * and strip everything we still cannot
1455 * validate.
1456 */
1457 dnskeys_finalized = true;
1458 continue;
547973de
LP
1459 }
1460
56352fe9 1461 /* We're done */
547973de
LP
1462 break;
1463 }
1464
1465 dns_answer_unref(t->answer);
1466 t->answer = validated;
1467 validated = NULL;
1468
79e24931
LP
1469 /* Everything that's now in t->answer is known to be good, hence cacheable. */
1470 t->n_answer_cacheable = (unsigned) -1; /* everything! */
1471
547973de
LP
1472 t->answer_authenticated = true;
1473 t->dnssec_result = DNSSEC_VALIDATED;
1474 return 1;
1475}
1476
ec2c5e43
LP
1477static const char* const dns_transaction_state_table[_DNS_TRANSACTION_STATE_MAX] = {
1478 [DNS_TRANSACTION_NULL] = "null",
1479 [DNS_TRANSACTION_PENDING] = "pending",
547973de 1480 [DNS_TRANSACTION_VALIDATING] = "validating",
ec2c5e43
LP
1481 [DNS_TRANSACTION_FAILURE] = "failure",
1482 [DNS_TRANSACTION_SUCCESS] = "success",
1483 [DNS_TRANSACTION_NO_SERVERS] = "no-servers",
1484 [DNS_TRANSACTION_TIMEOUT] = "timeout",
1485 [DNS_TRANSACTION_ATTEMPTS_MAX_REACHED] = "attempts-max-reached",
1486 [DNS_TRANSACTION_INVALID_REPLY] = "invalid-reply",
1487 [DNS_TRANSACTION_RESOURCES] = "resources",
1488 [DNS_TRANSACTION_ABORTED] = "aborted",
547973de 1489 [DNS_TRANSACTION_DNSSEC_FAILED] = "dnssec-failed",
ec2c5e43
LP
1490};
1491DEFINE_STRING_TABLE_LOOKUP(dns_transaction_state, DnsTransactionState);
c3bc53e6
LP
1492
1493static const char* const dns_transaction_source_table[_DNS_TRANSACTION_SOURCE_MAX] = {
1494 [DNS_TRANSACTION_NETWORK] = "network",
1495 [DNS_TRANSACTION_CACHE] = "cache",
1496 [DNS_TRANSACTION_ZONE] = "zone",
0d2cd476 1497 [DNS_TRANSACTION_TRUST_ANCHOR] = "trust-anchor",
c3bc53e6
LP
1498};
1499DEFINE_STRING_TABLE_LOOKUP(dns_transaction_source, DnsTransactionSource);