]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/resolve/resolved-dns-transaction.c
man: add basic documentation for resolved.conf's DNSSEC= switch
[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
beef6a5f
LP
22#include <sd-messages.h>
23
ec2c5e43 24#include "af-list.h"
b5efdb8a 25#include "alloc-util.h"
f52e61da 26#include "dns-domain.h"
3ffd4af2
LP
27#include "fd-util.h"
28#include "random-util.h"
7778dfff 29#include "resolved-dns-cache.h"
3ffd4af2
LP
30#include "resolved-dns-transaction.h"
31#include "resolved-llmnr.h"
8b43440b 32#include "string-table.h"
ec2c5e43 33
c61d2b44
LP
34static void dns_transaction_reset_answer(DnsTransaction *t) {
35 assert(t);
36
37 t->received = dns_packet_unref(t->received);
38 t->answer = dns_answer_unref(t->answer);
39 t->answer_rcode = 0;
40 t->answer_dnssec_result = _DNSSEC_RESULT_INVALID;
41 t->answer_source = _DNS_TRANSACTION_SOURCE_INVALID;
42 t->answer_authenticated = false;
43}
44
f32f0e57
LP
45static void dns_transaction_close_connection(DnsTransaction *t) {
46 assert(t);
47
48 t->stream = dns_stream_free(t->stream);
49 t->dns_udp_event_source = sd_event_source_unref(t->dns_udp_event_source);
50 t->dns_udp_fd = safe_close(t->dns_udp_fd);
51}
52
f535705a 53static void dns_transaction_stop_timeout(DnsTransaction *t) {
97cc656c
LP
54 assert(t);
55
56 t->timeout_event_source = sd_event_source_unref(t->timeout_event_source);
97cc656c
LP
57}
58
ec2c5e43 59DnsTransaction* dns_transaction_free(DnsTransaction *t) {
801ad6a6 60 DnsQueryCandidate *c;
ec2c5e43 61 DnsZoneItem *i;
547973de 62 DnsTransaction *z;
ec2c5e43
LP
63
64 if (!t)
65 return NULL;
66
51e399bc
LP
67 log_debug("Freeing transaction %" PRIu16 ".", t->id);
68
f32f0e57 69 dns_transaction_close_connection(t);
f535705a 70 dns_transaction_stop_timeout(t);
ec2c5e43 71
ec2c5e43 72 dns_packet_unref(t->sent);
c61d2b44 73 dns_transaction_reset_answer(t);
ec2c5e43 74
8300ba21 75 dns_server_unref(t->server);
ec2c5e43
LP
76
77 if (t->scope) {
f9ebb22a
LP
78 hashmap_remove_value(t->scope->transactions_by_key, t->key, t);
79 LIST_REMOVE(transactions_by_scope, t->scope->transactions, t);
ec2c5e43
LP
80
81 if (t->id != 0)
82 hashmap_remove(t->scope->manager->dns_transactions, UINT_TO_PTR(t->id));
83 }
84
547973de 85 while ((c = set_steal_first(t->notify_query_candidates)))
801ad6a6 86 set_remove(c->transactions, t);
547973de 87 set_free(t->notify_query_candidates);
801ad6a6 88
547973de 89 while ((i = set_steal_first(t->notify_zone_items)))
ec2c5e43 90 i->probe_transaction = NULL;
547973de
LP
91 set_free(t->notify_zone_items);
92
93 while ((z = set_steal_first(t->notify_transactions)))
94 set_remove(z->dnssec_transactions, t);
95 set_free(t->notify_transactions);
96
97 while ((z = set_steal_first(t->dnssec_transactions))) {
98 set_remove(z->notify_transactions, t);
99 dns_transaction_gc(z);
100 }
101 set_free(t->dnssec_transactions);
102
103 dns_answer_unref(t->validated_keys);
97cc656c 104 dns_resource_key_unref(t->key);
a5784c49 105 free(t->key_string);
97cc656c 106
ec2c5e43
LP
107 free(t);
108 return NULL;
109}
110
111DEFINE_TRIVIAL_CLEANUP_FUNC(DnsTransaction*, dns_transaction_free);
112
51e399bc 113bool dns_transaction_gc(DnsTransaction *t) {
ec2c5e43
LP
114 assert(t);
115
116 if (t->block_gc > 0)
51e399bc 117 return true;
ec2c5e43 118
547973de
LP
119 if (set_isempty(t->notify_query_candidates) &&
120 set_isempty(t->notify_zone_items) &&
51e399bc 121 set_isempty(t->notify_transactions)) {
ec2c5e43 122 dns_transaction_free(t);
51e399bc
LP
123 return false;
124 }
125
126 return true;
ec2c5e43
LP
127}
128
f52e61da 129int dns_transaction_new(DnsTransaction **ret, DnsScope *s, DnsResourceKey *key) {
ec2c5e43
LP
130 _cleanup_(dns_transaction_freep) DnsTransaction *t = NULL;
131 int r;
132
133 assert(ret);
134 assert(s);
f52e61da 135 assert(key);
ec2c5e43 136
9eae2bf3 137 /* Don't allow looking up invalid or pseudo RRs */
c463eb78 138 if (!dns_type_is_valid_query(key->type))
9eae2bf3
LP
139 return -EINVAL;
140
141 /* We only support the IN class */
c463eb78 142 if (key->class != DNS_CLASS_IN && key->class != DNS_CLASS_ANY)
9eae2bf3
LP
143 return -EOPNOTSUPP;
144
d5099efc 145 r = hashmap_ensure_allocated(&s->manager->dns_transactions, NULL);
ec2c5e43
LP
146 if (r < 0)
147 return r;
148
f9ebb22a 149 r = hashmap_ensure_allocated(&s->transactions_by_key, &dns_resource_key_hash_ops);
da0c630e
LP
150 if (r < 0)
151 return r;
152
ec2c5e43
LP
153 t = new0(DnsTransaction, 1);
154 if (!t)
155 return -ENOMEM;
156
4667e00a 157 t->dns_udp_fd = -1;
c3bc53e6 158 t->answer_source = _DNS_TRANSACTION_SOURCE_INVALID;
019036a4 159 t->answer_dnssec_result = _DNSSEC_RESULT_INVALID;
f52e61da 160 t->key = dns_resource_key_ref(key);
ec2c5e43 161
da0c630e 162 /* Find a fresh, unused transaction id */
ec2c5e43
LP
163 do
164 random_bytes(&t->id, sizeof(t->id));
165 while (t->id == 0 ||
166 hashmap_get(s->manager->dns_transactions, UINT_TO_PTR(t->id)));
167
168 r = hashmap_put(s->manager->dns_transactions, UINT_TO_PTR(t->id), t);
169 if (r < 0) {
170 t->id = 0;
171 return r;
172 }
173
f9ebb22a 174 r = hashmap_replace(s->transactions_by_key, t->key, t);
da0c630e
LP
175 if (r < 0) {
176 hashmap_remove(s->manager->dns_transactions, UINT_TO_PTR(t->id));
177 return r;
178 }
179
f9ebb22a 180 LIST_PREPEND(transactions_by_scope, s->transactions, t);
ec2c5e43
LP
181 t->scope = s;
182
a150ff5e
LP
183 s->manager->n_transactions_total ++;
184
ec2c5e43
LP
185 if (ret)
186 *ret = t;
187
188 t = NULL;
189
190 return 0;
191}
192
ec2c5e43 193static void dns_transaction_tentative(DnsTransaction *t, DnsPacket *p) {
2fb3034c 194 _cleanup_free_ char *pretty = NULL;
ec2c5e43 195 DnsZoneItem *z;
ec2c5e43
LP
196
197 assert(t);
198 assert(p);
199
200 if (manager_our_packet(t->scope->manager, p) != 0)
201 return;
202
2fb3034c
LP
203 in_addr_to_string(p->family, &p->sender, &pretty);
204
a5784c49
LP
205 log_debug("Transaction %" PRIu16 " for <%s> on scope %s on %s/%s got tentative packet from %s.",
206 t->id,
207 dns_transaction_key_string(t),
ec2c5e43
LP
208 dns_protocol_to_string(t->scope->protocol),
209 t->scope->link ? t->scope->link->name : "*",
2fb3034c
LP
210 t->scope->family == AF_UNSPEC ? "*" : af_to_name(t->scope->family),
211 pretty);
ec2c5e43 212
a4076574
LP
213 /* RFC 4795, Section 4.1 says that the peer with the
214 * lexicographically smaller IP address loses */
4d91eec4
LP
215 if (memcmp(&p->sender, &p->destination, FAMILY_ADDRESS_SIZE(p->family)) >= 0) {
216 log_debug("Peer has lexicographically larger IP address and thus lost in the conflict.");
a4076574
LP
217 return;
218 }
219
4d91eec4 220 log_debug("We have the lexicographically larger IP address and thus lost in the conflict.");
a4076574 221
ec2c5e43 222 t->block_gc++;
547973de 223 while ((z = set_first(t->notify_zone_items))) {
3ef64445
LP
224 /* First, make sure the zone item drops the reference
225 * to us */
226 dns_zone_item_probe_stop(z);
227
228 /* Secondly, report this as conflict, so that we might
229 * look for a different hostname */
ec2c5e43 230 dns_zone_item_conflict(z);
3ef64445 231 }
ec2c5e43
LP
232 t->block_gc--;
233
234 dns_transaction_gc(t);
235}
236
237void dns_transaction_complete(DnsTransaction *t, DnsTransactionState state) {
801ad6a6 238 DnsQueryCandidate *c;
ec2c5e43 239 DnsZoneItem *z;
547973de 240 DnsTransaction *d;
ec2c5e43
LP
241 Iterator i;
242
243 assert(t);
547973de 244 assert(!DNS_TRANSACTION_IS_LIVE(state));
e56187ca 245
f61dfddb
LP
246 if (state == DNS_TRANSACTION_DNSSEC_FAILED)
247 log_struct(LOG_NOTICE,
beef6a5f 248 LOG_MESSAGE_ID(SD_MESSAGE_DNSSEC_FAILURE),
f61dfddb
LP
249 LOG_MESSAGE("DNSSEC validation failed for question %s: %s", dns_transaction_key_string(t), dnssec_result_to_string(t->answer_dnssec_result)),
250 "DNS_TRANSACTION=%" PRIu16, t->id,
251 "DNS_QUESTION=%s", dns_transaction_key_string(t),
252 "DNSSEC_RESULT=%s", dnssec_result_to_string(t->answer_dnssec_result),
253 NULL);
254
ec2c5e43
LP
255 /* Note that this call might invalidate the query. Callers
256 * should hence not attempt to access the query or transaction
257 * after calling this function. */
258
a5784c49
LP
259 log_debug("Transaction %" PRIu16 " for <%s> on scope %s on %s/%s now complete with <%s> from %s (%s).",
260 t->id,
261 dns_transaction_key_string(t),
ec2c5e43
LP
262 dns_protocol_to_string(t->scope->protocol),
263 t->scope->link ? t->scope->link->name : "*",
264 t->scope->family == AF_UNSPEC ? "*" : af_to_name(t->scope->family),
c3bc53e6 265 dns_transaction_state_to_string(state),
a5784c49
LP
266 t->answer_source < 0 ? "none" : dns_transaction_source_to_string(t->answer_source),
267 t->answer_authenticated ? "authenticated" : "unsigned");
ec2c5e43
LP
268
269 t->state = state;
270
f32f0e57 271 dns_transaction_close_connection(t);
f535705a 272 dns_transaction_stop_timeout(t);
ec2c5e43
LP
273
274 /* Notify all queries that are interested, but make sure the
275 * transaction isn't freed while we are still looking at it */
276 t->block_gc++;
f7014757 277
547973de
LP
278 SET_FOREACH(c, t->notify_query_candidates, i)
279 dns_query_candidate_notify(c);
280 SET_FOREACH(z, t->notify_zone_items, i)
281 dns_zone_item_notify(z);
ec2c5e43 282
f7014757
LP
283 if (!set_isempty(t->notify_transactions)) {
284 DnsTransaction **nt;
285 unsigned j, n = 0;
286
287 /* We need to be careful when notifying other
288 * transactions, as that might destroy other
289 * transactions in our list. Hence, in order to be
290 * able to safely iterate through the list of
291 * transactions, take a GC lock on all of them
292 * first. Then, in a second loop, notify them, but
293 * first unlock that specific transaction. */
294
295 nt = newa(DnsTransaction*, set_size(t->notify_transactions));
296 SET_FOREACH(d, t->notify_transactions, i) {
297 nt[n++] = d;
298 d->block_gc++;
299 }
300
301 assert(n == set_size(t->notify_transactions));
302
303 for (j = 0; j < n; j++) {
304 if (set_contains(t->notify_transactions, nt[j]))
305 dns_transaction_notify(nt[j], t);
306
307 nt[j]->block_gc--;
308 dns_transaction_gc(nt[j]);
309 }
310 }
311
312 t->block_gc--;
ec2c5e43
LP
313 dns_transaction_gc(t);
314}
315
519ef046
LP
316static int dns_transaction_pick_server(DnsTransaction *t) {
317 DnsServer *server;
318
319 assert(t);
320 assert(t->scope->protocol == DNS_PROTOCOL_DNS);
321
322 server = dns_scope_get_dns_server(t->scope);
323 if (!server)
324 return -ESRCH;
325
f4461e56 326 t->current_features = dns_server_possible_feature_level(server);
519ef046
LP
327
328 if (server == t->server)
329 return 0;
330
331 dns_server_unref(t->server);
332 t->server = dns_server_ref(server);
333
334 return 1;
335}
336
ec2c5e43
LP
337static int on_stream_complete(DnsStream *s, int error) {
338 _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
339 DnsTransaction *t;
340
341 assert(s);
342 assert(s->transaction);
343
344 /* Copy the data we care about out of the stream before we
345 * destroy it. */
346 t = s->transaction;
347 p = dns_packet_ref(s->read_packet);
348
349 t->stream = dns_stream_free(t->stream);
350
ac720200
LP
351 if (IN_SET(error, ENOTCONN, ECONNRESET, ECONNREFUSED, ECONNABORTED, EPIPE)) {
352 dns_transaction_complete(t, DNS_TRANSACTION_CONNECTION_FAILURE);
353 return 0;
354 }
355
ec2c5e43
LP
356 if (error != 0) {
357 dns_transaction_complete(t, DNS_TRANSACTION_RESOURCES);
358 return 0;
359 }
360
a4076574 361 if (dns_packet_validate_reply(p) <= 0) {
a20b9592 362 log_debug("Invalid TCP reply packet.");
a4076574
LP
363 dns_transaction_complete(t, DNS_TRANSACTION_INVALID_REPLY);
364 return 0;
365 }
366
367 dns_scope_check_conflicts(t->scope, p);
368
ec2c5e43
LP
369 t->block_gc++;
370 dns_transaction_process_reply(t, p);
371 t->block_gc--;
372
519ef046
LP
373 /* If the response wasn't useful, then complete the transition
374 * now. After all, we are the worst feature set now with TCP
375 * sockets, and there's really no point in retrying. */
ec2c5e43
LP
376 if (t->state == DNS_TRANSACTION_PENDING)
377 dns_transaction_complete(t, DNS_TRANSACTION_INVALID_REPLY);
598f44bd
LP
378 else
379 dns_transaction_gc(t);
ec2c5e43
LP
380
381 return 0;
382}
383
384static int dns_transaction_open_tcp(DnsTransaction *t) {
385 _cleanup_close_ int fd = -1;
386 int r;
387
388 assert(t);
389
519ef046 390 dns_transaction_close_connection(t);
ec2c5e43 391
106784eb 392 switch (t->scope->protocol) {
519ef046 393
106784eb 394 case DNS_PROTOCOL_DNS:
519ef046
LP
395 r = dns_transaction_pick_server(t);
396 if (r < 0)
397 return r;
398
399 r = dns_server_adjust_opt(t->server, t->sent, t->current_features);
400 if (r < 0)
401 return r;
402
403 fd = dns_scope_socket_tcp(t->scope, AF_UNSPEC, NULL, t->server, 53);
106784eb 404 break;
ec2c5e43 405
106784eb 406 case DNS_PROTOCOL_LLMNR:
a8f6397f 407 /* When we already received a reply to this (but it was truncated), send to its sender address */
ec2c5e43 408 if (t->received)
519ef046 409 fd = dns_scope_socket_tcp(t->scope, t->received->family, &t->received->sender, NULL, t->received->sender_port);
ec2c5e43
LP
410 else {
411 union in_addr_union address;
a7f7d1bd 412 int family = AF_UNSPEC;
ec2c5e43
LP
413
414 /* Otherwise, try to talk to the owner of a
415 * the IP address, in case this is a reverse
416 * PTR lookup */
f52e61da
LP
417
418 r = dns_name_address(DNS_RESOURCE_KEY_NAME(t->key), &family, &address);
ec2c5e43
LP
419 if (r < 0)
420 return r;
421 if (r == 0)
422 return -EINVAL;
9e08a6e0 423 if (family != t->scope->family)
9318cdd3 424 return -ESRCH;
ec2c5e43 425
519ef046 426 fd = dns_scope_socket_tcp(t->scope, family, &address, NULL, LLMNR_PORT);
ec2c5e43 427 }
106784eb
DM
428
429 break;
430
431 default:
ec2c5e43 432 return -EAFNOSUPPORT;
106784eb 433 }
ec2c5e43
LP
434
435 if (fd < 0)
436 return fd;
437
438 r = dns_stream_new(t->scope->manager, &t->stream, t->scope->protocol, fd);
439 if (r < 0)
440 return r;
ec2c5e43
LP
441 fd = -1;
442
443 r = dns_stream_write_packet(t->stream, t->sent);
444 if (r < 0) {
445 t->stream = dns_stream_free(t->stream);
446 return r;
447 }
448
ec2c5e43
LP
449 t->stream->complete = on_stream_complete;
450 t->stream->transaction = t;
451
452 /* The interface index is difficult to determine if we are
453 * connecting to the local host, hence fill this in right away
454 * instead of determining it from the socket */
455 if (t->scope->link)
456 t->stream->ifindex = t->scope->link->ifindex;
457
519ef046
LP
458 dns_transaction_reset_answer(t);
459
cbe4216d
LP
460 t->tried_stream = true;
461
ec2c5e43
LP
462 return 0;
463}
464
547973de 465static void dns_transaction_cache_answer(DnsTransaction *t) {
547973de
LP
466 assert(t);
467
468 /* For mDNS we cache whenever we get the packet, rather than
469 * in each transaction. */
470 if (!IN_SET(t->scope->protocol, DNS_PROTOCOL_DNS, DNS_PROTOCOL_LLMNR))
471 return;
472
473 /* We never cache if this packet is from the local host, under
474 * the assumption that a locally running DNS server would
475 * cache this anyway, and probably knows better when to flush
476 * the cache then we could. */
477 if (!DNS_PACKET_SHALL_CACHE(t->received))
478 return;
479
547973de
LP
480 dns_cache_put(&t->scope->cache,
481 t->key,
482 t->answer_rcode,
483 t->answer,
547973de
LP
484 t->answer_authenticated,
485 0,
486 t->received->family,
487 &t->received->sender);
488}
489
105e1512
LP
490static bool dns_transaction_dnssec_is_live(DnsTransaction *t) {
491 DnsTransaction *dt;
492 Iterator i;
493
494 assert(t);
495
496 SET_FOREACH(dt, t->dnssec_transactions, i)
497 if (DNS_TRANSACTION_IS_LIVE(dt->state))
498 return true;
499
500 return false;
501}
502
547973de
LP
503static void dns_transaction_process_dnssec(DnsTransaction *t) {
504 int r;
505
506 assert(t);
507
508 /* Are there ongoing DNSSEC transactions? If so, let's wait for them. */
105e1512 509 if (dns_transaction_dnssec_is_live(t))
547973de
LP
510 return;
511
512 /* All our auxiliary DNSSEC transactions are complete now. Try
513 * to validate our RRset now. */
514 r = dns_transaction_validate_dnssec(t);
515 if (r < 0) {
516 dns_transaction_complete(t, DNS_TRANSACTION_RESOURCES);
517 return;
518 }
519
b652d4a2
LP
520 if (t->answer_dnssec_result == DNSSEC_INCOMPATIBLE_SERVER &&
521 t->scope->dnssec_mode == DNSSEC_YES) {
522 /* We are not in automatic downgrade mode, and the
523 * server is bad, refuse operation. */
524 dns_transaction_complete(t, DNS_TRANSACTION_DNSSEC_FAILED);
525 return;
526 }
527
019036a4 528 if (!IN_SET(t->answer_dnssec_result,
b652d4a2
LP
529 _DNSSEC_RESULT_INVALID, /* No DNSSEC validation enabled */
530 DNSSEC_VALIDATED, /* Answer is signed and validated successfully */
531 DNSSEC_UNSIGNED, /* Answer is right-fully unsigned */
532 DNSSEC_INCOMPATIBLE_SERVER)) { /* Server does not do DNSSEC (Yay, we are downgrade attack vulnerable!) */
547973de
LP
533 dns_transaction_complete(t, DNS_TRANSACTION_DNSSEC_FAILED);
534 return;
535 }
536
537 dns_transaction_cache_answer(t);
538
539 if (t->answer_rcode == DNS_RCODE_SUCCESS)
540 dns_transaction_complete(t, DNS_TRANSACTION_SUCCESS);
541 else
3bbdc31d 542 dns_transaction_complete(t, DNS_TRANSACTION_RCODE_FAILURE);
547973de
LP
543}
544
ec2c5e43 545void dns_transaction_process_reply(DnsTransaction *t, DnsPacket *p) {
9df3ba6c 546 usec_t ts;
ec2c5e43
LP
547 int r;
548
549 assert(t);
550 assert(p);
9df3ba6c
TG
551 assert(t->scope);
552 assert(t->scope->manager);
ec2c5e43 553
5a7e41a3
LP
554 if (t->state != DNS_TRANSACTION_PENDING)
555 return;
556
ec2c5e43
LP
557 /* Note that this call might invalidate the query. Callers
558 * should hence not attempt to access the query or transaction
559 * after calling this function. */
560
b5efcf29
LP
561 log_debug("Processing incoming packet on transaction %" PRIu16".", t->id);
562
106784eb 563 switch (t->scope->protocol) {
b5efcf29 564
106784eb 565 case DNS_PROTOCOL_LLMNR:
ec2c5e43
LP
566 assert(t->scope->link);
567
568 /* For LLMNR we will not accept any packets from other
569 * interfaces */
570
571 if (p->ifindex != t->scope->link->ifindex)
572 return;
573
574 if (p->family != t->scope->family)
575 return;
576
577 /* Tentative packets are not full responses but still
578 * useful for identifying uniqueness conflicts during
579 * probing. */
8b757a38 580 if (DNS_PACKET_LLMNR_T(p)) {
ec2c5e43
LP
581 dns_transaction_tentative(t, p);
582 return;
583 }
106784eb
DM
584
585 break;
586
4e5bf5e1
DM
587 case DNS_PROTOCOL_MDNS:
588 assert(t->scope->link);
589
590 /* For mDNS we will not accept any packets from other interfaces */
591 if (p->ifindex != t->scope->link->ifindex)
592 return;
593
594 if (p->family != t->scope->family)
595 return;
596
597 break;
598
106784eb 599 case DNS_PROTOCOL_DNS:
8ad182a1
LP
600 /* Note that we do not need to verify the
601 * addresses/port numbers of incoming traffic, as we
602 * invoked connect() on our UDP socket in which case
603 * the kernel already does the needed verification for
604 * us. */
106784eb
DM
605 break;
606
607 default:
9c56a6f3 608 assert_not_reached("Invalid DNS protocol.");
ec2c5e43
LP
609 }
610
ec2c5e43
LP
611 if (t->received != p) {
612 dns_packet_unref(t->received);
613 t->received = dns_packet_ref(p);
614 }
615
c3bc53e6
LP
616 t->answer_source = DNS_TRANSACTION_NETWORK;
617
ec2c5e43
LP
618 if (p->ipproto == IPPROTO_TCP) {
619 if (DNS_PACKET_TC(p)) {
620 /* Truncated via TCP? Somebody must be fucking with us */
621 dns_transaction_complete(t, DNS_TRANSACTION_INVALID_REPLY);
622 return;
623 }
624
625 if (DNS_PACKET_ID(p) != t->id) {
626 /* Not the reply to our query? Somebody must be fucking with us */
627 dns_transaction_complete(t, DNS_TRANSACTION_INVALID_REPLY);
628 return;
629 }
630 }
631
38a03f06 632 assert_se(sd_event_now(t->scope->manager->event, clock_boottime_or_monotonic(), &ts) >= 0);
9df3ba6c
TG
633
634 switch (t->scope->protocol) {
8af5b883 635
9df3ba6c
TG
636 case DNS_PROTOCOL_DNS:
637 assert(t->server);
638
4e0b8b17
TG
639 if (IN_SET(DNS_PACKET_RCODE(p), DNS_RCODE_FORMERR, DNS_RCODE_SERVFAIL, DNS_RCODE_NOTIMP)) {
640
8af5b883 641 /* Request failed, immediately try again with reduced features */
4e0b8b17
TG
642 log_debug("Server returned error: %s", dns_rcode_to_string(DNS_PACKET_RCODE(p)));
643
644 dns_server_packet_failed(t->server, t->current_features);
645
646 r = dns_transaction_go(t);
647 if (r < 0) {
648 dns_transaction_complete(t, DNS_TRANSACTION_RESOURCES);
649 return;
650 }
651
652 return;
653 } else
d74fb368 654 dns_server_packet_received(t->server, t->current_features, ts - t->start_usec, p->size);
9df3ba6c
TG
655
656 break;
8af5b883 657
9df3ba6c
TG
658 case DNS_PROTOCOL_LLMNR:
659 case DNS_PROTOCOL_MDNS:
660 dns_scope_packet_received(t->scope, ts - t->start_usec);
9df3ba6c 661 break;
8af5b883 662
9df3ba6c 663 default:
8af5b883 664 assert_not_reached("Invalid DNS protocol.");
9df3ba6c
TG
665 }
666
ec2c5e43 667 if (DNS_PACKET_TC(p)) {
547493c5
DM
668
669 /* Truncated packets for mDNS are not allowed. Give up immediately. */
670 if (t->scope->protocol == DNS_PROTOCOL_MDNS) {
671 dns_transaction_complete(t, DNS_TRANSACTION_INVALID_REPLY);
672 return;
673 }
674
ec2c5e43
LP
675 /* Response was truncated, let's try again with good old TCP */
676 r = dns_transaction_open_tcp(t);
677 if (r == -ESRCH) {
678 /* No servers found? Damn! */
679 dns_transaction_complete(t, DNS_TRANSACTION_NO_SERVERS);
680 return;
681 }
682 if (r < 0) {
8af5b883 683 /* On LLMNR, if we cannot connect to the host,
ec2c5e43
LP
684 * we immediately give up */
685 if (t->scope->protocol == DNS_PROTOCOL_LLMNR) {
686 dns_transaction_complete(t, DNS_TRANSACTION_RESOURCES);
687 return;
688 }
689
690 /* On DNS, couldn't send? Try immediately again, with a new server */
519ef046 691 dns_scope_next_dns_server(t->scope);
ec2c5e43
LP
692
693 r = dns_transaction_go(t);
694 if (r < 0) {
695 dns_transaction_complete(t, DNS_TRANSACTION_RESOURCES);
696 return;
697 }
ec2c5e43 698 }
2a6658ef
LP
699
700 return;
ec2c5e43
LP
701 }
702
8af5b883 703 /* Parse message, if it isn't parsed yet. */
ec2c5e43
LP
704 r = dns_packet_extract(p);
705 if (r < 0) {
706 dns_transaction_complete(t, DNS_TRANSACTION_INVALID_REPLY);
707 return;
708 }
709
b5efcf29
LP
710 if (IN_SET(t->scope->protocol, DNS_PROTOCOL_DNS, DNS_PROTOCOL_LLMNR)) {
711
547493c5 712 /* Only consider responses with equivalent query section to the request */
8af5b883
LP
713 r = dns_packet_is_reply_for(p, t->key);
714 if (r < 0) {
715 dns_transaction_complete(t, DNS_TRANSACTION_RESOURCES);
716 return;
717 }
718 if (r == 0) {
547493c5
DM
719 dns_transaction_complete(t, DNS_TRANSACTION_INVALID_REPLY);
720 return;
721 }
29815b6c 722
547493c5
DM
723 /* Install the answer as answer to the transaction */
724 dns_answer_unref(t->answer);
725 t->answer = dns_answer_ref(p->answer);
726 t->answer_rcode = DNS_PACKET_RCODE(p);
919c2ae0 727 t->answer_dnssec_result = _DNSSEC_RESULT_INVALID;
105e1512 728 t->answer_authenticated = false;
79e24931 729
51e399bc
LP
730 /* Block GC while starting requests for additional DNSSEC RRs */
731 t->block_gc++;
547973de 732 r = dns_transaction_request_dnssec_keys(t);
51e399bc
LP
733 t->block_gc--;
734
735 /* Maybe the transaction is ready for GC'ing now? If so, free it and return. */
736 if (!dns_transaction_gc(t))
737 return;
738
739 /* Requesting additional keys might have resulted in
740 * this transaction to fail, since the auxiliary
741 * request failed for some reason. If so, we are not
742 * in pending state anymore, and we should exit
743 * quickly. */
744 if (t->state != DNS_TRANSACTION_PENDING)
745 return;
547973de
LP
746 if (r < 0) {
747 dns_transaction_complete(t, DNS_TRANSACTION_RESOURCES);
748 return;
749 }
750 if (r > 0) {
751 /* There are DNSSEC transactions pending now. Update the state accordingly. */
752 t->state = DNS_TRANSACTION_VALIDATING;
f535705a
LP
753 dns_transaction_close_connection(t);
754 dns_transaction_stop_timeout(t);
547973de
LP
755 return;
756 }
547493c5 757 }
ec2c5e43 758
547973de 759 dns_transaction_process_dnssec(t);
ec2c5e43
LP
760}
761
c19ffd9f
TG
762static int on_dns_packet(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
763 _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
764 DnsTransaction *t = userdata;
765 int r;
766
767 assert(t);
768 assert(t->scope);
769
770 r = manager_recv(t->scope->manager, fd, DNS_PROTOCOL_DNS, &p);
771 if (r <= 0)
772 return r;
773
774 if (dns_packet_validate_reply(p) > 0 &&
9df3ba6c 775 DNS_PACKET_ID(p) == t->id)
c19ffd9f 776 dns_transaction_process_reply(t, p);
9df3ba6c 777 else
2c6bf498 778 log_debug("Invalid DNS UDP packet, ignoring.");
c19ffd9f
TG
779
780 return 0;
781}
782
49cce12d 783static int dns_transaction_emit_udp(DnsTransaction *t) {
c19ffd9f
TG
784 int r;
785
786 assert(t);
c19ffd9f 787
519ef046 788 if (t->scope->protocol == DNS_PROTOCOL_DNS) {
c19ffd9f 789
519ef046 790 r = dns_transaction_pick_server(t);
471d40d9
TG
791 if (r < 0)
792 return r;
c19ffd9f 793
519ef046
LP
794 if (t->current_features < DNS_SERVER_FEATURE_LEVEL_UDP)
795 return -EAGAIN;
796
797 if (r > 0 || t->dns_udp_fd < 0) { /* Server changed, or no connection yet. */
798 int fd;
799
800 dns_transaction_close_connection(t);
c19ffd9f 801
519ef046
LP
802 fd = dns_scope_socket_udp(t->scope, t->server, 53);
803 if (fd < 0)
804 return fd;
805
806 r = sd_event_add_io(t->scope->manager->event, &t->dns_udp_event_source, fd, EPOLLIN, on_dns_packet, t);
807 if (r < 0) {
808 safe_close(fd);
809 return r;
810 }
811
812 t->dns_udp_fd = fd;
813 }
814
815 r = dns_server_adjust_opt(t->server, t->sent, t->current_features);
816 if (r < 0)
817 return r;
818 } else
819 dns_transaction_close_connection(t);
820
821 r = dns_scope_emit_udp(t->scope, t->dns_udp_fd, t->sent);
471d40d9
TG
822 if (r < 0)
823 return r;
c19ffd9f 824
519ef046 825 dns_transaction_reset_answer(t);
be808ea0 826
471d40d9 827 return 0;
c19ffd9f
TG
828}
829
ec2c5e43
LP
830static int on_transaction_timeout(sd_event_source *s, usec_t usec, void *userdata) {
831 DnsTransaction *t = userdata;
832 int r;
833
834 assert(s);
835 assert(t);
836
ef7ce6df
DM
837 if (!t->initial_jitter_scheduled || t->initial_jitter_elapsed) {
838 /* Timeout reached? Increase the timeout for the server used */
839 switch (t->scope->protocol) {
49cce12d 840
ef7ce6df
DM
841 case DNS_PROTOCOL_DNS:
842 assert(t->server);
ef7ce6df 843 dns_server_packet_lost(t->server, t->current_features, usec - t->start_usec);
ef7ce6df 844 break;
49cce12d 845
ef7ce6df
DM
846 case DNS_PROTOCOL_LLMNR:
847 case DNS_PROTOCOL_MDNS:
848 dns_scope_packet_lost(t->scope, usec - t->start_usec);
ef7ce6df 849 break;
49cce12d 850
ef7ce6df
DM
851 default:
852 assert_not_reached("Invalid DNS protocol.");
853 }
854
855 if (t->initial_jitter_scheduled)
856 t->initial_jitter_elapsed = true;
be808ea0
TG
857 }
858
423659ab
LP
859 log_debug("Timeout reached on transaction %" PRIu16 ".", t->id);
860
be808ea0 861 /* ...and try again with a new server */
519ef046 862 dns_scope_next_dns_server(t->scope);
be808ea0 863
ec2c5e43
LP
864 r = dns_transaction_go(t);
865 if (r < 0)
866 dns_transaction_complete(t, DNS_TRANSACTION_RESOURCES);
867
868 return 0;
869}
870
9df3ba6c
TG
871static usec_t transaction_get_resend_timeout(DnsTransaction *t) {
872 assert(t);
873 assert(t->scope);
874
875 switch (t->scope->protocol) {
49cce12d 876
9df3ba6c
TG
877 case DNS_PROTOCOL_DNS:
878 assert(t->server);
9df3ba6c 879 return t->server->resend_timeout;
49cce12d 880
9df3ba6c 881 case DNS_PROTOCOL_MDNS:
11a27c2e
DM
882 assert(t->n_attempts > 0);
883 return (1 << (t->n_attempts - 1)) * USEC_PER_SEC;
49cce12d 884
11a27c2e 885 case DNS_PROTOCOL_LLMNR:
9df3ba6c 886 return t->scope->resend_timeout;
49cce12d 887
9df3ba6c
TG
888 default:
889 assert_not_reached("Invalid DNS protocol.");
890 }
891}
892
c842ff24 893static int dns_transaction_prepare(DnsTransaction *t, usec_t ts) {
ec2c5e43
LP
894 int r;
895
896 assert(t);
897
f535705a 898 dns_transaction_stop_timeout(t);
ec2c5e43 899
ec2c5e43
LP
900 if (t->n_attempts >= TRANSACTION_ATTEMPTS_MAX(t->scope->protocol)) {
901 dns_transaction_complete(t, DNS_TRANSACTION_ATTEMPTS_MAX_REACHED);
902 return 0;
903 }
904
cbe4216d 905 if (t->scope->protocol == DNS_PROTOCOL_LLMNR && t->tried_stream) {
ec2c5e43
LP
906 /* If we already tried via a stream, then we don't
907 * retry on LLMNR. See RFC 4795, Section 2.7. */
908 dns_transaction_complete(t, DNS_TRANSACTION_ATTEMPTS_MAX_REACHED);
909 return 0;
910 }
911
912 t->n_attempts++;
9df3ba6c 913 t->start_usec = ts;
c61d2b44
LP
914
915 dns_transaction_reset_answer(t);
ec2c5e43 916
0d2cd476
LP
917 /* Check the trust anchor. Do so only on classic DNS, since DNSSEC does not apply otherwise. */
918 if (t->scope->protocol == DNS_PROTOCOL_DNS) {
8e54f5d9 919 r = dns_trust_anchor_lookup_positive(&t->scope->manager->trust_anchor, t->key, &t->answer);
0d2cd476
LP
920 if (r < 0)
921 return r;
922 if (r > 0) {
923 t->answer_rcode = DNS_RCODE_SUCCESS;
924 t->answer_source = DNS_TRANSACTION_TRUST_ANCHOR;
931851e8 925 t->answer_authenticated = true;
0d2cd476
LP
926 dns_transaction_complete(t, DNS_TRANSACTION_SUCCESS);
927 return 0;
928 }
b2b796b8
LP
929
930 if (dns_name_is_root(DNS_RESOURCE_KEY_NAME(t->key)) &&
931 t->key->type == DNS_TYPE_DS) {
932
933 /* Hmm, this is a request for the root DS? A
934 * DS RR doesn't exist in the root zone, and
935 * if our trust anchor didn't know it either,
936 * this means we cannot do any DNSSEC logic
937 * anymore. */
938
939 if (t->scope->dnssec_mode == DNSSEC_DOWNGRADE_OK) {
940 /* We are in downgrade mode. In this
941 * case, synthesize an unsigned empty
942 * response, so that the any lookup
943 * depending on this one can continue
944 * assuming there was no DS, and hence
945 * the root zone was unsigned. */
946
947 t->answer_rcode = DNS_RCODE_SUCCESS;
948 t->answer_source = DNS_TRANSACTION_TRUST_ANCHOR;
949 t->answer_authenticated = false;
950 dns_transaction_complete(t, DNS_TRANSACTION_SUCCESS);
951 } else
952 /* If we are not in downgrade mode,
953 * then fail the lookup, because we
954 * cannot reasonably answer it. There
955 * might be DS RRs, but we don't know
956 * them, and the DNS server won't tell
957 * them to us (and even if it would,
958 * we couldn't validate it and trust
959 * it). */
960 dns_transaction_complete(t, DNS_TRANSACTION_NO_TRUST_ANCHOR);
961
962 return 0;
963 }
0d2cd476
LP
964 }
965
966 /* Check the zone, but only if this transaction is not used
d746bb3e 967 * for probing or verifying a zone item. */
547973de 968 if (set_isempty(t->notify_zone_items)) {
d746bb3e 969
ae6a4bbf 970 r = dns_zone_lookup(&t->scope->zone, t->key, &t->answer, NULL, NULL);
d746bb3e
LP
971 if (r < 0)
972 return r;
973 if (r > 0) {
ae6a4bbf 974 t->answer_rcode = DNS_RCODE_SUCCESS;
c3bc53e6 975 t->answer_source = DNS_TRANSACTION_ZONE;
931851e8 976 t->answer_authenticated = true;
d746bb3e
LP
977 dns_transaction_complete(t, DNS_TRANSACTION_SUCCESS);
978 return 0;
979 }
980 }
981
4d926a69
LP
982 /* Check the cache, but only if this transaction is not used
983 * for probing or verifying a zone item. */
547973de 984 if (set_isempty(t->notify_zone_items)) {
2c27fbca 985
4d926a69
LP
986 /* Before trying the cache, let's make sure we figured out a
987 * server to use. Should this cause a change of server this
988 * might flush the cache. */
989 dns_scope_get_dns_server(t->scope);
2c27fbca 990
4d926a69
LP
991 /* Let's then prune all outdated entries */
992 dns_cache_prune(&t->scope->cache);
993
931851e8 994 r = dns_cache_lookup(&t->scope->cache, t->key, &t->answer_rcode, &t->answer, &t->answer_authenticated);
4d926a69
LP
995 if (r < 0)
996 return r;
997 if (r > 0) {
c3bc53e6 998 t->answer_source = DNS_TRANSACTION_CACHE;
ae6a4bbf 999 if (t->answer_rcode == DNS_RCODE_SUCCESS)
4d926a69
LP
1000 dns_transaction_complete(t, DNS_TRANSACTION_SUCCESS);
1001 else
3bbdc31d 1002 dns_transaction_complete(t, DNS_TRANSACTION_RCODE_FAILURE);
4d926a69
LP
1003 return 0;
1004 }
ec2c5e43
LP
1005 }
1006
1effe965
DM
1007 return 1;
1008}
1009
0afa57e2
DM
1010static int dns_transaction_make_packet_mdns(DnsTransaction *t) {
1011
1012 _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
7778dfff 1013 bool add_known_answers = false;
0afa57e2
DM
1014 DnsTransaction *other;
1015 unsigned qdcount;
1016 usec_t ts;
1017 int r;
1018
1019 assert(t);
1020 assert(t->scope->protocol == DNS_PROTOCOL_MDNS);
1021
e5abebab 1022 /* Discard any previously prepared packet, so we can start over and coalesce again */
0afa57e2
DM
1023 t->sent = dns_packet_unref(t->sent);
1024
1025 r = dns_packet_new_query(&p, t->scope->protocol, 0, false);
1026 if (r < 0)
1027 return r;
1028
1029 r = dns_packet_append_key(p, t->key, NULL);
1030 if (r < 0)
1031 return r;
1032
1033 qdcount = 1;
1034
7778dfff
DM
1035 if (dns_key_is_shared(t->key))
1036 add_known_answers = true;
1037
0afa57e2
DM
1038 /*
1039 * For mDNS, we want to coalesce as many open queries in pending transactions into one single
1040 * query packet on the wire as possible. To achieve that, we iterate through all pending transactions
1041 * in our current scope, and see whether their timing contraints allow them to be sent.
1042 */
1043
1044 assert_se(sd_event_now(t->scope->manager->event, clock_boottime_or_monotonic(), &ts) >= 0);
1045
1046 LIST_FOREACH(transactions_by_scope, other, t->scope->transactions) {
1047
1048 /* Skip ourselves */
1049 if (other == t)
1050 continue;
1051
1052 if (other->state != DNS_TRANSACTION_PENDING)
1053 continue;
1054
1055 if (other->next_attempt_after > ts)
1056 continue;
1057
1058 if (qdcount >= UINT16_MAX)
1059 break;
1060
1061 r = dns_packet_append_key(p, other->key, NULL);
1062
1063 /*
1064 * If we can't stuff more questions into the packet, just give up.
1065 * One of the 'other' transactions will fire later and take care of the rest.
1066 */
1067 if (r == -EMSGSIZE)
1068 break;
1069
1070 if (r < 0)
1071 return r;
1072
c842ff24 1073 r = dns_transaction_prepare(other, ts);
0afa57e2
DM
1074 if (r <= 0)
1075 continue;
1076
1077 ts += transaction_get_resend_timeout(other);
1078
1079 r = sd_event_add_time(
1080 other->scope->manager->event,
1081 &other->timeout_event_source,
1082 clock_boottime_or_monotonic(),
1083 ts, 0,
1084 on_transaction_timeout, other);
1085 if (r < 0)
1086 return r;
1087
1088 other->state = DNS_TRANSACTION_PENDING;
1089 other->next_attempt_after = ts;
1090
1091 qdcount ++;
7778dfff
DM
1092
1093 if (dns_key_is_shared(other->key))
1094 add_known_answers = true;
0afa57e2
DM
1095 }
1096
1097 DNS_PACKET_HEADER(p)->qdcount = htobe16(qdcount);
0afa57e2 1098
7778dfff
DM
1099 /* Append known answer section if we're asking for any shared record */
1100 if (add_known_answers) {
1101 r = dns_cache_export_shared_to_packet(&t->scope->cache, p);
1102 if (r < 0)
1103 return r;
1104 }
1105
0afa57e2
DM
1106 t->sent = p;
1107 p = NULL;
1108
1109 return 0;
1110}
1111
1112static int dns_transaction_make_packet(DnsTransaction *t) {
1113 _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
1114 int r;
1115
1116 assert(t);
1117
1118 if (t->scope->protocol == DNS_PROTOCOL_MDNS)
1119 return dns_transaction_make_packet_mdns(t);
1120
1121 if (t->sent)
1122 return 0;
1123
b652d4a2 1124 r = dns_packet_new_query(&p, t->scope->protocol, 0, t->scope->dnssec_mode != DNSSEC_NO);
0afa57e2
DM
1125 if (r < 0)
1126 return r;
1127
1128 r = dns_scope_good_key(t->scope, t->key);
1129 if (r < 0)
1130 return r;
1131 if (r == 0)
1132 return -EDOM;
1133
1134 r = dns_packet_append_key(p, t->key, NULL);
1135 if (r < 0)
1136 return r;
1137
1138 DNS_PACKET_HEADER(p)->qdcount = htobe16(1);
1139 DNS_PACKET_HEADER(p)->id = t->id;
1140
1141 t->sent = p;
1142 p = NULL;
1143
1144 return 0;
1145}
1146
1effe965
DM
1147int dns_transaction_go(DnsTransaction *t) {
1148 usec_t ts;
1149 int r;
1150
1151 assert(t);
1152
1153 assert_se(sd_event_now(t->scope->manager->event, clock_boottime_or_monotonic(), &ts) >= 0);
547973de 1154
c842ff24 1155 r = dns_transaction_prepare(t, ts);
1effe965
DM
1156 if (r <= 0)
1157 return r;
1158
a5784c49
LP
1159 log_debug("Excercising transaction %" PRIu16 " for <%s> on scope %s on %s/%s.",
1160 t->id,
1161 dns_transaction_key_string(t),
1162 dns_protocol_to_string(t->scope->protocol),
1163 t->scope->link ? t->scope->link->name : "*",
1164 t->scope->family == AF_UNSPEC ? "*" : af_to_name(t->scope->family));
1effe965 1165
ef7ce6df 1166 if (!t->initial_jitter_scheduled &&
ea12bcc7
DM
1167 (t->scope->protocol == DNS_PROTOCOL_LLMNR ||
1168 t->scope->protocol == DNS_PROTOCOL_MDNS)) {
1169 usec_t jitter, accuracy;
6e068472
LP
1170
1171 /* RFC 4795 Section 2.7 suggests all queries should be
1172 * delayed by a random time from 0 to JITTER_INTERVAL. */
1173
ef7ce6df 1174 t->initial_jitter_scheduled = true;
6e068472
LP
1175
1176 random_bytes(&jitter, sizeof(jitter));
ea12bcc7
DM
1177
1178 switch (t->scope->protocol) {
519ef046 1179
ea12bcc7
DM
1180 case DNS_PROTOCOL_LLMNR:
1181 jitter %= LLMNR_JITTER_INTERVAL_USEC;
1182 accuracy = LLMNR_JITTER_INTERVAL_USEC;
1183 break;
519ef046 1184
ea12bcc7
DM
1185 case DNS_PROTOCOL_MDNS:
1186 jitter %= MDNS_JITTER_RANGE_USEC;
1187 jitter += MDNS_JITTER_MIN_USEC;
1188 accuracy = MDNS_JITTER_RANGE_USEC;
1189 break;
1190 default:
1191 assert_not_reached("bad protocol");
1192 }
6e068472
LP
1193
1194 r = sd_event_add_time(
1195 t->scope->manager->event,
1196 &t->timeout_event_source,
1197 clock_boottime_or_monotonic(),
ea12bcc7 1198 ts + jitter, accuracy,
6e068472
LP
1199 on_transaction_timeout, t);
1200 if (r < 0)
1201 return r;
1202
1203 t->n_attempts = 0;
a9da14e1 1204 t->next_attempt_after = ts;
6e068472
LP
1205 t->state = DNS_TRANSACTION_PENDING;
1206
ea12bcc7 1207 log_debug("Delaying %s transaction for " USEC_FMT "us.", dns_protocol_to_string(t->scope->protocol), jitter);
6e068472
LP
1208 return 0;
1209 }
1210
ec2c5e43
LP
1211 /* Otherwise, we need to ask the network */
1212 r = dns_transaction_make_packet(t);
1213 if (r == -EDOM) {
1214 /* Not the right request to make on this network?
1215 * (i.e. an A request made on IPv6 or an AAAA request
1216 * made on IPv4, on LLMNR or mDNS.) */
1217 dns_transaction_complete(t, DNS_TRANSACTION_NO_SERVERS);
1218 return 0;
1219 }
1220 if (r < 0)
1221 return r;
1222
1223 if (t->scope->protocol == DNS_PROTOCOL_LLMNR &&
f52e61da
LP
1224 (dns_name_endswith(DNS_RESOURCE_KEY_NAME(t->key), "in-addr.arpa") > 0 ||
1225 dns_name_endswith(DNS_RESOURCE_KEY_NAME(t->key), "ip6.arpa") > 0)) {
ec2c5e43
LP
1226
1227 /* RFC 4795, Section 2.4. says reverse lookups shall
1228 * always be made via TCP on LLMNR */
1229 r = dns_transaction_open_tcp(t);
1230 } else {
be808ea0
TG
1231 /* Try via UDP, and if that fails due to large size or lack of
1232 * support try via TCP */
49cce12d 1233 r = dns_transaction_emit_udp(t);
be808ea0 1234 if (r == -EMSGSIZE || r == -EAGAIN)
ec2c5e43
LP
1235 r = dns_transaction_open_tcp(t);
1236 }
be808ea0 1237
ec2c5e43
LP
1238 if (r == -ESRCH) {
1239 /* No servers to send this to? */
1240 dns_transaction_complete(t, DNS_TRANSACTION_NO_SERVERS);
1241 return 0;
8300ba21 1242 } else if (r < 0) {
13b551ac
LP
1243 if (t->scope->protocol != DNS_PROTOCOL_DNS) {
1244 dns_transaction_complete(t, DNS_TRANSACTION_RESOURCES);
1245 return 0;
1246 }
1247
ec2c5e43 1248 /* Couldn't send? Try immediately again, with a new server */
519ef046 1249 dns_scope_next_dns_server(t->scope);
ec2c5e43
LP
1250
1251 return dns_transaction_go(t);
1252 }
1253
a9da14e1
DM
1254 ts += transaction_get_resend_timeout(t);
1255
9a015429
LP
1256 r = sd_event_add_time(
1257 t->scope->manager->event,
1258 &t->timeout_event_source,
1259 clock_boottime_or_monotonic(),
a9da14e1 1260 ts, 0,
9a015429 1261 on_transaction_timeout, t);
ec2c5e43
LP
1262 if (r < 0)
1263 return r;
1264
1265 t->state = DNS_TRANSACTION_PENDING;
a9da14e1
DM
1266 t->next_attempt_after = ts;
1267
ec2c5e43
LP
1268 return 1;
1269}
1270
f2992dc1
LP
1271static int dns_transaction_find_cyclic(DnsTransaction *t, DnsTransaction *aux) {
1272 DnsTransaction *n;
1273 Iterator i;
1274 int r;
1275
1276 assert(t);
1277 assert(aux);
1278
1279 /* Try to find cyclic dependencies between transaction objects */
1280
1281 if (t == aux)
1282 return 1;
1283
1284 SET_FOREACH(n, aux->notify_transactions, i) {
1285 r = dns_transaction_find_cyclic(t, n);
1286 if (r != 0)
1287 return r;
1288 }
1289
1290 return r;
1291}
1292
547973de
LP
1293static int dns_transaction_add_dnssec_transaction(DnsTransaction *t, DnsResourceKey *key, DnsTransaction **ret) {
1294 DnsTransaction *aux;
1295 int r;
1296
1297 assert(t);
1298 assert(ret);
1299 assert(key);
1300
1301 aux = dns_scope_find_transaction(t->scope, key, true);
1302 if (!aux) {
1303 r = dns_transaction_new(&aux, t->scope, key);
1304 if (r < 0)
1305 return r;
1306 } else {
1307 if (set_contains(t->dnssec_transactions, aux)) {
1308 *ret = aux;
1309 return 0;
1310 }
f2992dc1
LP
1311
1312 r = dns_transaction_find_cyclic(t, aux);
1313 if (r < 0)
1314 return r;
1315 if (r > 0) {
1316 log_debug("Detected potential cyclic dependency, refusing to add transaction %" PRIu16 " (%s) as dependency for %" PRIu16 " (%s).",
1317 aux->id,
1318 strna(dns_transaction_key_string(aux)),
1319 t->id,
1320 strna(dns_transaction_key_string(t)));
1321 return -ELOOP;
1322 }
547973de
LP
1323 }
1324
1325 r = set_ensure_allocated(&t->dnssec_transactions, NULL);
1326 if (r < 0)
1327 goto gc;
1328
1329 r = set_ensure_allocated(&aux->notify_transactions, NULL);
1330 if (r < 0)
1331 goto gc;
1332
1333 r = set_put(t->dnssec_transactions, aux);
1334 if (r < 0)
1335 goto gc;
1336
1337 r = set_put(aux->notify_transactions, t);
1338 if (r < 0) {
1339 (void) set_remove(t->dnssec_transactions, aux);
1340 goto gc;
1341 }
1342
1343 *ret = aux;
1344 return 1;
1345
1346gc:
1347 dns_transaction_gc(aux);
1348 return r;
1349}
1350
1351static int dns_transaction_request_dnssec_rr(DnsTransaction *t, DnsResourceKey *key) {
1352 _cleanup_(dns_answer_unrefp) DnsAnswer *a = NULL;
1353 DnsTransaction *aux;
1354 int r;
1355
1356 assert(t);
1357 assert(key);
1358
1359 /* Try to get the data from the trust anchor */
8e54f5d9 1360 r = dns_trust_anchor_lookup_positive(&t->scope->manager->trust_anchor, key, &a);
547973de
LP
1361 if (r < 0)
1362 return r;
1363 if (r > 0) {
1364 r = dns_answer_extend(&t->validated_keys, a);
1365 if (r < 0)
1366 return r;
1367
1368 return 0;
1369 }
1370
1371 /* This didn't work, ask for it via the network/cache then. */
1372 r = dns_transaction_add_dnssec_transaction(t, key, &aux);
f2992dc1
LP
1373 if (r == -ELOOP) /* This would result in a cyclic dependency */
1374 return 0;
547973de
LP
1375 if (r < 0)
1376 return r;
1377
1378 if (aux->state == DNS_TRANSACTION_NULL) {
1379 r = dns_transaction_go(aux);
1380 if (r < 0)
1381 return r;
1382 }
1383
f2992dc1 1384 return 1;
547973de
LP
1385}
1386
105e1512
LP
1387static int dns_transaction_has_positive_answer(DnsTransaction *t, DnsAnswerFlags *flags) {
1388 int r;
1389
1390 assert(t);
1391
1392 /* Checks whether the answer is positive, i.e. either a direct
1393 * answer to the question, or a CNAME/DNAME for it */
1394
1395 r = dns_answer_match_key(t->answer, t->key, flags);
1396 if (r != 0)
1397 return r;
1398
1399 r = dns_answer_find_cname_or_dname(t->answer, t->key, NULL, flags);
1400 if (r != 0)
1401 return r;
1402
1403 return false;
1404}
1405
1406static int dns_transaction_has_unsigned_negative_answer(DnsTransaction *t) {
1407 int r;
1408
1409 assert(t);
1410
1411 /* Checks whether the answer is negative, and lacks NSEC/NSEC3
1412 * RRs to prove it */
1413
1414 r = dns_transaction_has_positive_answer(t, NULL);
1415 if (r < 0)
1416 return r;
1417 if (r > 0)
1418 return false;
1419
8e54f5d9
LP
1420 /* Is this key explicitly listed as a negative trust anchor?
1421 * If so, it's nothing we need to care about */
1422 r = dns_trust_anchor_lookup_negative(&t->scope->manager->trust_anchor, DNS_RESOURCE_KEY_NAME(t->key));
1423 if (r < 0)
1424 return r;
1425 if (r > 0)
1426 return false;
1427
105e1512
LP
1428 /* The answer does not contain any RRs that match to the
1429 * question. If so, let's see if there are any NSEC/NSEC3 RRs
1430 * included. If not, the answer is unsigned. */
1431
1432 r = dns_answer_contains_nsec_or_nsec3(t->answer);
1433 if (r < 0)
1434 return r;
1435 if (r > 0)
1436 return false;
1437
1438 return true;
1439}
1440
1441static int dns_transaction_is_primary_response(DnsTransaction *t, DnsResourceRecord *rr) {
1442 int r;
1443
1444 assert(t);
1445 assert(rr);
1446
1447 /* Check if the specified RR is the "primary" response,
1448 * i.e. either matches the question precisely or is a
1449 * CNAME/DNAME for it, or is any kind of NSEC/NSEC3 RR */
1450
1451 r = dns_resource_key_match_rr(t->key, rr, NULL);
1452 if (r != 0)
1453 return r;
1454
1455 r = dns_resource_key_match_cname_or_dname(t->key, rr->key, NULL);
1456 if (r != 0)
1457 return r;
1458
1459 if (rr->key->type == DNS_TYPE_NSEC3) {
1460 const char *p;
1461
1462 p = DNS_RESOURCE_KEY_NAME(rr->key);
1463 r = dns_name_parent(&p);
1464 if (r < 0)
1465 return r;
1466 if (r > 0) {
1467 r = dns_name_endswith(DNS_RESOURCE_KEY_NAME(t->key), p);
1468 if (r < 0)
1469 return r;
1470 if (r > 0)
1471 return true;
1472 }
1473 }
1474
1475 return rr->key->type == DNS_TYPE_NSEC;
1476}
1477
547973de
LP
1478int dns_transaction_request_dnssec_keys(DnsTransaction *t) {
1479 DnsResourceRecord *rr;
105e1512 1480
547973de
LP
1481 int r;
1482
1483 assert(t);
1484
105e1512
LP
1485 /*
1486 * Retrieve all auxiliary RRs for the answer we got, so that
1487 * we can verify signatures or prove that RRs are rightfully
1488 * unsigned. Specifically:
1489 *
1490 * - For RRSIG we get the matching DNSKEY
1491 * - For DNSKEY we get the matching DS
1492 * - For unsigned SOA/NS we get the matching DS
b63fca62 1493 * - For unsigned CNAME/DNAME/DS we get the parent SOA RR
105e1512
LP
1494 * - For other unsigned RRs we get the matching SOA RR
1495 * - For SOA/NS/DS queries with no matching response RRs, and no NSEC/NSEC3, the parent's SOA RR
1496 * - For other queries with no matching response RRs, and no NSEC/NSEC3, the SOA RR
1497 */
1498
b652d4a2 1499 if (t->scope->dnssec_mode == DNSSEC_NO)
547973de
LP
1500 return 0;
1501
b652d4a2
LP
1502 if (t->current_features < DNS_SERVER_FEATURE_LEVEL_DO)
1503 return 0; /* Server doesn't do DNSSEC, there's no point in requesting any RRs then. */
1504 if (t->server && t->server->rrsig_missing)
1505 return 0; /* Server handles DNSSEC requests, but isn't augmenting responses with RRSIGs. No point in trying DNSSEC then. */
1506
547973de
LP
1507 DNS_ANSWER_FOREACH(rr, t->answer) {
1508
105e1512
LP
1509 if (dns_type_is_pseudo(rr->key->type))
1510 continue;
1511
8e54f5d9
LP
1512 /* If this RR is in the negative trust anchor, we don't need to validate it. */
1513 r = dns_trust_anchor_lookup_negative(&t->scope->manager->trust_anchor, DNS_RESOURCE_KEY_NAME(rr->key));
1514 if (r < 0)
1515 return r;
1516 if (r > 0)
1517 continue;
1518
547973de
LP
1519 switch (rr->key->type) {
1520
1521 case DNS_TYPE_RRSIG: {
1522 /* For each RRSIG we request the matching DNSKEY */
1523 _cleanup_(dns_resource_key_unrefp) DnsResourceKey *dnskey = NULL;
1524
1525 /* If this RRSIG is about a DNSKEY RR and the
1526 * signer is the same as the owner, then we
1527 * already have the DNSKEY, and we don't have
1528 * to look for more. */
1529 if (rr->rrsig.type_covered == DNS_TYPE_DNSKEY) {
1530 r = dns_name_equal(rr->rrsig.signer, DNS_RESOURCE_KEY_NAME(rr->key));
1531 if (r < 0)
1532 return r;
1533 if (r > 0)
1534 continue;
1535 }
1536
105e1512
LP
1537 /* If the signer is not a parent of our
1538 * original query, then this is about an
1539 * auxiliary RRset, but not anything we asked
1540 * for. In this case we aren't interested,
1541 * because we don't want to request additional
1542 * RRs for stuff we didn't really ask for, and
1543 * also to avoid request loops, where
1544 * additional RRs from one transaction result
1545 * in another transaction whose additonal RRs
1546 * point back to the original transaction, and
1547 * we deadlock. */
1548 r = dns_name_endswith(DNS_RESOURCE_KEY_NAME(t->key), rr->rrsig.signer);
547973de
LP
1549 if (r < 0)
1550 return r;
1551 if (r == 0)
1552 continue;
1553
1554 dnskey = dns_resource_key_new(rr->key->class, DNS_TYPE_DNSKEY, rr->rrsig.signer);
1555 if (!dnskey)
1556 return -ENOMEM;
1557
105e1512 1558 log_debug("Requesting DNSKEY to validate transaction %" PRIu16" (%s, RRSIG with key tag: %" PRIu16 ").", t->id, DNS_RESOURCE_KEY_NAME(rr->key), rr->rrsig.key_tag);
547973de
LP
1559 r = dns_transaction_request_dnssec_rr(t, dnskey);
1560 if (r < 0)
1561 return r;
1562 break;
1563 }
1564
1565 case DNS_TYPE_DNSKEY: {
1566 /* For each DNSKEY we request the matching DS */
1567 _cleanup_(dns_resource_key_unrefp) DnsResourceKey *ds = NULL;
1568
105e1512
LP
1569 /* If the DNSKEY we are looking at is not for
1570 * zone we are interested in, nor any of its
1571 * parents, we aren't interested, and don't
1572 * request it. After all, we don't want to end
1573 * up in request loops, and want to keep
1574 * additional traffic down. */
1575
1576 r = dns_name_endswith(DNS_RESOURCE_KEY_NAME(t->key), DNS_RESOURCE_KEY_NAME(rr->key));
1577 if (r < 0)
1578 return r;
1579 if (r == 0)
1580 continue;
1581
547973de
LP
1582 ds = dns_resource_key_new(rr->key->class, DNS_TYPE_DS, DNS_RESOURCE_KEY_NAME(rr->key));
1583 if (!ds)
1584 return -ENOMEM;
1585
0c857028 1586 log_debug("Requesting DS to validate transaction %" PRIu16" (%s, DNSKEY with key tag: %" PRIu16 ").", t->id, DNS_RESOURCE_KEY_NAME(rr->key), dnssec_keytag(rr, false));
105e1512
LP
1587 r = dns_transaction_request_dnssec_rr(t, ds);
1588 if (r < 0)
1589 return r;
547973de 1590
105e1512
LP
1591 break;
1592 }
1593
105e1512
LP
1594 case DNS_TYPE_SOA:
1595 case DNS_TYPE_NS: {
1596 _cleanup_(dns_resource_key_unrefp) DnsResourceKey *ds = NULL;
1597
1598 /* For an unsigned SOA or NS, try to acquire
1599 * the matching DS RR, as we are at a zone cut
1600 * then, and whether a DS exists tells us
1601 * whether the zone is signed. Do so only if
1602 * this RR matches our original question,
1603 * however. */
1604
1605 r = dns_resource_key_match_rr(t->key, rr, NULL);
1606 if (r < 0)
1607 return r;
1608 if (r == 0)
1609 continue;
1610
1611 r = dnssec_has_rrsig(t->answer, rr->key);
1612 if (r < 0)
1613 return r;
1614 if (r > 0)
1615 continue;
1616
1617 ds = dns_resource_key_new(rr->key->class, DNS_TYPE_DS, DNS_RESOURCE_KEY_NAME(rr->key));
1618 if (!ds)
1619 return -ENOMEM;
1620
1621 log_debug("Requesting DS to validate transaction %" PRIu16 " (%s, unsigned SOA/NS RRset).", t->id, DNS_RESOURCE_KEY_NAME(rr->key));
547973de
LP
1622 r = dns_transaction_request_dnssec_rr(t, ds);
1623 if (r < 0)
1624 return r;
1625
1626 break;
105e1512
LP
1627 }
1628
b63fca62 1629 case DNS_TYPE_DS:
105e1512
LP
1630 case DNS_TYPE_CNAME:
1631 case DNS_TYPE_DNAME: {
1632 _cleanup_(dns_resource_key_unrefp) DnsResourceKey *soa = NULL;
1633 const char *name;
1634
1635 /* CNAMEs and DNAMEs cannot be located at a
1636 * zone apex, hence ask for the parent SOA for
1637 * unsigned CNAME/DNAME RRs, maybe that's the
1638 * apex. But do all that only if this is
1639 * actually a response to our original
b63fca62
LP
1640 * question.
1641 *
1642 * Similar for DS RRs, which are signed when
1643 * the parent SOA is signed. */
105e1512
LP
1644
1645 r = dns_transaction_is_primary_response(t, rr);
1646 if (r < 0)
1647 return r;
1648 if (r == 0)
1649 continue;
1650
1651 r = dnssec_has_rrsig(t->answer, rr->key);
1652 if (r < 0)
1653 return r;
1654 if (r > 0)
1655 continue;
1656
1657 name = DNS_RESOURCE_KEY_NAME(rr->key);
1658 r = dns_name_parent(&name);
1659 if (r < 0)
1660 return r;
1661 if (r == 0)
1662 continue;
1663
1664 soa = dns_resource_key_new(rr->key->class, DNS_TYPE_SOA, name);
1665 if (!soa)
1666 return -ENOMEM;
1667
b63fca62 1668 log_debug("Requesting parent SOA to validate transaction %" PRIu16 " (%s, unsigned CNAME/DNAME/DS RRset).", t->id, DNS_RESOURCE_KEY_NAME(rr->key));
105e1512
LP
1669 r = dns_transaction_request_dnssec_rr(t, soa);
1670 if (r < 0)
1671 return r;
1672
1673 break;
1674 }
1675
1676 default: {
1677 _cleanup_(dns_resource_key_unrefp) DnsResourceKey *soa = NULL;
1678
b63fca62
LP
1679 /* For other unsigned RRsets (including
1680 * NSEC/NSEC3!), look for proof the zone is
1681 * unsigned, by requesting the SOA RR of the
1682 * zone. However, do so only if they are
1683 * directly relevant to our original
105e1512
LP
1684 * question. */
1685
1686 r = dns_transaction_is_primary_response(t, rr);
1687 if (r < 0)
1688 return r;
1689 if (r == 0)
1690 continue;
1691
1692 r = dnssec_has_rrsig(t->answer, rr->key);
1693 if (r < 0)
1694 return r;
1695 if (r > 0)
1696 continue;
1697
1698 soa = dns_resource_key_new(rr->key->class, DNS_TYPE_SOA, DNS_RESOURCE_KEY_NAME(rr->key));
1699 if (!soa)
1700 return -ENOMEM;
1701
db5b0e92 1702 log_debug("Requesting SOA to validate transaction %" PRIu16 " (%s, unsigned non-SOA/NS RRset <%s>).", t->id, DNS_RESOURCE_KEY_NAME(rr->key), dns_resource_record_to_string(rr));
105e1512
LP
1703 r = dns_transaction_request_dnssec_rr(t, soa);
1704 if (r < 0)
1705 return r;
1706 break;
547973de
LP
1707 }}
1708 }
1709
105e1512
LP
1710 /* Above, we requested everything necessary to validate what
1711 * we got. Now, let's request what we need to validate what we
1712 * didn't get... */
1713
1714 r = dns_transaction_has_unsigned_negative_answer(t);
1715 if (r < 0)
1716 return r;
1717 if (r > 0) {
1718 const char *name;
1719
1720 name = DNS_RESOURCE_KEY_NAME(t->key);
1721
1722 /* If this was a SOA or NS request, then this
1723 * indicates that we are not at a zone apex, hence ask
1724 * the parent name instead. If this was a DS request,
1725 * then it's signed when the parent zone is signed,
1726 * hence ask the parent in that case, too. */
1727
1728 if (IN_SET(t->key->type, DNS_TYPE_SOA, DNS_TYPE_NS, DNS_TYPE_DS)) {
1729 r = dns_name_parent(&name);
1730 if (r < 0)
1731 return r;
1732 if (r > 0)
1733 log_debug("Requesting parent SOA to validate transaction %" PRIu16 " (%s, unsigned empty SOA/NS/DS response).", t->id, DNS_RESOURCE_KEY_NAME(t->key));
1734 else
1735 name = NULL;
1736 } else
1737 log_debug("Requesting SOA to validate transaction %" PRIu16 " (%s, unsigned empty non-SOA/NS/DS response).", t->id, DNS_RESOURCE_KEY_NAME(t->key));
1738
1739 if (name) {
1740 _cleanup_(dns_resource_key_unrefp) DnsResourceKey *soa = NULL;
1741
1742 soa = dns_resource_key_new(t->key->class, DNS_TYPE_SOA, name);
1743 if (!soa)
1744 return -ENOMEM;
1745
1746 r = dns_transaction_request_dnssec_rr(t, soa);
1747 if (r < 0)
1748 return r;
1749 }
1750 }
1751
1752 return dns_transaction_dnssec_is_live(t);
547973de
LP
1753}
1754
1755void dns_transaction_notify(DnsTransaction *t, DnsTransaction *source) {
1756 int r;
1757
1758 assert(t);
547973de
LP
1759 assert(source);
1760
105e1512
LP
1761 if (!IN_SET(t->state, DNS_TRANSACTION_PENDING, DNS_TRANSACTION_VALIDATING))
1762 return;
1763
547973de 1764 /* Invoked whenever any of our auxiliary DNSSEC transactions
105e1512
LP
1765 completed its work. We copy any RRs from that transaction
1766 over into our list of validated keys -- but only if the
1767 answer is authenticated.
1768
1769 Note that we fail our transaction if the auxiliary
1770 transaction failed, except on NXDOMAIN. This is because
1771 some broken DNS servers (Akamai...) will return NXDOMAIN
1772 for empty non-terminals. */
1773
6773896e 1774 switch (source->state) {
547973de 1775
6773896e
LP
1776 case DNS_TRANSACTION_DNSSEC_FAILED:
1777
1778 log_debug("Auxiliary DNSSEC RR query failed validation: %s", dnssec_result_to_string(source->answer_dnssec_result));
1779 t->answer_dnssec_result = source->answer_dnssec_result; /* Copy error code over */
1780 dns_transaction_complete(t, DNS_TRANSACTION_DNSSEC_FAILED);
1781 break;
1782
1783 case DNS_TRANSACTION_RCODE_FAILURE:
1784
1785 if (source->answer_rcode != DNS_RCODE_NXDOMAIN) {
1786 log_debug("Auxiliary DNSSEC RR query failed with rcode=%i.", source->answer_rcode);
105e1512 1787 goto fail;
547973de 1788 }
547973de 1789
6773896e
LP
1790 /* fall-through: NXDOMAIN is good enough for us */
1791
1792 case DNS_TRANSACTION_SUCCESS:
1793 if (source->answer_authenticated) {
1794 r = dns_answer_extend(&t->validated_keys, source->answer);
1795 if (r < 0) {
1796 log_error_errno(r, "Failed to merge validated DNSSEC key data: %m");
1797 goto fail;
1798 }
1799 }
1800
1801 /* If the state is still PENDING, we are still in the loop
1802 * that adds further DNSSEC transactions, hence don't check if
1803 * we are ready yet. If the state is VALIDATING however, we
1804 * should check if we are complete now. */
1805 if (t->state == DNS_TRANSACTION_VALIDATING)
1806 dns_transaction_process_dnssec(t);
1807 break;
1808
1809 default:
1810 log_debug("Auxiliary DNSSEC RR query failed with %s", dns_transaction_state_to_string(source->state));
1811 goto fail;
1812 }
105e1512
LP
1813
1814 return;
1815
1816fail:
019036a4 1817 t->answer_dnssec_result = DNSSEC_FAILED_AUXILIARY;
105e1512 1818 dns_transaction_complete(t, DNS_TRANSACTION_DNSSEC_FAILED);
547973de
LP
1819}
1820
105e1512
LP
1821static int dns_transaction_validate_dnskey_by_ds(DnsTransaction *t) {
1822 DnsResourceRecord *rr;
1823 int ifindex, r;
1824
1825 assert(t);
1826
1827 /* Add all DNSKEY RRs from the answer that are validated by DS
1828 * RRs from the list of validated keys to the list of
1829 * validated keys. */
1830
1831 DNS_ANSWER_FOREACH_IFINDEX(rr, ifindex, t->answer) {
1832
1833 r = dnssec_verify_dnskey_search(rr, t->validated_keys);
1834 if (r < 0)
1835 return r;
1836 if (r == 0)
1837 continue;
1838
1839 /* If so, the DNSKEY is validated too. */
1840 r = dns_answer_add_extend(&t->validated_keys, rr, ifindex, DNS_ANSWER_AUTHENTICATED);
1841 if (r < 0)
1842 return r;
1843 }
1844
1845 return 0;
1846}
1847
1848static int dns_transaction_requires_rrsig(DnsTransaction *t, DnsResourceRecord *rr) {
56352fe9
LP
1849 int r;
1850
1851 assert(t);
1852 assert(rr);
1853
105e1512
LP
1854 /* Checks if the RR we are looking for must be signed with an
1855 * RRSIG. This is used for positive responses. */
24a5b982 1856
b652d4a2 1857 if (t->scope->dnssec_mode == DNSSEC_NO)
105e1512 1858 return false;
56352fe9 1859
105e1512
LP
1860 if (dns_type_is_pseudo(rr->key->type))
1861 return -EINVAL;
56352fe9 1862
8e54f5d9
LP
1863 r = dns_trust_anchor_lookup_negative(&t->scope->manager->trust_anchor, DNS_RESOURCE_KEY_NAME(rr->key));
1864 if (r < 0)
1865 return r;
1866 if (r > 0)
1867 return false;
1868
105e1512 1869 switch (rr->key->type) {
56352fe9 1870
105e1512
LP
1871 case DNS_TYPE_RRSIG:
1872 /* RRSIGs are the signatures themselves, they need no signing. */
1873 return false;
1874
1875 case DNS_TYPE_SOA:
1876 case DNS_TYPE_NS: {
1877 DnsTransaction *dt;
1878 Iterator i;
1879
b63fca62 1880 /* For SOA or NS RRs we look for a matching DS transaction */
105e1512
LP
1881
1882 SET_FOREACH(dt, t->dnssec_transactions, i) {
1883
1884 if (dt->key->class != rr->key->class)
1885 continue;
1886 if (dt->key->type != DNS_TYPE_DS)
1887 continue;
1888
1889 r = dns_name_equal(DNS_RESOURCE_KEY_NAME(dt->key), DNS_RESOURCE_KEY_NAME(rr->key));
1890 if (r < 0)
1891 return r;
1892 if (r == 0)
1893 continue;
1894
1895 /* We found a DS transactions for the SOA/NS
1896 * RRs we are looking at. If it discovered signed DS
1897 * RRs, then we need to be signed, too. */
1898
097a2517
TA
1899 if (!dt->answer_authenticated)
1900 return false;
105e1512 1901
097a2517 1902 return dns_answer_match_key(dt->answer, dt->key, NULL);
105e1512
LP
1903 }
1904
1905 /* We found nothing that proves this is safe to leave
1906 * this unauthenticated, hence ask inist on
1907 * authentication. */
1908 return true;
1909 }
1910
b63fca62 1911 case DNS_TYPE_DS:
105e1512
LP
1912 case DNS_TYPE_CNAME:
1913 case DNS_TYPE_DNAME: {
1914 const char *parent = NULL;
1915 DnsTransaction *dt;
1916 Iterator i;
1917
b63fca62
LP
1918 /*
1919 * CNAME/DNAME RRs cannot be located at a zone apex, hence look directly for the parent SOA.
1920 *
1921 * DS RRs are signed if the parent is signed, hence also look at the parent SOA
1922 */
105e1512
LP
1923
1924 SET_FOREACH(dt, t->dnssec_transactions, i) {
1925
1926 if (dt->key->class != rr->key->class)
1927 continue;
1928 if (dt->key->type != DNS_TYPE_SOA)
1929 continue;
1930
1931 if (!parent) {
1932 parent = DNS_RESOURCE_KEY_NAME(rr->key);
1933 r = dns_name_parent(&parent);
1934 if (r < 0)
1935 return r;
1936 if (r == 0) {
b63fca62
LP
1937 if (rr->key->type == DNS_TYPE_DS)
1938 return true;
1939
105e1512
LP
1940 /* A CNAME/DNAME without a parent? That's sooo weird. */
1941 log_debug("Transaction %" PRIu16 " claims CNAME/DNAME at root. Refusing.", t->id);
1942 return -EBADMSG;
1943 }
1944 }
1945
1946 r = dns_name_equal(DNS_RESOURCE_KEY_NAME(dt->key), parent);
1947 if (r < 0)
1948 return r;
1949 if (r == 0)
1950 continue;
1951
1952 return t->answer_authenticated;
1953 }
1954
1955 return true;
1956 }
1957
1958 default: {
1959 DnsTransaction *dt;
1960 Iterator i;
1961
b63fca62 1962 /* Any other kind of RR (including DNSKEY/NSEC/NSEC3). Let's see if our SOA lookup was authenticated */
105e1512
LP
1963
1964 SET_FOREACH(dt, t->dnssec_transactions, i) {
1965
1966 if (dt->key->class != rr->key->class)
1967 continue;
1968 if (dt->key->type != DNS_TYPE_SOA)
1969 continue;
1970
1971 r = dns_name_equal(DNS_RESOURCE_KEY_NAME(dt->key), DNS_RESOURCE_KEY_NAME(rr->key));
1972 if (r < 0)
1973 return r;
1974 if (r == 0)
1975 continue;
1976
1977 /* We found the transaction that was supposed to find
1978 * the SOA RR for us. It was successful, but found no
1979 * RR for us. This means we are not at a zone cut. In
1980 * this case, we require authentication if the SOA
1981 * lookup was authenticated too. */
1982 return t->answer_authenticated;
1983 }
1984
1985 return true;
1986 }}
56352fe9
LP
1987}
1988
105e1512
LP
1989static int dns_transaction_requires_nsec(DnsTransaction *t) {
1990 DnsTransaction *dt;
1991 const char *name;
1992 Iterator i;
1993 int r;
56352fe9
LP
1994
1995 assert(t);
1996
105e1512
LP
1997 /* Checks if we need to insist on NSEC/NSEC3 RRs for proving
1998 * this negative reply */
56352fe9 1999
b652d4a2 2000 if (t->scope->dnssec_mode == DNSSEC_NO)
105e1512 2001 return false;
56352fe9 2002
105e1512
LP
2003 if (dns_type_is_pseudo(t->key->type))
2004 return -EINVAL;
2005
8e54f5d9
LP
2006 r = dns_trust_anchor_lookup_negative(&t->scope->manager->trust_anchor, DNS_RESOURCE_KEY_NAME(t->key));
2007 if (r < 0)
2008 return r;
2009 if (r > 0)
2010 return false;
2011
105e1512
LP
2012 name = DNS_RESOURCE_KEY_NAME(t->key);
2013
2014 if (IN_SET(t->key->type, DNS_TYPE_SOA, DNS_TYPE_NS, DNS_TYPE_DS)) {
2015
2016 /* We got a negative reply for this SOA/NS lookup? If
2017 * so, then we are not at a zone apex, and thus should
2018 * look at the result of the parent SOA lookup.
2019 *
2020 * We got a negative reply for this DS lookup? DS RRs
2021 * are signed when their parent zone is signed, hence
2022 * also check the parent SOA in this case. */
2023
2024 r = dns_name_parent(&name);
56352fe9
LP
2025 if (r < 0)
2026 return r;
2027 if (r == 0)
105e1512
LP
2028 return true;
2029 }
2030
2031 /* For all other RRs we check the SOA on the same level to see
2032 * if it's signed. */
2033
2034 SET_FOREACH(dt, t->dnssec_transactions, i) {
2035
2036 if (dt->key->class != t->key->class)
2037 continue;
2038 if (dt->key->type != DNS_TYPE_SOA)
56352fe9
LP
2039 continue;
2040
105e1512 2041 r = dns_name_equal(DNS_RESOURCE_KEY_NAME(dt->key), name);
56352fe9
LP
2042 if (r < 0)
2043 return r;
105e1512
LP
2044 if (r == 0)
2045 continue;
2046
2047 return dt->answer_authenticated;
56352fe9
LP
2048 }
2049
105e1512
LP
2050 /* If in doubt, require NSEC/NSEC3 */
2051 return true;
56352fe9
LP
2052}
2053
94aa7071
LP
2054static int dns_transaction_dnskey_authenticated(DnsTransaction *t, DnsResourceRecord *rr) {
2055 DnsResourceRecord *rrsig;
2056 bool found = false;
2057 int r;
2058
2059 /* Checks whether any of the DNSKEYs used for the RRSIGs for
2060 * the specified RRset is authenticated (i.e. has a matching
2061 * DS RR). */
2062
8e54f5d9
LP
2063 r = dns_trust_anchor_lookup_negative(&t->scope->manager->trust_anchor, DNS_RESOURCE_KEY_NAME(rr->key));
2064 if (r < 0)
2065 return r;
2066 if (r > 0)
2067 return false;
2068
94aa7071
LP
2069 DNS_ANSWER_FOREACH(rrsig, t->answer) {
2070 DnsTransaction *dt;
2071 Iterator i;
2072
2073 r = dnssec_key_match_rrsig(rr->key, rrsig);
2074 if (r < 0)
2075 return r;
2076 if (r == 0)
2077 continue;
2078
2079 SET_FOREACH(dt, t->dnssec_transactions, i) {
2080
2081 if (dt->key->class != rr->key->class)
2082 continue;
2083
2084 if (dt->key->type == DNS_TYPE_DNSKEY) {
2085
2086 r = dns_name_equal(DNS_RESOURCE_KEY_NAME(dt->key), rrsig->rrsig.signer);
2087 if (r < 0)
2088 return r;
2089 if (r == 0)
2090 continue;
2091
2092 /* OK, we found an auxiliary DNSKEY
2093 * lookup. If that lookup is
2094 * authenticated, report this. */
2095
2096 if (dt->answer_authenticated)
2097 return true;
2098
2099 found = true;
2100
2101 } else if (dt->key->type == DNS_TYPE_DS) {
2102
2103 r = dns_name_equal(DNS_RESOURCE_KEY_NAME(dt->key), rrsig->rrsig.signer);
2104 if (r < 0)
2105 return r;
2106 if (r == 0)
2107 continue;
2108
2109 /* OK, we found an auxiliary DS
2110 * lookup. If that lookup is
2111 * authenticated and non-zero, we
2112 * won! */
2113
2114 if (!dt->answer_authenticated)
2115 return false;
2116
2117 return dns_answer_match_key(dt->answer, dt->key, NULL);
2118 }
2119 }
2120 }
2121
2122 return found ? false : -ENXIO;
2123}
2124
b652d4a2
LP
2125static int dns_transaction_known_signed(DnsTransaction *t, DnsResourceRecord *rr) {
2126 assert(t);
2127 assert(rr);
2128
2129 /* We know that the root domain is signed, hence if it appears
2130 * not to be signed, there's a problem with the DNS server */
2131
2132 return rr->key->class == DNS_CLASS_IN &&
2133 dns_name_is_root(DNS_RESOURCE_KEY_NAME(rr->key));
2134}
2135
547973de
LP
2136int dns_transaction_validate_dnssec(DnsTransaction *t) {
2137 _cleanup_(dns_answer_unrefp) DnsAnswer *validated = NULL;
56352fe9 2138 bool dnskeys_finalized = false;
547973de 2139 DnsResourceRecord *rr;
105e1512 2140 DnsAnswerFlags flags;
56352fe9 2141 int r;
547973de
LP
2142
2143 assert(t);
2144
2145 /* We have now collected all DS and DNSKEY RRs in
2146 * t->validated_keys, let's see which RRs we can now
2147 * authenticate with that. */
2148
b652d4a2 2149 if (t->scope->dnssec_mode == DNSSEC_NO)
547973de
LP
2150 return 0;
2151
2152 /* Already validated */
019036a4 2153 if (t->answer_dnssec_result != _DNSSEC_RESULT_INVALID)
547973de
LP
2154 return 0;
2155
105e1512 2156 /* Our own stuff needs no validation */
547973de 2157 if (IN_SET(t->answer_source, DNS_TRANSACTION_ZONE, DNS_TRANSACTION_TRUST_ANCHOR)) {
019036a4 2158 t->answer_dnssec_result = DNSSEC_VALIDATED;
547973de
LP
2159 t->answer_authenticated = true;
2160 return 0;
2161 }
2162
105e1512
LP
2163 /* Cached stuff is not affected by validation. */
2164 if (t->answer_source != DNS_TRANSACTION_NETWORK)
2165 return 0;
2166
b652d4a2
LP
2167 if (t->current_features < DNS_SERVER_FEATURE_LEVEL_DO ||
2168 (t->server && t->server->rrsig_missing)) {
2169 /* The server does not support DNSSEC, or doesn't augment responses with RRSIGs. */
2170 t->answer_dnssec_result = DNSSEC_INCOMPATIBLE_SERVER;
2171 return 0;
2172 }
2173
a5784c49 2174 log_debug("Validating response from transaction %" PRIu16 " (%s).", t->id, dns_transaction_key_string(t));
547973de
LP
2175
2176 /* First see if there are DNSKEYs we already known a validated DS for. */
56352fe9
LP
2177 r = dns_transaction_validate_dnskey_by_ds(t);
2178 if (r < 0)
2179 return r;
547973de
LP
2180
2181 for (;;) {
56352fe9 2182 bool changed = false;
547973de
LP
2183
2184 DNS_ANSWER_FOREACH(rr, t->answer) {
2185 DnssecResult result;
2186
2187 if (rr->key->type == DNS_TYPE_RRSIG)
2188 continue;
2189
2190 r = dnssec_verify_rrset_search(t->answer, rr->key, t->validated_keys, USEC_INFINITY, &result);
2191 if (r < 0)
2192 return r;
2193
7b50eb2e 2194 log_debug("Looking at %s: %s", strna(dns_resource_record_to_string(rr)), dnssec_result_to_string(result));
547973de 2195
56352fe9 2196 if (result == DNSSEC_VALIDATED) {
547973de 2197
547973de
LP
2198 if (rr->key->type == DNS_TYPE_DNSKEY) {
2199 /* If we just validated a
2200 * DNSKEY RRset, then let's
2201 * add these keys to the set
2202 * of validated keys for this
2203 * transaction. */
2204
105e1512 2205 r = dns_answer_copy_by_key(&t->validated_keys, t->answer, rr->key, DNS_ANSWER_AUTHENTICATED);
547973de
LP
2206 if (r < 0)
2207 return r;
0c857028
LP
2208
2209 /* Maybe warn the user that we
2210 * encountered a revoked
2211 * DNSKEY for a key from our
2212 * trust anchor */
2213 r = dns_trust_anchor_check_revoked(&t->scope->manager->trust_anchor, t->answer, rr->key);
2214 if (r < 0)
2215 return r;
547973de
LP
2216 }
2217
105e1512
LP
2218 /* Add the validated RRset to the new
2219 * list of validated RRsets, and
2220 * remove it from the unvalidated
2221 * RRsets. We mark the RRset as
2222 * authenticated and cacheable. */
2223 r = dns_answer_move_by_key(&validated, &t->answer, rr->key, DNS_ANSWER_AUTHENTICATED|DNS_ANSWER_CACHEABLE);
547973de
LP
2224 if (r < 0)
2225 return r;
2226
a150ff5e
LP
2227 t->scope->manager->n_dnssec_secure++;
2228
56352fe9 2229 /* Exit the loop, we dropped something from the answer, start from the beginning */
547973de
LP
2230 changed = true;
2231 break;
2232
56352fe9 2233 } else if (dnskeys_finalized) {
94aa7071 2234
56352fe9
LP
2235 /* If we haven't read all DNSKEYs yet
2236 * a negative result of the validation
2237 * is irrelevant, as there might be
2238 * more DNSKEYs coming. */
547973de 2239
105e1512
LP
2240 if (result == DNSSEC_NO_SIGNATURE) {
2241 r = dns_transaction_requires_rrsig(t, rr);
2242 if (r < 0)
2243 return r;
2244 if (r == 0) {
2245 /* Data does not require signing. In that case, just copy it over,
2246 * but remember that this is by no means authenticated.*/
2247 r = dns_answer_move_by_key(&validated, &t->answer, rr->key, 0);
2248 if (r < 0)
2249 return r;
2250
a150ff5e
LP
2251 t->scope->manager->n_dnssec_insecure++;
2252
105e1512
LP
2253 changed = true;
2254 break;
2255 }
b652d4a2
LP
2256
2257 r = dns_transaction_known_signed(t, rr);
2258 if (r < 0)
2259 return r;
2260 if (r > 0) {
2261 /* This is an RR we know has to be signed. If it isn't this means
2262 * the server is not attaching RRSIGs, hence complain. */
2263
2264 dns_server_packet_rrsig_missing(t->server);
2265
2266 if (t->scope->dnssec_mode == DNSSEC_DOWNGRADE_OK) {
2267
2268 /* Downgrading is OK? If so, just consider the information unsigned */
2269
2270 r = dns_answer_move_by_key(&validated, &t->answer, rr->key, 0);
2271 if (r < 0)
2272 return r;
2273
2274 t->scope->manager->n_dnssec_insecure++;
2275 changed = true;
2276 break;
2277 }
2278
2279 /* Otherwise, fail */
2280 t->answer_dnssec_result = DNSSEC_INCOMPATIBLE_SERVER;
2281 return 0;
2282 }
94aa7071
LP
2283 }
2284
2285 if (IN_SET(result,
2286 DNSSEC_MISSING_KEY,
2287 DNSSEC_SIGNATURE_EXPIRED,
2288 DNSSEC_UNSUPPORTED_ALGORITHM)) {
2289
2290 r = dns_transaction_dnskey_authenticated(t, rr);
2291 if (r < 0 && r != -ENXIO)
2292 return r;
2293 if (r == 0) {
2294 /* The DNSKEY transaction was not authenticated, this means there's
2295 * no DS for this, which means it's OK if no keys are found for this signature. */
2296
2297 r = dns_answer_move_by_key(&validated, &t->answer, rr->key, 0);
2298 if (r < 0)
2299 return r;
2300
a150ff5e
LP
2301 t->scope->manager->n_dnssec_insecure++;
2302
94aa7071
LP
2303 changed = true;
2304 break;
2305 }
105e1512
LP
2306 }
2307
a150ff5e
LP
2308 if (IN_SET(result,
2309 DNSSEC_INVALID,
2310 DNSSEC_SIGNATURE_EXPIRED,
2311 DNSSEC_NO_SIGNATURE,
2312 DNSSEC_UNSUPPORTED_ALGORITHM))
2313 t->scope->manager->n_dnssec_bogus++;
2314 else
2315 t->scope->manager->n_dnssec_indeterminate++;
2316
56352fe9 2317 r = dns_transaction_is_primary_response(t, rr);
547973de
LP
2318 if (r < 0)
2319 return r;
2320 if (r > 0) {
56352fe9
LP
2321 /* This is a primary response
2322 * to our question, and it
2323 * failed validation. That's
2324 * fatal. */
019036a4 2325 t->answer_dnssec_result = result;
547973de
LP
2326 return 0;
2327 }
2328
56352fe9
LP
2329 /* This is just some auxiliary
2330 * data. Just remove the RRset and
2331 * continue. */
547973de
LP
2332 r = dns_answer_remove_by_key(&t->answer, rr->key);
2333 if (r < 0)
2334 return r;
2335
56352fe9 2336 /* Exit the loop, we dropped something from the answer, start from the beginning */
547973de
LP
2337 changed = true;
2338 break;
547973de 2339 }
547973de
LP
2340 }
2341
2342 if (changed)
2343 continue;
2344
56352fe9
LP
2345 if (!dnskeys_finalized) {
2346 /* OK, now we know we have added all DNSKEYs
2347 * we possibly could to our validated
2348 * list. Now run the whole thing once more,
2349 * and strip everything we still cannot
2350 * validate.
2351 */
2352 dnskeys_finalized = true;
2353 continue;
547973de
LP
2354 }
2355
56352fe9 2356 /* We're done */
547973de
LP
2357 break;
2358 }
2359
2360 dns_answer_unref(t->answer);
2361 t->answer = validated;
2362 validated = NULL;
2363
72667f08
LP
2364 /* At this point the answer only contains validated
2365 * RRsets. Now, let's see if it actually answers the question
2366 * we asked. If so, great! If it doesn't, then see if
2367 * NSEC/NSEC3 can prove this. */
105e1512 2368 r = dns_transaction_has_positive_answer(t, &flags);
72667f08 2369 if (r > 0) {
105e1512
LP
2370 /* Yes, it answers the question! */
2371
2372 if (flags & DNS_ANSWER_AUTHENTICATED) {
2373 /* The answer is fully authenticated, yay. */
019036a4 2374 t->answer_dnssec_result = DNSSEC_VALIDATED;
105e1512
LP
2375 t->answer_rcode = DNS_RCODE_SUCCESS;
2376 t->answer_authenticated = true;
2377 } else {
2378 /* The answer is not fully authenticated. */
019036a4 2379 t->answer_dnssec_result = DNSSEC_UNSIGNED;
105e1512
LP
2380 t->answer_authenticated = false;
2381 }
2382
72667f08
LP
2383 } else if (r == 0) {
2384 DnssecNsecResult nr;
ed29bfdc 2385 bool authenticated = false;
72667f08
LP
2386
2387 /* Bummer! Let's check NSEC/NSEC3 */
ed29bfdc 2388 r = dnssec_test_nsec(t->answer, t->key, &nr, &authenticated);
72667f08
LP
2389 if (r < 0)
2390 return r;
2391
2392 switch (nr) {
2393
2394 case DNSSEC_NSEC_NXDOMAIN:
2395 /* NSEC proves the domain doesn't exist. Very good. */
105e1512 2396 log_debug("Proved NXDOMAIN via NSEC/NSEC3 for transaction %u (%s)", t->id, dns_transaction_key_string(t));
019036a4 2397 t->answer_dnssec_result = DNSSEC_VALIDATED;
72667f08 2398 t->answer_rcode = DNS_RCODE_NXDOMAIN;
ed29bfdc 2399 t->answer_authenticated = authenticated;
72667f08
LP
2400 break;
2401
2402 case DNSSEC_NSEC_NODATA:
2403 /* NSEC proves that there's no data here, very good. */
105e1512 2404 log_debug("Proved NODATA via NSEC/NSEC3 for transaction %u (%s)", t->id, dns_transaction_key_string(t));
019036a4 2405 t->answer_dnssec_result = DNSSEC_VALIDATED;
72667f08 2406 t->answer_rcode = DNS_RCODE_SUCCESS;
ed29bfdc 2407 t->answer_authenticated = authenticated;
72667f08
LP
2408 break;
2409
105e1512
LP
2410 case DNSSEC_NSEC_OPTOUT:
2411 /* NSEC3 says the data might not be signed */
2412 log_debug("Data is NSEC3 opt-out via NSEC/NSEC3 for transaction %u (%s)", t->id, dns_transaction_key_string(t));
019036a4 2413 t->answer_dnssec_result = DNSSEC_UNSIGNED;
105e1512
LP
2414 t->answer_authenticated = false;
2415 break;
2416
72667f08
LP
2417 case DNSSEC_NSEC_NO_RR:
2418 /* No NSEC data? Bummer! */
105e1512
LP
2419
2420 r = dns_transaction_requires_nsec(t);
2421 if (r < 0)
2422 return r;
2423 if (r > 0)
019036a4 2424 t->answer_dnssec_result = DNSSEC_NO_SIGNATURE;
105e1512 2425 else {
019036a4 2426 t->answer_dnssec_result = DNSSEC_UNSIGNED;
105e1512
LP
2427 t->answer_authenticated = false;
2428 }
2429
2430 break;
2431
2432 case DNSSEC_NSEC_UNSUPPORTED_ALGORITHM:
2433 /* We don't know the NSEC3 algorithm used? */
019036a4 2434 t->answer_dnssec_result = DNSSEC_UNSUPPORTED_ALGORITHM;
72667f08
LP
2435 break;
2436
2437 case DNSSEC_NSEC_FOUND:
146035b3 2438 case DNSSEC_NSEC_CNAME:
72667f08 2439 /* NSEC says it needs to be there, but we couldn't find it? Bummer! */
019036a4 2440 t->answer_dnssec_result = DNSSEC_NSEC_MISMATCH;
72667f08
LP
2441 break;
2442
2443 default:
2444 assert_not_reached("Unexpected NSEC result.");
2445 }
2446 }
2447
547973de
LP
2448 return 1;
2449}
2450
a5784c49
LP
2451const char *dns_transaction_key_string(DnsTransaction *t) {
2452 assert(t);
2453
2454 if (!t->key_string) {
2455 if (dns_resource_key_to_string(t->key, &t->key_string) < 0)
2456 return "n/a";
2457 }
2458
2459 return strstrip(t->key_string);
2460}
2461
ec2c5e43
LP
2462static const char* const dns_transaction_state_table[_DNS_TRANSACTION_STATE_MAX] = {
2463 [DNS_TRANSACTION_NULL] = "null",
2464 [DNS_TRANSACTION_PENDING] = "pending",
547973de 2465 [DNS_TRANSACTION_VALIDATING] = "validating",
3bbdc31d 2466 [DNS_TRANSACTION_RCODE_FAILURE] = "rcode-failure",
ec2c5e43
LP
2467 [DNS_TRANSACTION_SUCCESS] = "success",
2468 [DNS_TRANSACTION_NO_SERVERS] = "no-servers",
2469 [DNS_TRANSACTION_TIMEOUT] = "timeout",
2470 [DNS_TRANSACTION_ATTEMPTS_MAX_REACHED] = "attempts-max-reached",
2471 [DNS_TRANSACTION_INVALID_REPLY] = "invalid-reply",
2472 [DNS_TRANSACTION_RESOURCES] = "resources",
ac720200 2473 [DNS_TRANSACTION_CONNECTION_FAILURE] = "connection-failure",
ec2c5e43 2474 [DNS_TRANSACTION_ABORTED] = "aborted",
547973de 2475 [DNS_TRANSACTION_DNSSEC_FAILED] = "dnssec-failed",
b2b796b8 2476 [DNS_TRANSACTION_NO_TRUST_ANCHOR] = "no-trust-anchor",
ec2c5e43
LP
2477};
2478DEFINE_STRING_TABLE_LOOKUP(dns_transaction_state, DnsTransactionState);
c3bc53e6
LP
2479
2480static const char* const dns_transaction_source_table[_DNS_TRANSACTION_SOURCE_MAX] = {
2481 [DNS_TRANSACTION_NETWORK] = "network",
2482 [DNS_TRANSACTION_CACHE] = "cache",
2483 [DNS_TRANSACTION_ZONE] = "zone",
0d2cd476 2484 [DNS_TRANSACTION_TRUST_ANCHOR] = "trust-anchor",
c3bc53e6
LP
2485};
2486DEFINE_STRING_TABLE_LOOKUP(dns_transaction_source, DnsTransactionSource);