]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/resolve/resolved-dns-transaction.c
resolved: generalize DNS RR type validity checks
[thirdparty/systemd.git] / src / resolve / resolved-dns-transaction.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4 This file is part of systemd.
5
6 Copyright 2014 Lennart Poettering
7
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
12
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22 #include "af-list.h"
23 #include "alloc-util.h"
24 #include "dns-domain.h"
25 #include "fd-util.h"
26 #include "random-util.h"
27 #include "resolved-dns-cache.h"
28 #include "resolved-dns-transaction.h"
29 #include "resolved-llmnr.h"
30 #include "string-table.h"
31
32 DnsTransaction* dns_transaction_free(DnsTransaction *t) {
33 DnsQueryCandidate *c;
34 DnsZoneItem *i;
35 DnsTransaction *z;
36
37 if (!t)
38 return NULL;
39
40 sd_event_source_unref(t->timeout_event_source);
41
42 dns_packet_unref(t->sent);
43 dns_packet_unref(t->received);
44
45 dns_answer_unref(t->answer);
46
47 sd_event_source_unref(t->dns_udp_event_source);
48 safe_close(t->dns_udp_fd);
49
50 dns_server_unref(t->server);
51 dns_stream_free(t->stream);
52
53 if (t->scope) {
54 hashmap_remove_value(t->scope->transactions_by_key, t->key, t);
55 LIST_REMOVE(transactions_by_scope, t->scope->transactions, t);
56
57 if (t->id != 0)
58 hashmap_remove(t->scope->manager->dns_transactions, UINT_TO_PTR(t->id));
59 }
60
61 dns_resource_key_unref(t->key);
62
63 while ((c = set_steal_first(t->notify_query_candidates)))
64 set_remove(c->transactions, t);
65 set_free(t->notify_query_candidates);
66
67 while ((i = set_steal_first(t->notify_zone_items)))
68 i->probe_transaction = NULL;
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);
82
83 free(t);
84 return NULL;
85 }
86
87 DEFINE_TRIVIAL_CLEANUP_FUNC(DnsTransaction*, dns_transaction_free);
88
89 void dns_transaction_gc(DnsTransaction *t) {
90 assert(t);
91
92 if (t->block_gc > 0)
93 return;
94
95 if (set_isempty(t->notify_query_candidates) &&
96 set_isempty(t->notify_zone_items) &&
97 set_isempty(t->notify_transactions))
98 dns_transaction_free(t);
99 }
100
101 int dns_transaction_new(DnsTransaction **ret, DnsScope *s, DnsResourceKey *key) {
102 _cleanup_(dns_transaction_freep) DnsTransaction *t = NULL;
103 int r;
104
105 assert(ret);
106 assert(s);
107 assert(key);
108
109 /* Don't allow looking up invalid or pseudo RRs */
110 if (!dns_type_is_valid_query(key->type))
111 return -EINVAL;
112
113 /* We only support the IN class */
114 if (key->class != DNS_CLASS_IN && key->class != DNS_CLASS_ANY)
115 return -EOPNOTSUPP;
116
117 r = hashmap_ensure_allocated(&s->manager->dns_transactions, NULL);
118 if (r < 0)
119 return r;
120
121 r = hashmap_ensure_allocated(&s->transactions_by_key, &dns_resource_key_hash_ops);
122 if (r < 0)
123 return r;
124
125 t = new0(DnsTransaction, 1);
126 if (!t)
127 return -ENOMEM;
128
129 t->dns_udp_fd = -1;
130 t->answer_source = _DNS_TRANSACTION_SOURCE_INVALID;
131 t->dnssec_result = _DNSSEC_RESULT_INVALID;
132 t->key = dns_resource_key_ref(key);
133
134 /* Find a fresh, unused transaction id */
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
146 r = hashmap_replace(s->transactions_by_key, t->key, t);
147 if (r < 0) {
148 hashmap_remove(s->manager->dns_transactions, UINT_TO_PTR(t->id));
149 return r;
150 }
151
152 LIST_PREPEND(transactions_by_scope, s->transactions, t);
153 t->scope = s;
154
155 if (ret)
156 *ret = t;
157
158 t = NULL;
159
160 return 0;
161 }
162
163 static 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);
168
169 /* Note that we do not drop the UDP socket here, as we want to
170 * reuse it to repeat the interaction. */
171 }
172
173 static void dns_transaction_tentative(DnsTransaction *t, DnsPacket *p) {
174 _cleanup_free_ char *pretty = NULL;
175 DnsZoneItem *z;
176
177 assert(t);
178 assert(p);
179
180 if (manager_our_packet(t->scope->manager, p) != 0)
181 return;
182
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",
186 dns_protocol_to_string(t->scope->protocol),
187 t->scope->link ? t->scope->link->name : "*",
188 t->scope->family == AF_UNSPEC ? "*" : af_to_name(t->scope->family),
189 pretty);
190
191 /* RFC 4795, Section 4.1 says that the peer with the
192 * lexicographically smaller IP address loses */
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.");
195 return;
196 }
197
198 log_debug("We have the lexicographically larger IP address and thus lost in the conflict.");
199
200 t->block_gc++;
201 while ((z = set_first(t->notify_zone_items))) {
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 */
208 dns_zone_item_conflict(z);
209 }
210 t->block_gc--;
211
212 dns_transaction_gc(t);
213 }
214
215 void dns_transaction_complete(DnsTransaction *t, DnsTransactionState state) {
216 DnsQueryCandidate *c;
217 DnsZoneItem *z;
218 DnsTransaction *d;
219 Iterator i;
220
221 assert(t);
222 assert(!DNS_TRANSACTION_IS_LIVE(state));
223
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
228 log_debug("Transaction on scope %s on %s/%s now complete with <%s> from %s",
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),
232 dns_transaction_state_to_string(state),
233 t->answer_source < 0 ? "none" : dns_transaction_source_to_string(t->answer_source));
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++;
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);
248 t->block_gc--;
249
250 dns_transaction_gc(t);
251 }
252
253 static 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
272 if (dns_packet_validate_reply(p) <= 0) {
273 log_debug("Invalid TCP reply packet.");
274 dns_transaction_complete(t, DNS_TRANSACTION_INVALID_REPLY);
275 return 0;
276 }
277
278 dns_scope_check_conflicts(t->scope, p);
279
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
291 static int dns_transaction_open_tcp(DnsTransaction *t) {
292 DnsServer *server = NULL;
293 _cleanup_close_ int fd = -1;
294 int r;
295
296 assert(t);
297
298 if (t->stream)
299 return 0;
300
301 switch (t->scope->protocol) {
302 case DNS_PROTOCOL_DNS:
303 fd = dns_scope_tcp_socket(t->scope, AF_UNSPEC, NULL, 53, &server);
304 break;
305
306 case DNS_PROTOCOL_LLMNR:
307 /* When we already received a reply to this (but it was truncated), send to its sender address */
308 if (t->received)
309 fd = dns_scope_tcp_socket(t->scope, t->received->family, &t->received->sender, t->received->sender_port, NULL);
310 else {
311 union in_addr_union address;
312 int family = AF_UNSPEC;
313
314 /* Otherwise, try to talk to the owner of a
315 * the IP address, in case this is a reverse
316 * PTR lookup */
317
318 r = dns_name_address(DNS_RESOURCE_KEY_NAME(t->key), &family, &address);
319 if (r < 0)
320 return r;
321 if (r == 0)
322 return -EINVAL;
323 if (family != t->scope->family)
324 return -ESRCH;
325
326 fd = dns_scope_tcp_socket(t->scope, family, &address, LLMNR_PORT, NULL);
327 }
328
329 break;
330
331 default:
332 return -EAFNOSUPPORT;
333 }
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
350 dns_server_unref(t->server);
351 t->server = dns_server_ref(server);
352 t->received = dns_packet_unref(t->received);
353 t->answer = dns_answer_unref(t->answer);
354 t->answer_rcode = 0;
355 t->stream->complete = on_stream_complete;
356 t->stream->transaction = t;
357
358 /* The interface index is difficult to determine if we are
359 * connecting to the local host, hence fill this in right away
360 * instead of determining it from the socket */
361 if (t->scope->link)
362 t->stream->ifindex = t->scope->link->ifindex;
363
364 return 0;
365 }
366
367 static void dns_transaction_next_dns_server(DnsTransaction *t) {
368 assert(t);
369
370 t->server = dns_server_unref(t->server);
371 t->dns_udp_event_source = sd_event_source_unref(t->dns_udp_event_source);
372 t->dns_udp_fd = safe_close(t->dns_udp_fd);
373
374 dns_scope_next_dns_server(t->scope);
375 }
376
377 static void dns_transaction_cache_answer(DnsTransaction *t) {
378 unsigned n_cache;
379
380 assert(t);
381
382 /* For mDNS we cache whenever we get the packet, rather than
383 * in each transaction. */
384 if (!IN_SET(t->scope->protocol, DNS_PROTOCOL_DNS, DNS_PROTOCOL_LLMNR))
385 return;
386
387 /* We never cache if this packet is from the local host, under
388 * the assumption that a locally running DNS server would
389 * cache this anyway, and probably knows better when to flush
390 * the cache then we could. */
391 if (!DNS_PACKET_SHALL_CACHE(t->received))
392 return;
393
394 /* According to RFC 4795, section 2.9. only the RRs from the
395 * answer section shall be cached. However, if we know the
396 * message is authenticated, we might as well cache
397 * everything. */
398 if (t->answer_authenticated)
399 n_cache = dns_answer_size(t->answer);
400 else
401 n_cache = DNS_PACKET_ANCOUNT(t->received);
402
403 dns_cache_put(&t->scope->cache,
404 t->key,
405 t->answer_rcode,
406 t->answer,
407 n_cache,
408 t->answer_authenticated,
409 0,
410 t->received->family,
411 &t->received->sender);
412 }
413
414 static void dns_transaction_process_dnssec(DnsTransaction *t) {
415 int r;
416
417 assert(t);
418
419 /* Are there ongoing DNSSEC transactions? If so, let's wait for them. */
420 if (!set_isempty(t->dnssec_transactions))
421 return;
422
423 /* All our auxiliary DNSSEC transactions are complete now. Try
424 * to validate our RRset now. */
425 r = dns_transaction_validate_dnssec(t);
426 if (r < 0) {
427 dns_transaction_complete(t, DNS_TRANSACTION_RESOURCES);
428 return;
429 }
430
431 if (!IN_SET(t->dnssec_result, _DNSSEC_RESULT_INVALID, DNSSEC_VALIDATED, DNSSEC_NO_SIGNATURE /* FOR NOW! */)) {
432 dns_transaction_complete(t, DNS_TRANSACTION_DNSSEC_FAILED);
433 return;
434 }
435
436 dns_transaction_cache_answer(t);
437
438 if (t->answer_rcode == DNS_RCODE_SUCCESS)
439 dns_transaction_complete(t, DNS_TRANSACTION_SUCCESS);
440 else
441 dns_transaction_complete(t, DNS_TRANSACTION_FAILURE);
442 }
443
444 void dns_transaction_process_reply(DnsTransaction *t, DnsPacket *p) {
445 usec_t ts;
446 int r;
447
448 assert(t);
449 assert(p);
450 assert(t->state == DNS_TRANSACTION_PENDING);
451 assert(t->scope);
452 assert(t->scope->manager);
453
454 /* Note that this call might invalidate the query. Callers
455 * should hence not attempt to access the query or transaction
456 * after calling this function. */
457
458 log_debug("Processing incoming packet on transaction %" PRIu16".", t->id);
459
460 switch (t->scope->protocol) {
461
462 case DNS_PROTOCOL_LLMNR:
463 assert(t->scope->link);
464
465 /* For LLMNR we will not accept any packets from other
466 * interfaces */
467
468 if (p->ifindex != t->scope->link->ifindex)
469 return;
470
471 if (p->family != t->scope->family)
472 return;
473
474 /* Tentative packets are not full responses but still
475 * useful for identifying uniqueness conflicts during
476 * probing. */
477 if (DNS_PACKET_LLMNR_T(p)) {
478 dns_transaction_tentative(t, p);
479 return;
480 }
481
482 break;
483
484 case DNS_PROTOCOL_MDNS:
485 assert(t->scope->link);
486
487 /* For mDNS we will not accept any packets from other interfaces */
488 if (p->ifindex != t->scope->link->ifindex)
489 return;
490
491 if (p->family != t->scope->family)
492 return;
493
494 break;
495
496 case DNS_PROTOCOL_DNS:
497 break;
498
499 default:
500 assert_not_reached("Invalid DNS protocol.");
501 }
502
503 if (t->received != p) {
504 dns_packet_unref(t->received);
505 t->received = dns_packet_ref(p);
506 }
507
508 t->answer_source = DNS_TRANSACTION_NETWORK;
509
510 if (p->ipproto == IPPROTO_TCP) {
511 if (DNS_PACKET_TC(p)) {
512 /* Truncated via TCP? Somebody must be fucking with us */
513 dns_transaction_complete(t, DNS_TRANSACTION_INVALID_REPLY);
514 return;
515 }
516
517 if (DNS_PACKET_ID(p) != t->id) {
518 /* Not the reply to our query? Somebody must be fucking with us */
519 dns_transaction_complete(t, DNS_TRANSACTION_INVALID_REPLY);
520 return;
521 }
522 }
523
524 assert_se(sd_event_now(t->scope->manager->event, clock_boottime_or_monotonic(), &ts) >= 0);
525
526 switch (t->scope->protocol) {
527
528 case DNS_PROTOCOL_DNS:
529 assert(t->server);
530
531 if (IN_SET(DNS_PACKET_RCODE(p), DNS_RCODE_FORMERR, DNS_RCODE_SERVFAIL, DNS_RCODE_NOTIMP)) {
532
533 /* Request failed, immediately try again with reduced features */
534 log_debug("Server returned error: %s", dns_rcode_to_string(DNS_PACKET_RCODE(p)));
535
536 dns_server_packet_failed(t->server, t->current_features);
537
538 r = dns_transaction_go(t);
539 if (r < 0) {
540 dns_transaction_complete(t, DNS_TRANSACTION_RESOURCES);
541 return;
542 }
543
544 return;
545 } else
546 dns_server_packet_received(t->server, t->current_features, ts - t->start_usec, p->size);
547
548 break;
549
550 case DNS_PROTOCOL_LLMNR:
551 case DNS_PROTOCOL_MDNS:
552 dns_scope_packet_received(t->scope, ts - t->start_usec);
553 break;
554
555 default:
556 assert_not_reached("Invalid DNS protocol.");
557 }
558
559 if (DNS_PACKET_TC(p)) {
560
561 /* Truncated packets for mDNS are not allowed. Give up immediately. */
562 if (t->scope->protocol == DNS_PROTOCOL_MDNS) {
563 dns_transaction_complete(t, DNS_TRANSACTION_INVALID_REPLY);
564 return;
565 }
566
567 /* Response was truncated, let's try again with good old TCP */
568 r = dns_transaction_open_tcp(t);
569 if (r == -ESRCH) {
570 /* No servers found? Damn! */
571 dns_transaction_complete(t, DNS_TRANSACTION_NO_SERVERS);
572 return;
573 }
574 if (r < 0) {
575 /* On LLMNR, if we cannot connect to the host,
576 * we immediately give up */
577 if (t->scope->protocol == DNS_PROTOCOL_LLMNR) {
578 dns_transaction_complete(t, DNS_TRANSACTION_RESOURCES);
579 return;
580 }
581
582 /* On DNS, couldn't send? Try immediately again, with a new server */
583 dns_transaction_next_dns_server(t);
584
585 r = dns_transaction_go(t);
586 if (r < 0) {
587 dns_transaction_complete(t, DNS_TRANSACTION_RESOURCES);
588 return;
589 }
590
591 return;
592 }
593 }
594
595 /* Parse message, if it isn't parsed yet. */
596 r = dns_packet_extract(p);
597 if (r < 0) {
598 dns_transaction_complete(t, DNS_TRANSACTION_INVALID_REPLY);
599 return;
600 }
601
602 if (IN_SET(t->scope->protocol, DNS_PROTOCOL_DNS, DNS_PROTOCOL_LLMNR)) {
603
604 /* Only consider responses with equivalent query section to the request */
605 r = dns_packet_is_reply_for(p, t->key);
606 if (r < 0) {
607 dns_transaction_complete(t, DNS_TRANSACTION_RESOURCES);
608 return;
609 }
610 if (r == 0) {
611 dns_transaction_complete(t, DNS_TRANSACTION_INVALID_REPLY);
612 return;
613 }
614
615 /* Install the answer as answer to the transaction */
616 dns_answer_unref(t->answer);
617 t->answer = dns_answer_ref(p->answer);
618 t->answer_rcode = DNS_PACKET_RCODE(p);
619 t->answer_authenticated = t->scope->dnssec_mode == DNSSEC_TRUST && DNS_PACKET_AD(p);
620
621 r = dns_transaction_request_dnssec_keys(t);
622 if (r < 0) {
623 dns_transaction_complete(t, DNS_TRANSACTION_RESOURCES);
624 return;
625 }
626 if (r > 0) {
627 /* There are DNSSEC transactions pending now. Update the state accordingly. */
628 t->state = DNS_TRANSACTION_VALIDATING;
629 return;
630 }
631 }
632
633 dns_transaction_process_dnssec(t);
634 }
635
636 static int on_dns_packet(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
637 _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
638 DnsTransaction *t = userdata;
639 int r;
640
641 assert(t);
642 assert(t->scope);
643
644 r = manager_recv(t->scope->manager, fd, DNS_PROTOCOL_DNS, &p);
645 if (r <= 0)
646 return r;
647
648 if (dns_packet_validate_reply(p) > 0 &&
649 DNS_PACKET_ID(p) == t->id)
650 dns_transaction_process_reply(t, p);
651 else
652 log_debug("Invalid DNS packet, ignoring.");
653
654 return 0;
655 }
656
657 static int dns_transaction_emit(DnsTransaction *t) {
658 int r;
659
660 assert(t);
661
662 if (t->scope->protocol == DNS_PROTOCOL_DNS && !t->server) {
663 DnsServer *server = NULL;
664 _cleanup_close_ int fd = -1;
665
666 fd = dns_scope_udp_dns_socket(t->scope, &server);
667 if (fd < 0)
668 return fd;
669
670 r = sd_event_add_io(t->scope->manager->event, &t->dns_udp_event_source, fd, EPOLLIN, on_dns_packet, t);
671 if (r < 0)
672 return r;
673
674 t->dns_udp_fd = fd;
675 fd = -1;
676 t->server = dns_server_ref(server);
677 }
678
679 r = dns_scope_emit(t->scope, t->dns_udp_fd, t->server, t->sent);
680 if (r < 0)
681 return r;
682
683 if (t->server)
684 t->current_features = t->server->possible_features;
685
686 return 0;
687 }
688
689 static int on_transaction_timeout(sd_event_source *s, usec_t usec, void *userdata) {
690 DnsTransaction *t = userdata;
691 int r;
692
693 assert(s);
694 assert(t);
695
696 if (!t->initial_jitter_scheduled || t->initial_jitter_elapsed) {
697 /* Timeout reached? Increase the timeout for the server used */
698 switch (t->scope->protocol) {
699 case DNS_PROTOCOL_DNS:
700 assert(t->server);
701
702 dns_server_packet_lost(t->server, t->current_features, usec - t->start_usec);
703
704 break;
705 case DNS_PROTOCOL_LLMNR:
706 case DNS_PROTOCOL_MDNS:
707 dns_scope_packet_lost(t->scope, usec - t->start_usec);
708
709 break;
710 default:
711 assert_not_reached("Invalid DNS protocol.");
712 }
713
714 if (t->initial_jitter_scheduled)
715 t->initial_jitter_elapsed = true;
716 }
717
718 /* ...and try again with a new server */
719 dns_transaction_next_dns_server(t);
720
721 r = dns_transaction_go(t);
722 if (r < 0)
723 dns_transaction_complete(t, DNS_TRANSACTION_RESOURCES);
724
725 return 0;
726 }
727
728 static usec_t transaction_get_resend_timeout(DnsTransaction *t) {
729 assert(t);
730 assert(t->scope);
731
732 switch (t->scope->protocol) {
733 case DNS_PROTOCOL_DNS:
734 assert(t->server);
735
736 return t->server->resend_timeout;
737 case DNS_PROTOCOL_MDNS:
738 assert(t->n_attempts > 0);
739 return (1 << (t->n_attempts - 1)) * USEC_PER_SEC;
740 case DNS_PROTOCOL_LLMNR:
741 return t->scope->resend_timeout;
742 default:
743 assert_not_reached("Invalid DNS protocol.");
744 }
745 }
746
747 static int dns_transaction_prepare(DnsTransaction *t, usec_t ts) {
748 bool had_stream;
749 int r;
750
751 assert(t);
752
753 had_stream = !!t->stream;
754
755 dns_transaction_stop(t);
756
757 if (t->n_attempts >= TRANSACTION_ATTEMPTS_MAX(t->scope->protocol)) {
758 dns_transaction_complete(t, DNS_TRANSACTION_ATTEMPTS_MAX_REACHED);
759 return 0;
760 }
761
762 if (t->scope->protocol == DNS_PROTOCOL_LLMNR && had_stream) {
763 /* If we already tried via a stream, then we don't
764 * retry on LLMNR. See RFC 4795, Section 2.7. */
765 dns_transaction_complete(t, DNS_TRANSACTION_ATTEMPTS_MAX_REACHED);
766 return 0;
767 }
768
769 t->n_attempts++;
770 t->start_usec = ts;
771 t->received = dns_packet_unref(t->received);
772 t->answer = dns_answer_unref(t->answer);
773 t->answer_rcode = 0;
774 t->answer_source = _DNS_TRANSACTION_SOURCE_INVALID;
775
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;
784 t->answer_authenticated = true;
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
791 * for probing or verifying a zone item. */
792 if (set_isempty(t->notify_zone_items)) {
793
794 r = dns_zone_lookup(&t->scope->zone, t->key, &t->answer, NULL, NULL);
795 if (r < 0)
796 return r;
797 if (r > 0) {
798 t->answer_rcode = DNS_RCODE_SUCCESS;
799 t->answer_source = DNS_TRANSACTION_ZONE;
800 t->answer_authenticated = true;
801 dns_transaction_complete(t, DNS_TRANSACTION_SUCCESS);
802 return 0;
803 }
804 }
805
806 /* Check the cache, but only if this transaction is not used
807 * for probing or verifying a zone item. */
808 if (set_isempty(t->notify_zone_items)) {
809
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);
814
815 /* Let's then prune all outdated entries */
816 dns_cache_prune(&t->scope->cache);
817
818 r = dns_cache_lookup(&t->scope->cache, t->key, &t->answer_rcode, &t->answer, &t->answer_authenticated);
819 if (r < 0)
820 return r;
821 if (r > 0) {
822 t->answer_source = DNS_TRANSACTION_CACHE;
823 if (t->answer_rcode == DNS_RCODE_SUCCESS)
824 dns_transaction_complete(t, DNS_TRANSACTION_SUCCESS);
825 else
826 dns_transaction_complete(t, DNS_TRANSACTION_FAILURE);
827 return 0;
828 }
829 }
830
831 return 1;
832 }
833
834 static int dns_transaction_make_packet_mdns(DnsTransaction *t) {
835
836 _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
837 bool add_known_answers = false;
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
859 if (dns_key_is_shared(t->key))
860 add_known_answers = true;
861
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
897 r = dns_transaction_prepare(other, ts);
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 ++;
916
917 if (dns_key_is_shared(other->key))
918 add_known_answers = true;
919 }
920
921 DNS_PACKET_HEADER(p)->qdcount = htobe16(qdcount);
922
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
930 t->sent = p;
931 p = NULL;
932
933 return 0;
934 }
935
936 static 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
971 int 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);
978
979 r = dns_transaction_prepare(t, ts);
980 if (r <= 0)
981 return r;
982
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 }
994
995 if (!t->initial_jitter_scheduled &&
996 (t->scope->protocol == DNS_PROTOCOL_LLMNR ||
997 t->scope->protocol == DNS_PROTOCOL_MDNS)) {
998 usec_t jitter, accuracy;
999
1000 /* RFC 4795 Section 2.7 suggests all queries should be
1001 * delayed by a random time from 0 to JITTER_INTERVAL. */
1002
1003 t->initial_jitter_scheduled = true;
1004
1005 random_bytes(&jitter, sizeof(jitter));
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 }
1020
1021 r = sd_event_add_time(
1022 t->scope->manager->event,
1023 &t->timeout_event_source,
1024 clock_boottime_or_monotonic(),
1025 ts + jitter, accuracy,
1026 on_transaction_timeout, t);
1027 if (r < 0)
1028 return r;
1029
1030 t->n_attempts = 0;
1031 t->next_attempt_after = ts;
1032 t->state = DNS_TRANSACTION_PENDING;
1033
1034 log_debug("Delaying %s transaction for " USEC_FMT "us.", dns_protocol_to_string(t->scope->protocol), jitter);
1035 return 0;
1036 }
1037
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 &&
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)) {
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 {
1058 /* Try via UDP, and if that fails due to large size or lack of
1059 * support try via TCP */
1060 r = dns_transaction_emit(t);
1061 if (r == -EMSGSIZE || r == -EAGAIN)
1062 r = dns_transaction_open_tcp(t);
1063 }
1064
1065 if (r == -ESRCH) {
1066 /* No servers to send this to? */
1067 dns_transaction_complete(t, DNS_TRANSACTION_NO_SERVERS);
1068 return 0;
1069 } else if (r < 0) {
1070 if (t->scope->protocol != DNS_PROTOCOL_DNS) {
1071 dns_transaction_complete(t, DNS_TRANSACTION_RESOURCES);
1072 return 0;
1073 }
1074
1075 /* Couldn't send? Try immediately again, with a new server */
1076 dns_transaction_next_dns_server(t);
1077
1078 return dns_transaction_go(t);
1079 }
1080
1081 ts += transaction_get_resend_timeout(t);
1082
1083 r = sd_event_add_time(
1084 t->scope->manager->event,
1085 &t->timeout_event_source,
1086 clock_boottime_or_monotonic(),
1087 ts, 0,
1088 on_transaction_timeout, t);
1089 if (r < 0)
1090 return r;
1091
1092 t->state = DNS_TRANSACTION_PENDING;
1093 t->next_attempt_after = ts;
1094
1095 return 1;
1096 }
1097
1098 static 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
1139 gc:
1140 dns_transaction_gc(aux);
1141 return r;
1142 }
1143
1144 static 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
1178 int 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
1249 void 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
1283 int dns_transaction_validate_dnssec(DnsTransaction *t) {
1284 _cleanup_(dns_answer_unrefp) DnsAnswer *validated = NULL;
1285 DnsResourceRecord *rr;
1286 int ifindex, r;
1287
1288 assert(t);
1289
1290 /* We have now collected all DS and DNSKEY RRs in
1291 * t->validated_keys, let's see which RRs we can now
1292 * authenticate with that. */
1293
1294 if (t->scope->dnssec_mode != DNSSEC_YES)
1295 return 0;
1296
1297 /* Already validated */
1298 if (t->dnssec_result != _DNSSEC_RESULT_INVALID)
1299 return 0;
1300
1301 if (IN_SET(t->answer_source, DNS_TRANSACTION_ZONE, DNS_TRANSACTION_TRUST_ANCHOR)) {
1302 t->dnssec_result = DNSSEC_VALIDATED;
1303 t->answer_authenticated = true;
1304 return 0;
1305 }
1306
1307 if (log_get_max_level() >= LOG_DEBUG) {
1308 _cleanup_free_ char *ks = NULL;
1309
1310 (void) dns_resource_key_to_string(t->key, &ks);
1311 log_debug("Validating response from transaction %" PRIu16 " (%s).", t->id, ks ? strstrip(ks) : "???");
1312 }
1313
1314 /* First see if there are DNSKEYs we already known a validated DS for. */
1315 DNS_ANSWER_FOREACH_IFINDEX(rr, ifindex, t->answer) {
1316
1317 r = dnssec_verify_dnskey_search(rr, t->validated_keys);
1318 if (r < 0)
1319 return r;
1320 if (r == 0)
1321 continue;
1322
1323 /* If so, the DNSKEY is validated too. */
1324 r = dns_answer_add_extend(&t->validated_keys, rr, ifindex);
1325 if (r < 0)
1326 return r;
1327 }
1328
1329 for (;;) {
1330 bool changed = false, missing_key_for_transaction = false;
1331
1332 DNS_ANSWER_FOREACH(rr, t->answer) {
1333 DnssecResult result;
1334
1335 if (rr->key->type == DNS_TYPE_RRSIG)
1336 continue;
1337
1338 r = dnssec_verify_rrset_search(t->answer, rr->key, t->validated_keys, USEC_INFINITY, &result);
1339 if (r < 0)
1340 return r;
1341
1342 if (log_get_max_level() >= LOG_DEBUG) {
1343 _cleanup_free_ char *rrs = NULL;
1344
1345 (void) dns_resource_record_to_string(rr, &rrs);
1346 log_debug("Looking at %s: %s", rrs ? strstrip(rrs) : "???", dnssec_result_to_string(result));
1347 }
1348
1349 switch (result) {
1350
1351 case DNSSEC_VALIDATED:
1352
1353 /* Add the validated RRset to the new list of validated RRsets */
1354 r = dns_answer_copy_by_key(&validated, t->answer, rr->key);
1355 if (r < 0)
1356 return r;
1357
1358 if (rr->key->type == DNS_TYPE_DNSKEY) {
1359 /* If we just validated a
1360 * DNSKEY RRset, then let's
1361 * add these keys to the set
1362 * of validated keys for this
1363 * transaction. */
1364
1365 r = dns_answer_copy_by_key(&t->validated_keys, t->answer, rr->key);
1366 if (r < 0)
1367 return r;
1368 }
1369
1370 /* Now, remove this RRset from the RRs still to process */
1371 r = dns_answer_remove_by_key(&t->answer, rr->key);
1372 if (r < 0)
1373 return r;
1374
1375 changed = true;
1376 break;
1377
1378 case DNSSEC_INVALID:
1379 case DNSSEC_NO_SIGNATURE:
1380 case DNSSEC_SIGNATURE_EXPIRED:
1381
1382 /* Is this the RRset that we were looking for? If so, this is fatal for the whole transaction */
1383 r = dns_resource_key_match_rr(t->key, rr, NULL);
1384 if (r < 0)
1385 return r;
1386 if (r > 0) {
1387 t->dnssec_result = result;
1388 return 0;
1389 }
1390
1391 /* Is this a CNAME for a record we were looking for? If so, it's also fatal for the whole transaction */
1392 r = dns_resource_key_match_cname_or_dname(t->key, rr->key, NULL);
1393 if (r < 0)
1394 return r;
1395 if (r > 0) {
1396 t->dnssec_result = result;
1397 return 0;
1398 }
1399
1400 /* This is just something auxiliary. Just remove the RRset and continue. */
1401 r = dns_answer_remove_by_key(&t->answer, rr->key);
1402 if (r < 0)
1403 return r;
1404
1405 changed = true;
1406 break;
1407
1408 case DNSSEC_MISSING_KEY:
1409 /* They key is missing? Let's continue
1410 * with the next iteration, maybe
1411 * we'll find it in an DNSKEY RRset
1412 * later on. */
1413
1414 r = dns_resource_key_equal(rr->key, t->key);
1415 if (r < 0)
1416 return r;
1417 if (r > 0)
1418 missing_key_for_transaction = true;
1419
1420 break;
1421
1422 default:
1423 assert_not_reached("Unexpected DNSSEC result");
1424 }
1425
1426 if (changed)
1427 break;
1428 }
1429
1430 if (changed)
1431 continue;
1432
1433 /* This didn't work either, there's no point in
1434 * continuing. */
1435 if (missing_key_for_transaction) {
1436 t->dnssec_result = DNSSEC_MISSING_KEY;
1437 return 0;
1438 }
1439
1440 break;
1441 }
1442
1443 dns_answer_unref(t->answer);
1444 t->answer = validated;
1445 validated = NULL;
1446
1447 t->answer_authenticated = true;
1448 t->dnssec_result = DNSSEC_VALIDATED;
1449 return 1;
1450 }
1451
1452 static const char* const dns_transaction_state_table[_DNS_TRANSACTION_STATE_MAX] = {
1453 [DNS_TRANSACTION_NULL] = "null",
1454 [DNS_TRANSACTION_PENDING] = "pending",
1455 [DNS_TRANSACTION_VALIDATING] = "validating",
1456 [DNS_TRANSACTION_FAILURE] = "failure",
1457 [DNS_TRANSACTION_SUCCESS] = "success",
1458 [DNS_TRANSACTION_NO_SERVERS] = "no-servers",
1459 [DNS_TRANSACTION_TIMEOUT] = "timeout",
1460 [DNS_TRANSACTION_ATTEMPTS_MAX_REACHED] = "attempts-max-reached",
1461 [DNS_TRANSACTION_INVALID_REPLY] = "invalid-reply",
1462 [DNS_TRANSACTION_RESOURCES] = "resources",
1463 [DNS_TRANSACTION_ABORTED] = "aborted",
1464 [DNS_TRANSACTION_DNSSEC_FAILED] = "dnssec-failed",
1465 };
1466 DEFINE_STRING_TABLE_LOOKUP(dns_transaction_state, DnsTransactionState);
1467
1468 static const char* const dns_transaction_source_table[_DNS_TRANSACTION_SOURCE_MAX] = {
1469 [DNS_TRANSACTION_NETWORK] = "network",
1470 [DNS_TRANSACTION_CACHE] = "cache",
1471 [DNS_TRANSACTION_ZONE] = "zone",
1472 [DNS_TRANSACTION_TRUST_ANCHOR] = "trust-anchor",
1473 };
1474 DEFINE_STRING_TABLE_LOOKUP(dns_transaction_source, DnsTransactionSource);