]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/resolve/resolved-dns-transaction.c
Merge pull request #31811 from yuwata/network-pin-persistent-storage
[thirdparty/systemd.git] / src / resolve / resolved-dns-transaction.c
CommitLineData
db9ecf05 1/* SPDX-License-Identifier: LGPL-2.1-or-later */
ec2c5e43 2
62cc1c55 3#include "sd-messages.h"
beef6a5f 4
ec2c5e43 5#include "af-list.h"
b5efdb8a 6#include "alloc-util.h"
f52e61da 7#include "dns-domain.h"
7cc6ed7b 8#include "errno-list.h"
c3fecddf 9#include "errno-util.h"
3ffd4af2 10#include "fd-util.h"
e2341b6b 11#include "glyph-util.h"
3ffd4af2 12#include "random-util.h"
7778dfff 13#include "resolved-dns-cache.h"
3ffd4af2 14#include "resolved-dns-transaction.h"
6016fcb0 15#include "resolved-dnstls.h"
aedf00a2 16#include "resolved-llmnr.h"
6016fcb0 17#include "string-table.h"
5d67a7ae 18
b214dc0f 19#define TRANSACTIONS_MAX 4096
dc349f5f 20#define TRANSACTION_TCP_TIMEOUT_USEC (10U*USEC_PER_SEC)
b214dc0f 21
dbc4661a
MCO
22/* After how much time to repeat classic DNS requests */
23#define DNS_TIMEOUT_USEC (SD_RESOLVED_QUERY_TIMEOUT_USEC / DNS_TRANSACTION_ATTEMPTS_MAX)
24
c61d2b44
LP
25static void dns_transaction_reset_answer(DnsTransaction *t) {
26 assert(t);
27
28 t->received = dns_packet_unref(t->received);
29 t->answer = dns_answer_unref(t->answer);
30 t->answer_rcode = 0;
41398e87
YW
31 t->answer_ede_rcode = _DNS_EDE_RCODE_INVALID;
32 t->answer_ede_msg = mfree(t->answer_ede_msg);
c61d2b44
LP
33 t->answer_dnssec_result = _DNSSEC_RESULT_INVALID;
34 t->answer_source = _DNS_TRANSACTION_SOURCE_INVALID;
6f055e43 35 t->answer_query_flags = 0;
f5fbe71d 36 t->answer_nsec_ttl = UINT32_MAX;
7cc6ed7b 37 t->answer_errno = 0;
c61d2b44
LP
38}
39
c5b4f861
LP
40static void dns_transaction_flush_dnssec_transactions(DnsTransaction *t) {
41 DnsTransaction *z;
42
43 assert(t);
44
45 while ((z = set_steal_first(t->dnssec_transactions))) {
46 set_remove(z->notify_transactions, t);
35aa04e9 47 set_remove(z->notify_transactions_done, t);
c5b4f861
LP
48 dns_transaction_gc(z);
49 }
50}
51
80710ade
LP
52static void dns_transaction_close_connection(
53 DnsTransaction *t,
54 bool use_graveyard) { /* Set use_graveyard = false when you know the connection is already
55 * dead, for example because you got a connection error back from the
56 * kernel. In that case there's no point in keeping the fd around,
57 * hence don't. */
58 int r;
59
f32f0e57
LP
60 assert(t);
61
b30bf55d
LP
62 if (t->stream) {
63 /* Let's detach the stream from our transaction, in case something else keeps a reference to it. */
98767d75
IT
64 LIST_REMOVE(transactions_by_stream, t->stream->transactions, t);
65
66 /* Remove packet in case it's still in the queue */
67 dns_packet_unref(ordered_set_remove(t->stream->write_queue, t->sent));
68
b30bf55d
LP
69 t->stream = dns_stream_unref(t->stream);
70 }
71
97935302 72 t->dns_udp_event_source = sd_event_source_disable_unref(t->dns_udp_event_source);
80710ade 73
5bc9ea07 74 /* If we have a UDP socket where we sent a packet, but never received one, then add it to the socket
80710ade
LP
75 * graveyard, instead of closing it right away. That way it will stick around for a moment longer,
76 * and the reply we might still get from the server will be eaten up instead of resulting in an ICMP
77 * port unreachable error message. */
78
73780aa8
YW
79 /* Skip the graveyard stuff when we're shutting down, since that requires running event loop.
80 * Note that this is also called from dns_transaction_free(). In that case, scope may be NULL. */
81 if (!t->scope ||
82 !t->scope->manager ||
83 !t->scope->manager->event ||
84 sd_event_get_state(t->scope->manager->event) == SD_EVENT_FINISHED)
ac1b7b9e
FS
85 use_graveyard = false;
86
80710ade
LP
87 if (use_graveyard && t->dns_udp_fd >= 0 && t->sent && !t->received) {
88 r = manager_add_socket_to_graveyard(t->scope->manager, t->dns_udp_fd);
89 if (r < 0)
90 log_debug_errno(r, "Failed to add UDP socket to graveyard, closing immediately: %m");
91 else
92 TAKE_FD(t->dns_udp_fd);
93 }
94
f32f0e57
LP
95 t->dns_udp_fd = safe_close(t->dns_udp_fd);
96}
97
f535705a 98static void dns_transaction_stop_timeout(DnsTransaction *t) {
97cc656c
LP
99 assert(t);
100
97935302 101 t->timeout_event_source = sd_event_source_disable_unref(t->timeout_event_source);
97cc656c
LP
102}
103
ec2c5e43 104DnsTransaction* dns_transaction_free(DnsTransaction *t) {
801ad6a6 105 DnsQueryCandidate *c;
ec2c5e43 106 DnsZoneItem *i;
547973de 107 DnsTransaction *z;
ec2c5e43
LP
108
109 if (!t)
110 return NULL;
111
51e399bc
LP
112 log_debug("Freeing transaction %" PRIu16 ".", t->id);
113
80710ade 114 dns_transaction_close_connection(t, true);
f535705a 115 dns_transaction_stop_timeout(t);
ec2c5e43 116
ec2c5e43 117 dns_packet_unref(t->sent);
c61d2b44 118 dns_transaction_reset_answer(t);
ec2c5e43 119
8300ba21 120 dns_server_unref(t->server);
ec2c5e43
LP
121
122 if (t->scope) {
775ae354
LP
123 if (t->key) {
124 DnsTransaction *first;
125
126 first = hashmap_get(t->scope->transactions_by_key, t->key);
127 LIST_REMOVE(transactions_by_key, first, t);
128 if (first)
129 hashmap_replace(t->scope->transactions_by_key, first->key, first);
130 else
131 hashmap_remove(t->scope->transactions_by_key, t->key);
132 }
ec2c5e43 133
775ae354 134 LIST_REMOVE(transactions_by_scope, t->scope->transactions, t);
ec2c5e43 135
013668db
LP
136 if (t->id != 0)
137 hashmap_remove(t->scope->manager->dns_transactions, UINT_TO_PTR(t->id));
138 }
775ae354 139
547973de 140 while ((c = set_steal_first(t->notify_query_candidates)))
801ad6a6 141 set_remove(c->transactions, t);
547973de 142 set_free(t->notify_query_candidates);
801ad6a6 143
35aa04e9
LP
144 while ((c = set_steal_first(t->notify_query_candidates_done)))
145 set_remove(c->transactions, t);
146 set_free(t->notify_query_candidates_done);
147
547973de 148 while ((i = set_steal_first(t->notify_zone_items)))
ec2c5e43 149 i->probe_transaction = NULL;
547973de
LP
150 set_free(t->notify_zone_items);
151
35aa04e9
LP
152 while ((i = set_steal_first(t->notify_zone_items_done)))
153 i->probe_transaction = NULL;
154 set_free(t->notify_zone_items_done);
155
547973de
LP
156 while ((z = set_steal_first(t->notify_transactions)))
157 set_remove(z->dnssec_transactions, t);
158 set_free(t->notify_transactions);
159
35aa04e9
LP
160 while ((z = set_steal_first(t->notify_transactions_done)))
161 set_remove(z->dnssec_transactions, t);
162 set_free(t->notify_transactions_done);
163
c5b4f861 164 dns_transaction_flush_dnssec_transactions(t);
547973de
LP
165 set_free(t->dnssec_transactions);
166
167 dns_answer_unref(t->validated_keys);
97cc656c 168 dns_resource_key_unref(t->key);
775ae354 169 dns_packet_unref(t->bypass);
97cc656c 170
6b430fdb 171 return mfree(t);
ec2c5e43
LP
172}
173
174DEFINE_TRIVIAL_CLEANUP_FUNC(DnsTransaction*, dns_transaction_free);
175
1f388301 176DnsTransaction* dns_transaction_gc(DnsTransaction *t) {
ec2c5e43
LP
177 assert(t);
178
1f388301
ZJS
179 /* Returns !NULL if we can't gc yet. */
180
ec2c5e43 181 if (t->block_gc > 0)
1f388301 182 return t;
ec2c5e43 183
547973de 184 if (set_isempty(t->notify_query_candidates) &&
35aa04e9 185 set_isempty(t->notify_query_candidates_done) &&
547973de 186 set_isempty(t->notify_zone_items) &&
35aa04e9
LP
187 set_isempty(t->notify_zone_items_done) &&
188 set_isempty(t->notify_transactions) &&
1f388301
ZJS
189 set_isempty(t->notify_transactions_done))
190 return dns_transaction_free(t);
51e399bc 191
1f388301 192 return t;
ec2c5e43
LP
193}
194
4dd15077
LP
195static uint16_t pick_new_id(Manager *m) {
196 uint16_t new_id;
197
4ea8b443
ZJS
198 /* Find a fresh, unused transaction id. Note that this loop is bounded because there's a limit on the
199 * number of transactions, and it's much lower than the space of IDs. */
4dd15077
LP
200
201 assert_cc(TRANSACTIONS_MAX < 0xFFFF);
202
203 do
204 random_bytes(&new_id, sizeof(new_id));
205 while (new_id == 0 ||
206 hashmap_get(m->dns_transactions, UINT_TO_PTR(new_id)));
207
208 return new_id;
209}
210
775ae354
LP
211static int key_ok(
212 DnsScope *scope,
213 DnsResourceKey *key) {
ec2c5e43 214
9eae2bf3 215 /* Don't allow looking up invalid or pseudo RRs */
c463eb78 216 if (!dns_type_is_valid_query(key->type))
9eae2bf3 217 return -EINVAL;
d0129ddb
LP
218 if (dns_type_is_obsolete(key->type))
219 return -EOPNOTSUPP;
9eae2bf3
LP
220
221 /* We only support the IN class */
4c701096 222 if (!IN_SET(key->class, DNS_CLASS_IN, DNS_CLASS_ANY))
9eae2bf3
LP
223 return -EOPNOTSUPP;
224
775ae354
LP
225 /* Don't allows DNSSEC RRs to be looked up via LLMNR/mDNS. They don't really make sense
226 * there, and it speeds up our queries if we refuse this early */
227 if (scope->protocol != DNS_PROTOCOL_DNS &&
228 dns_type_is_dnssec(key->type))
229 return -EOPNOTSUPP;
230
231 return 0;
232}
233
234int dns_transaction_new(
235 DnsTransaction **ret,
236 DnsScope *s,
237 DnsResourceKey *key,
238 DnsPacket *bypass,
239 uint64_t query_flags) {
240
241 _cleanup_(dns_transaction_freep) DnsTransaction *t = NULL;
242 int r;
243
244 assert(ret);
245 assert(s);
246
247 if (key) {
248 assert(!bypass);
249
250 r = key_ok(s, key);
251 if (r < 0)
252 return r;
253 } else {
254 DnsResourceKey *qk;
255 assert(bypass);
256
257 r = dns_packet_validate_query(bypass);
258 if (r < 0)
259 return r;
260
261 DNS_QUESTION_FOREACH(qk, bypass->question) {
262 r = key_ok(s, qk);
263 if (r < 0)
264 return r;
265 }
266 }
267
b214dc0f
LP
268 if (hashmap_size(s->manager->dns_transactions) >= TRANSACTIONS_MAX)
269 return -EBUSY;
270
d5099efc 271 r = hashmap_ensure_allocated(&s->manager->dns_transactions, NULL);
ec2c5e43
LP
272 if (r < 0)
273 return r;
274
775ae354
LP
275 if (key) {
276 r = hashmap_ensure_allocated(&s->transactions_by_key, &dns_resource_key_hash_ops);
277 if (r < 0)
278 return r;
279 }
da0c630e 280
1ed31408 281 t = new(DnsTransaction, 1);
ec2c5e43
LP
282 if (!t)
283 return -ENOMEM;
284
1ed31408 285 *t = (DnsTransaction) {
254d1313 286 .dns_udp_fd = -EBADF,
1ed31408
LP
287 .answer_source = _DNS_TRANSACTION_SOURCE_INVALID,
288 .answer_dnssec_result = _DNSSEC_RESULT_INVALID,
9ca133e9 289 .answer_ede_rcode = _DNS_EDE_RCODE_INVALID,
f5fbe71d 290 .answer_nsec_ttl = UINT32_MAX,
1ed31408 291 .key = dns_resource_key_ref(key),
775ae354
LP
292 .query_flags = query_flags,
293 .bypass = dns_packet_ref(bypass),
1ed31408 294 .current_feature_level = _DNS_SERVER_FEATURE_LEVEL_INVALID,
1ed4e584 295 .clamp_feature_level_servfail = _DNS_SERVER_FEATURE_LEVEL_INVALID,
1ed31408
LP
296 .id = pick_new_id(s->manager),
297 };
ec2c5e43
LP
298
299 r = hashmap_put(s->manager->dns_transactions, UINT_TO_PTR(t->id), t);
300 if (r < 0) {
301 t->id = 0;
302 return r;
303 }
304
775ae354
LP
305 if (t->key) {
306 DnsTransaction *first;
307
308 first = hashmap_get(s->transactions_by_key, t->key);
309 LIST_PREPEND(transactions_by_key, first, t);
310
311 r = hashmap_replace(s->transactions_by_key, first->key, first);
312 if (r < 0) {
313 LIST_REMOVE(transactions_by_key, first, t);
314 return r;
315 }
da0c630e
LP
316 }
317
f9ebb22a 318 LIST_PREPEND(transactions_by_scope, s->transactions, t);
ec2c5e43
LP
319 t->scope = s;
320
313cefa1 321 s->manager->n_transactions_total++;
a150ff5e 322
ec2c5e43
LP
323 if (ret)
324 *ret = t;
325
775ae354 326 TAKE_PTR(t);
ec2c5e43
LP
327 return 0;
328}
329
4dd15077
LP
330static void dns_transaction_shuffle_id(DnsTransaction *t) {
331 uint16_t new_id;
332 assert(t);
333
334 /* Pick a new ID for this transaction. */
335
336 new_id = pick_new_id(t->scope->manager);
337 assert_se(hashmap_remove_and_put(t->scope->manager->dns_transactions, UINT_TO_PTR(t->id), UINT_TO_PTR(new_id), t) >= 0);
338
339 log_debug("Transaction %" PRIu16 " is now %" PRIu16 ".", t->id, new_id);
340 t->id = new_id;
341
342 /* Make sure we generate a new packet with the new ID */
343 t->sent = dns_packet_unref(t->sent);
344}
345
ec2c5e43 346static void dns_transaction_tentative(DnsTransaction *t, DnsPacket *p) {
202b76ae 347 char key_str[DNS_RESOURCE_KEY_STRING_MAX];
ec2c5e43 348 DnsZoneItem *z;
ec2c5e43
LP
349
350 assert(t);
351 assert(p);
94378145 352 assert(t->scope->protocol == DNS_PROTOCOL_LLMNR);
ec2c5e43 353
94378145 354 if (manager_packet_from_local_address(t->scope->manager, p) != 0)
ec2c5e43
LP
355 return;
356
a5784c49
LP
357 log_debug("Transaction %" PRIu16 " for <%s> on scope %s on %s/%s got tentative packet from %s.",
358 t->id,
42df9532 359 dns_resource_key_to_string(dns_transaction_key(t), key_str, sizeof key_str),
ec2c5e43 360 dns_protocol_to_string(t->scope->protocol),
6ff79f76 361 t->scope->link ? t->scope->link->ifname : "*",
202b76ae 362 af_to_name_short(t->scope->family),
84dbb3fd 363 IN_ADDR_TO_STRING(p->family, &p->sender));
ec2c5e43 364
a4076574
LP
365 /* RFC 4795, Section 4.1 says that the peer with the
366 * lexicographically smaller IP address loses */
4d91eec4
LP
367 if (memcmp(&p->sender, &p->destination, FAMILY_ADDRESS_SIZE(p->family)) >= 0) {
368 log_debug("Peer has lexicographically larger IP address and thus lost in the conflict.");
a4076574
LP
369 return;
370 }
371
4d91eec4 372 log_debug("We have the lexicographically larger IP address and thus lost in the conflict.");
a4076574 373
ec2c5e43 374 t->block_gc++;
35aa04e9 375
547973de 376 while ((z = set_first(t->notify_zone_items))) {
3ef64445
LP
377 /* First, make sure the zone item drops the reference
378 * to us */
379 dns_zone_item_probe_stop(z);
380
381 /* Secondly, report this as conflict, so that we might
382 * look for a different hostname */
ec2c5e43 383 dns_zone_item_conflict(z);
3ef64445 384 }
ec2c5e43
LP
385 t->block_gc--;
386
387 dns_transaction_gc(t);
388}
389
390void dns_transaction_complete(DnsTransaction *t, DnsTransactionState state) {
801ad6a6 391 DnsQueryCandidate *c;
ec2c5e43 392 DnsZoneItem *z;
547973de 393 DnsTransaction *d;
7cc6ed7b 394 const char *st;
202b76ae 395 char key_str[DNS_RESOURCE_KEY_STRING_MAX];
ec2c5e43
LP
396
397 assert(t);
547973de 398 assert(!DNS_TRANSACTION_IS_LIVE(state));
e56187ca 399
202b76ae 400 if (state == DNS_TRANSACTION_DNSSEC_FAILED) {
42df9532 401 dns_resource_key_to_string(dns_transaction_key(t), key_str, sizeof key_str);
202b76ae 402
f61dfddb 403 log_struct(LOG_NOTICE,
2b044526 404 "MESSAGE_ID=" SD_MESSAGE_DNSSEC_FAILURE_STR,
92663a5e
ZJS
405 LOG_MESSAGE("DNSSEC validation failed for question %s: %s",
406 key_str, dnssec_result_to_string(t->answer_dnssec_result)),
f61dfddb 407 "DNS_TRANSACTION=%" PRIu16, t->id,
202b76ae 408 "DNS_QUESTION=%s", key_str,
f61dfddb 409 "DNSSEC_RESULT=%s", dnssec_result_to_string(t->answer_dnssec_result),
8aa5afd2 410 "DNS_SERVER=%s", strna(dns_server_string_full(t->server)),
a1230ff9 411 "DNS_SERVER_FEATURE_LEVEL=%s", dns_server_feature_level_to_string(t->server->possible_feature_level));
202b76ae 412 }
f61dfddb 413
ec2c5e43
LP
414 /* Note that this call might invalidate the query. Callers
415 * should hence not attempt to access the query or transaction
416 * after calling this function. */
417
7cc6ed7b
LP
418 if (state == DNS_TRANSACTION_ERRNO)
419 st = errno_to_name(t->answer_errno);
420 else
421 st = dns_transaction_state_to_string(state);
422
43fc4baa 423 log_debug("%s transaction %" PRIu16 " for <%s> on scope %s on %s/%s now complete with <%s> from %s (%s; %s).",
775ae354 424 t->bypass ? "Bypass" : "Regular",
a5784c49 425 t->id,
42df9532 426 dns_resource_key_to_string(dns_transaction_key(t), key_str, sizeof key_str),
ec2c5e43 427 dns_protocol_to_string(t->scope->protocol),
6ff79f76 428 t->scope->link ? t->scope->link->ifname : "*",
202b76ae 429 af_to_name_short(t->scope->family),
7cc6ed7b 430 st,
a5784c49 431 t->answer_source < 0 ? "none" : dns_transaction_source_to_string(t->answer_source),
775ae354 432 FLAGS_SET(t->query_flags, SD_RESOLVED_NO_VALIDATE) ? "not validated" :
43fc4baa
LP
433 (FLAGS_SET(t->answer_query_flags, SD_RESOLVED_AUTHENTICATED) ? "authenticated" : "unsigned"),
434 FLAGS_SET(t->answer_query_flags, SD_RESOLVED_CONFIDENTIAL) ? "confidential" : "non-confidential");
ec2c5e43
LP
435
436 t->state = state;
437
80710ade 438 dns_transaction_close_connection(t, true);
f535705a 439 dns_transaction_stop_timeout(t);
ec2c5e43
LP
440
441 /* Notify all queries that are interested, but make sure the
442 * transaction isn't freed while we are still looking at it */
443 t->block_gc++;
f7014757 444
35aa04e9 445 SET_FOREACH_MOVE(c, t->notify_query_candidates_done, t->notify_query_candidates)
547973de 446 dns_query_candidate_notify(c);
35aa04e9 447 SWAP_TWO(t->notify_query_candidates, t->notify_query_candidates_done);
ec2c5e43 448
35aa04e9
LP
449 SET_FOREACH_MOVE(z, t->notify_zone_items_done, t->notify_zone_items)
450 dns_zone_item_notify(z);
451 SWAP_TWO(t->notify_zone_items, t->notify_zone_items_done);
8d67e72c 452 if (t->probing && t->state == DNS_TRANSACTION_ATTEMPTS_MAX_REACHED)
1a63fc54 453 (void) dns_scope_announce(t->scope, false);
f7014757 454
35aa04e9
LP
455 SET_FOREACH_MOVE(d, t->notify_transactions_done, t->notify_transactions)
456 dns_transaction_notify(d, t);
457 SWAP_TWO(t->notify_transactions, t->notify_transactions_done);
f7014757
LP
458
459 t->block_gc--;
ec2c5e43
LP
460 dns_transaction_gc(t);
461}
462
fd8a3017
LP
463static void dns_transaction_complete_errno(DnsTransaction *t, int error) {
464 assert(t);
465 assert(error != 0);
466
467 t->answer_errno = abs(error);
468 dns_transaction_complete(t, DNS_TRANSACTION_ERRNO);
469}
470
519ef046
LP
471static int dns_transaction_pick_server(DnsTransaction *t) {
472 DnsServer *server;
473
474 assert(t);
475 assert(t->scope->protocol == DNS_PROTOCOL_DNS);
476
d001e0a3
LP
477 /* Pick a DNS server and a feature level for it. */
478
519ef046
LP
479 server = dns_scope_get_dns_server(t->scope);
480 if (!server)
481 return -ESRCH;
482
d001e0a3
LP
483 /* If we changed the server invalidate the feature level clamping, as the new server might have completely
484 * different properties. */
4aa37ad3 485 if (server != t->server)
1ed4e584 486 t->clamp_feature_level_servfail = _DNS_SERVER_FEATURE_LEVEL_INVALID;
d001e0a3 487
274b8748 488 t->current_feature_level = dns_server_possible_feature_level(server);
519ef046 489
d001e0a3 490 /* Clamp the feature level if that is requested. */
1ed4e584
LP
491 if (t->clamp_feature_level_servfail != _DNS_SERVER_FEATURE_LEVEL_INVALID &&
492 t->current_feature_level > t->clamp_feature_level_servfail)
493 t->current_feature_level = t->clamp_feature_level_servfail;
d001e0a3
LP
494
495 log_debug("Using feature level %s for transaction %u.", dns_server_feature_level_to_string(t->current_feature_level), t->id);
496
519ef046
LP
497 if (server == t->server)
498 return 0;
499
500 dns_server_unref(t->server);
501 t->server = dns_server_ref(server);
502
b3a9d980 503 t->n_picked_servers++;
44db02d0 504
8aa5afd2 505 log_debug("Using DNS server %s for transaction %u.", strna(dns_server_string_full(t->server)), t->id);
d001e0a3 506
519ef046
LP
507 return 1;
508}
509
d001e0a3 510static void dns_transaction_retry(DnsTransaction *t, bool next_server) {
8d10d620
LP
511 int r;
512
513 assert(t);
514
7ef863a7
LP
515 /* Retries the transaction as it is, possibly on a different server */
516
ca55fb88 517 if (next_server && t->scope->protocol == DNS_PROTOCOL_DNS)
7ef863a7
LP
518 log_debug("Retrying transaction %" PRIu16 ", after switching servers.", t->id);
519 else
520 log_debug("Retrying transaction %" PRIu16 ".", t->id);
8d10d620
LP
521
522 /* Before we try again, switch to a new server. */
d001e0a3 523 if (next_server)
5e8bc852 524 dns_scope_next_dns_server(t->scope, t->server);
8d10d620
LP
525
526 r = dns_transaction_go(t);
fd8a3017
LP
527 if (r < 0)
528 dns_transaction_complete_errno(t, r);
8d10d620
LP
529}
530
9147b591
LP
531static bool dns_transaction_limited_retry(DnsTransaction *t) {
532 assert(t);
533
534 /* If we haven't tried all different servers yet, let's try again with a different server */
535
536 if (t->n_picked_servers >= dns_scope_get_n_dns_servers(t->scope))
537 return false;
538
539 dns_transaction_retry(t, /* next_server= */ true);
540 return true;
541}
542
c02cf2f4 543static int dns_transaction_maybe_restart(DnsTransaction *t) {
5278bbfe
LP
544 int r;
545
c02cf2f4
LP
546 assert(t);
547
9147b591
LP
548 /* Restarts the transaction, under a new ID if the feature level of the server changed since we first
549 * tried, without changing DNS server. Returns > 0 if the transaction was restarted, 0 if not. */
5278bbfe 550
c02cf2f4
LP
551 if (!t->server)
552 return 0;
553
554 if (t->current_feature_level <= dns_server_possible_feature_level(t->server))
555 return 0;
556
557 /* The server's current feature level is lower than when we sent the original query. We learnt something from
558 the response or possibly an auxiliary DNSSEC response that we didn't know before. We take that as reason to
559 restart the whole transaction. This is a good idea to deal with servers that respond rubbish if we include
560 OPT RR or DO bit. One of these cases is documented here, for example:
561 https://open.nlnetlabs.nl/pipermail/dnssec-trigger/2014-November/000376.html */
562
4dd15077
LP
563 log_debug("Server feature level is now lower than when we began our transaction. Restarting with new ID.");
564 dns_transaction_shuffle_id(t);
5278bbfe
LP
565
566 r = dns_transaction_go(t);
567 if (r < 0)
568 return r;
569
570 return 1;
c02cf2f4
LP
571}
572
98767d75
IT
573static void on_transaction_stream_error(DnsTransaction *t, int error) {
574 assert(t);
ec2c5e43 575
80710ade 576 dns_transaction_close_connection(t, true);
ec2c5e43 577
a1a3f73a 578 if (ERRNO_IS_DISCONNECT(error)) {
0791110f
LP
579 if (t->scope->protocol == DNS_PROTOCOL_LLMNR) {
580 /* If the LLMNR/TCP connection failed, the host doesn't support LLMNR, and we cannot answer the
581 * question on this scope. */
582 dns_transaction_complete(t, DNS_TRANSACTION_NOT_FOUND);
daab72ea 583 return;
0791110f
LP
584 }
585
d001e0a3 586 dns_transaction_retry(t, true);
daab72ea 587 return;
ac720200 588 }
fd8a3017
LP
589 if (error != 0)
590 dns_transaction_complete_errno(t, error);
98767d75
IT
591}
592
43fc4baa
LP
593static int dns_transaction_on_stream_packet(DnsTransaction *t, DnsStream *s, DnsPacket *p) {
594 bool encrypted;
595
98767d75 596 assert(t);
43fc4baa 597 assert(s);
98767d75
IT
598 assert(p);
599
43fc4baa
LP
600 encrypted = s->encrypted;
601
80710ade 602 dns_transaction_close_connection(t, true);
ec2c5e43 603
a4076574 604 if (dns_packet_validate_reply(p) <= 0) {
a20b9592 605 log_debug("Invalid TCP reply packet.");
a4076574
LP
606 dns_transaction_complete(t, DNS_TRANSACTION_INVALID_REPLY);
607 return 0;
608 }
609
610 dns_scope_check_conflicts(t->scope, p);
611
ec2c5e43 612 t->block_gc++;
43fc4baa 613 dns_transaction_process_reply(t, p, encrypted);
ec2c5e43
LP
614 t->block_gc--;
615
519ef046
LP
616 /* If the response wasn't useful, then complete the transition
617 * now. After all, we are the worst feature set now with TCP
618 * sockets, and there's really no point in retrying. */
ec2c5e43
LP
619 if (t->state == DNS_TRANSACTION_PENDING)
620 dns_transaction_complete(t, DNS_TRANSACTION_INVALID_REPLY);
598f44bd
LP
621 else
622 dns_transaction_gc(t);
ec2c5e43
LP
623
624 return 0;
625}
626
98767d75 627static int on_stream_complete(DnsStream *s, int error) {
7172e4ee 628 assert(s);
98767d75
IT
629
630 if (ERRNO_IS_DISCONNECT(error) && s->protocol != DNS_PROTOCOL_LLMNR) {
98767d75
IT
631 log_debug_errno(error, "Connection failure for DNS TCP stream: %m");
632
633 if (s->transactions) {
97d5d905
LP
634 DnsTransaction *t;
635
98767d75 636 t = s->transactions;
3da3cdd5 637 dns_server_packet_lost(t->server, IPPROTO_TCP, t->current_feature_level);
98767d75
IT
638 }
639 }
640
3db1e6a8
YW
641 if (error != 0) {
642 /* First, detach the stream from the server. Otherwise, transactions attached to this stream
643 * may be restarted by on_transaction_stream_error() below with this stream. */
644 dns_stream_detach(s);
645
646 /* Do not use LIST_FOREACH() here, as
647 * on_transaction_stream_error()
648 * -> dns_transaction_complete_errno()
649 * -> dns_transaction_free()
650 * may free multiple transactions in the list. */
651 DnsTransaction *t;
652 while ((t = s->transactions))
98767d75 653 on_transaction_stream_error(t, error);
3db1e6a8 654 }
98767d75 655
97d5d905 656 return 0;
98767d75
IT
657}
658
624f907e 659static int on_stream_packet(DnsStream *s, DnsPacket *p) {
98767d75
IT
660 DnsTransaction *t;
661
aa337a5e 662 assert(s);
624f907e
YW
663 assert(s->manager);
664 assert(p);
98767d75
IT
665
666 t = hashmap_get(s->manager->dns_transactions, UINT_TO_PTR(DNS_PACKET_ID(p)));
b52eac20
LP
667 if (t && t->stream == s) /* Validate that the stream we got this on actually is the stream the
668 * transaction was using. */
43fc4baa 669 return dns_transaction_on_stream_packet(t, s, p);
98767d75 670
8227cfa1 671 /* Ignore incorrect transaction id as an old transaction can have been canceled. */
30f9e0bf 672 log_debug("Received unexpected TCP reply packet with id %" PRIu16 ", ignoring.", DNS_PACKET_ID(p));
aa337a5e 673 return 0;
98767d75
IT
674}
675
da9de738 676static uint16_t dns_transaction_port(DnsTransaction *t) {
775ae354
LP
677 assert(t);
678
da9de738
YW
679 if (t->server->port > 0)
680 return t->server->port;
775ae354 681
da9de738 682 return DNS_SERVER_FEATURE_LEVEL_IS_TLS(t->current_feature_level) ? 853 : 53;
ec962fba
LP
683}
684
98767d75 685static int dns_transaction_emit_tcp(DnsTransaction *t) {
e1158539 686 usec_t stream_timeout_usec = DNS_STREAM_DEFAULT_TIMEOUT_USEC;
98767d75 687 _cleanup_(dns_stream_unrefp) DnsStream *s = NULL;
254d1313 688 _cleanup_close_ int fd = -EBADF;
91ccab1e 689 union sockaddr_union sa;
652ba568 690 DnsStreamType type;
ec2c5e43
LP
691 int r;
692
693 assert(t);
775ae354 694 assert(t->sent);
ec2c5e43 695
80710ade 696 dns_transaction_close_connection(t, true);
ec2c5e43 697
106784eb 698 switch (t->scope->protocol) {
519ef046 699
106784eb 700 case DNS_PROTOCOL_DNS:
519ef046
LP
701 r = dns_transaction_pick_server(t);
702 if (r < 0)
703 return r;
704
49ef064c
LP
705 if (manager_server_is_stub(t->scope->manager, t->server))
706 return -ELOOP;
707
775ae354
LP
708 if (!t->bypass) {
709 if (!dns_server_dnssec_supported(t->server) && dns_type_is_dnssec(dns_transaction_key(t)->type))
710 return -EOPNOTSUPP;
91adc4db 711
775ae354
LP
712 r = dns_server_adjust_opt(t->server, t->sent, t->current_feature_level);
713 if (r < 0)
714 return r;
715 }
519ef046 716
5d67a7ae 717 if (t->server->stream && (DNS_SERVER_FEATURE_LEVEL_IS_TLS(t->current_feature_level) == t->server->stream->encrypted))
98767d75
IT
718 s = dns_stream_ref(t->server->stream);
719 else
da9de738 720 fd = dns_scope_socket_tcp(t->scope, AF_UNSPEC, NULL, t->server, dns_transaction_port(t), &sa);
98767d75 721
e1158539
LP
722 /* Lower timeout in DNS-over-TLS opportunistic mode. In environments where DoT is blocked
723 * without ICMP response overly long delays when contacting DoT servers are nasty, in
724 * particular if multiple DNS servers are defined which we try in turn and all are
725 * blocked. Hence, substantially lower the timeout in that case. */
726 if (DNS_SERVER_FEATURE_LEVEL_IS_TLS(t->current_feature_level) &&
727 dns_server_get_dns_over_tls_mode(t->server) == DNS_OVER_TLS_OPPORTUNISTIC)
728 stream_timeout_usec = DNS_STREAM_OPPORTUNISTIC_TLS_TIMEOUT_USEC;
729
652ba568 730 type = DNS_STREAM_LOOKUP;
106784eb 731 break;
ec2c5e43 732
106784eb 733 case DNS_PROTOCOL_LLMNR:
a8f6397f 734 /* When we already received a reply to this (but it was truncated), send to its sender address */
ec2c5e43 735 if (t->received)
91ccab1e 736 fd = dns_scope_socket_tcp(t->scope, t->received->family, &t->received->sender, NULL, t->received->sender_port, &sa);
ec2c5e43
LP
737 else {
738 union in_addr_union address;
a7f7d1bd 739 int family = AF_UNSPEC;
ec2c5e43
LP
740
741 /* Otherwise, try to talk to the owner of a
742 * the IP address, in case this is a reverse
743 * PTR lookup */
f52e61da 744
42df9532 745 r = dns_name_address(dns_resource_key_name(dns_transaction_key(t)), &family, &address);
ec2c5e43
LP
746 if (r < 0)
747 return r;
748 if (r == 0)
749 return -EINVAL;
9e08a6e0 750 if (family != t->scope->family)
9318cdd3 751 return -ESRCH;
ec2c5e43 752
91ccab1e 753 fd = dns_scope_socket_tcp(t->scope, family, &address, NULL, LLMNR_PORT, &sa);
ec2c5e43 754 }
106784eb 755
652ba568 756 type = DNS_STREAM_LLMNR_SEND;
106784eb
DM
757 break;
758
759 default:
ec2c5e43 760 return -EAFNOSUPPORT;
106784eb 761 }
ec2c5e43 762
98767d75
IT
763 if (!s) {
764 if (fd < 0)
765 return fd;
ec2c5e43 766
18230451
YW
767 r = dns_stream_new(t->scope->manager, &s, type, t->scope->protocol, fd, &sa,
768 on_stream_packet, on_stream_complete, stream_timeout_usec);
98767d75
IT
769 if (r < 0)
770 return r;
771
254d1313 772 fd = -EBADF;
98767d75 773
56ddbf10 774#if ENABLE_DNS_OVER_TLS
199dda9c
LP
775 if (t->scope->protocol == DNS_PROTOCOL_DNS &&
776 DNS_SERVER_FEATURE_LEVEL_IS_TLS(t->current_feature_level)) {
777
b02a7e1a 778 assert(t->server);
6016fcb0 779 r = dnstls_stream_connect_tls(s, t->server);
5d67a7ae
IT
780 if (r < 0)
781 return r;
782 }
783#endif
784
19feb28f 785 if (t->server) {
904dcaf9 786 dns_server_unref_stream(t->server);
19feb28f 787 s->server = dns_server_ref(t->server);
8227cfa1 788 t->server->stream = dns_stream_ref(s);
19feb28f
IT
789 }
790
98767d75
IT
791 /* The interface index is difficult to determine if we are
792 * connecting to the local host, hence fill this in right away
793 * instead of determining it from the socket */
794 s->ifindex = dns_scope_ifindex(t->scope);
795 }
796
797 t->stream = TAKE_PTR(s);
798 LIST_PREPEND(transactions_by_stream, t->stream->transactions, t);
ec2c5e43
LP
799
800 r = dns_stream_write_packet(t->stream, t->sent);
801 if (r < 0) {
80710ade 802 dns_transaction_close_connection(t, /* use_graveyard= */ false);
ec2c5e43
LP
803 return r;
804 }
805
519ef046
LP
806 dns_transaction_reset_answer(t);
807
cbe4216d
LP
808 t->tried_stream = true;
809
ec2c5e43
LP
810 return 0;
811}
812
547973de 813static void dns_transaction_cache_answer(DnsTransaction *t) {
547973de
LP
814 assert(t);
815
816 /* For mDNS we cache whenever we get the packet, rather than
817 * in each transaction. */
818 if (!IN_SET(t->scope->protocol, DNS_PROTOCOL_DNS, DNS_PROTOCOL_LLMNR))
819 return;
820
ceeddf79 821 /* Caching disabled? */
37d7a7d9 822 if (t->scope->manager->enable_cache == DNS_CACHE_MODE_NO)
ceeddf79
MP
823 return;
824
775ae354
LP
825 /* If validation is turned off for this transaction, but DNSSEC is on, then let's not cache this */
826 if (FLAGS_SET(t->query_flags, SD_RESOLVED_NO_VALIDATE) && t->scope->dnssec_mode != DNSSEC_NO)
827 return;
828
6d8325f6
PS
829 /* Packet from localhost? */
830 if (!t->scope->manager->cache_from_localhost &&
831 in_addr_is_localhost(t->received->family, &t->received->sender) != 0)
547973de
LP
832 return;
833
547973de 834 dns_cache_put(&t->scope->cache,
37d7a7d9 835 t->scope->manager->enable_cache,
a78049fc 836 t->scope->protocol,
42df9532 837 dns_transaction_key(t),
547973de
LP
838 t->answer_rcode,
839 t->answer,
775ae354 840 DNS_PACKET_CD(t->received) ? t->received : NULL, /* only cache full packets with CD on,
7227dd81 841 * since our use case for caching them
775ae354
LP
842 * is "bypass" mode which is only
843 * enabled for CD packets. */
6f055e43 844 t->answer_query_flags,
775ae354 845 t->answer_dnssec_result,
d3760be0 846 t->answer_nsec_ttl,
547973de 847 t->received->family,
5ed91481
KV
848 &t->received->sender,
849 t->scope->manager->stale_retention_usec);
547973de
LP
850}
851
105e1512
LP
852static bool dns_transaction_dnssec_is_live(DnsTransaction *t) {
853 DnsTransaction *dt;
105e1512
LP
854
855 assert(t);
856
90e74a66 857 SET_FOREACH(dt, t->dnssec_transactions)
105e1512
LP
858 if (DNS_TRANSACTION_IS_LIVE(dt->state))
859 return true;
860
861 return false;
862}
863
942eb2e7
LP
864static int dns_transaction_dnssec_ready(DnsTransaction *t) {
865 DnsTransaction *dt;
e30a62bf 866 int r;
942eb2e7
LP
867
868 assert(t);
869
870 /* Checks whether the auxiliary DNSSEC transactions of our transaction have completed, or are still
871 * ongoing. Returns 0, if we aren't ready for the DNSSEC validation, positive if we are. */
872
90e74a66 873 SET_FOREACH(dt, t->dnssec_transactions) {
942eb2e7
LP
874
875 switch (dt->state) {
876
877 case DNS_TRANSACTION_NULL:
878 case DNS_TRANSACTION_PENDING:
879 case DNS_TRANSACTION_VALIDATING:
880 /* Still ongoing */
881 return 0;
882
883 case DNS_TRANSACTION_RCODE_FAILURE:
b3c6b00a 884 if (!IN_SET(dt->answer_rcode, DNS_RCODE_NXDOMAIN, DNS_RCODE_SERVFAIL)) {
0d609349 885 log_debug("Auxiliary DNSSEC RR query failed with rcode=%s.", FORMAT_DNS_RCODE(dt->answer_rcode));
942eb2e7
LP
886 goto fail;
887 }
888
b3c6b00a 889 /* Fall-through: NXDOMAIN/SERVFAIL is good enough for us. This is because some DNS servers
5238e957 890 * erroneously return NXDOMAIN/SERVFAIL for empty non-terminals (Akamai...) or missing DS
b3c6b00a
LP
891 * records (Facebook), and we need to handle that nicely, when asking for parent SOA or similar
892 * RRs to make unsigned proofs. */
942eb2e7
LP
893
894 case DNS_TRANSACTION_SUCCESS:
895 /* All good. */
896 break;
897
898 case DNS_TRANSACTION_DNSSEC_FAILED:
899 /* We handle DNSSEC failures different from other errors, as we care about the DNSSEC
e30a62bf 900 * validation result */
942eb2e7 901
a72cf22d
YW
902 log_debug("Auxiliary DNSSEC RR query failed validation: %s%s%s%s%s%s",
903 dnssec_result_to_string(dt->answer_dnssec_result),
904 dt->answer_ede_rcode >= 0 ? " (" : "",
905 dt->answer_ede_rcode >= 0 ? FORMAT_DNS_EDE_RCODE(dt->answer_ede_rcode) : "",
906 (dt->answer_ede_rcode >= 0 && !isempty(dt->answer_ede_msg)) ? ": " : "",
907 dt->answer_ede_rcode >= 0 ? strempty(dt->answer_ede_msg) : "",
908 dt->answer_ede_rcode >= 0 ? ")" : "");
909
910 /* Copy error code over */
911 t->answer_dnssec_result = dt->answer_dnssec_result;
912 t->answer_ede_rcode = dt->answer_ede_rcode;
913 r = free_and_strdup(&t->answer_ede_msg, dt->answer_ede_msg);
914 if (r < 0)
915 log_oom_debug();
916
942eb2e7
LP
917 dns_transaction_complete(t, DNS_TRANSACTION_DNSSEC_FAILED);
918 return 0;
919
942eb2e7
LP
920 default:
921 log_debug("Auxiliary DNSSEC RR query failed with %s", dns_transaction_state_to_string(dt->state));
922 goto fail;
923 }
924 }
925
926 /* All is ready, we can go and validate */
927 return 1;
928
929fail:
e30a62bf
LP
930 /* Some auxiliary DNSSEC transaction failed for some reason. Maybe we learned something about the
931 * server due to this failure, and the feature level is now different? Let's see and restart the
932 * transaction if so. If not, let's propagate the auxiliary failure.
933 *
934 * This is particularly relevant if an auxiliary request figured out that DNSSEC doesn't work, and we
935 * are in permissive DNSSEC mode, and thus should restart things without DNSSEC magic. */
936 r = dns_transaction_maybe_restart(t);
937 if (r < 0)
938 return r;
939 if (r > 0)
940 return 0; /* don't validate just yet, we restarted things */
941
942eb2e7
LP
942 t->answer_dnssec_result = DNSSEC_FAILED_AUXILIARY;
943 dns_transaction_complete(t, DNS_TRANSACTION_DNSSEC_FAILED);
944 return 0;
945}
946
547973de
LP
947static void dns_transaction_process_dnssec(DnsTransaction *t) {
948 int r;
949
950 assert(t);
951
952 /* Are there ongoing DNSSEC transactions? If so, let's wait for them. */
942eb2e7 953 r = dns_transaction_dnssec_ready(t);
7cc6ed7b
LP
954 if (r < 0)
955 goto fail;
942eb2e7 956 if (r == 0) /* We aren't ready yet (or one of our auxiliary transactions failed, and we shouldn't validate now */
547973de
LP
957 return;
958
c02cf2f4
LP
959 /* See if we learnt things from the additional DNSSEC transactions, that we didn't know before, and better
960 * restart the lookup immediately. */
961 r = dns_transaction_maybe_restart(t);
7cc6ed7b
LP
962 if (r < 0)
963 goto fail;
c02cf2f4
LP
964 if (r > 0) /* Transaction got restarted... */
965 return;
966
547973de
LP
967 /* All our auxiliary DNSSEC transactions are complete now. Try
968 * to validate our RRset now. */
969 r = dns_transaction_validate_dnssec(t);
fcfaff12
LP
970 if (r == -EBADMSG) {
971 dns_transaction_complete(t, DNS_TRANSACTION_INVALID_REPLY);
972 return;
973 }
7cc6ed7b
LP
974 if (r < 0)
975 goto fail;
547973de 976
b652d4a2
LP
977 if (t->answer_dnssec_result == DNSSEC_INCOMPATIBLE_SERVER &&
978 t->scope->dnssec_mode == DNSSEC_YES) {
e82b1132
LP
979
980 /* We are not in automatic downgrade mode, and the server is bad. Let's try a different server, maybe
981 * that works. */
982
9147b591 983 if (dns_transaction_limited_retry(t))
e82b1132 984 return;
e82b1132
LP
985
986 /* OK, let's give up, apparently all servers we tried didn't work. */
b652d4a2
LP
987 dns_transaction_complete(t, DNS_TRANSACTION_DNSSEC_FAILED);
988 return;
989 }
990
019036a4 991 if (!IN_SET(t->answer_dnssec_result,
b652d4a2
LP
992 _DNSSEC_RESULT_INVALID, /* No DNSSEC validation enabled */
993 DNSSEC_VALIDATED, /* Answer is signed and validated successfully */
994 DNSSEC_UNSIGNED, /* Answer is right-fully unsigned */
995 DNSSEC_INCOMPATIBLE_SERVER)) { /* Server does not do DNSSEC (Yay, we are downgrade attack vulnerable!) */
547973de
LP
996 dns_transaction_complete(t, DNS_TRANSACTION_DNSSEC_FAILED);
997 return;
998 }
999
1e02e182
LP
1000 if (t->answer_dnssec_result == DNSSEC_INCOMPATIBLE_SERVER)
1001 dns_server_warn_downgrade(t->server);
1002
547973de
LP
1003 dns_transaction_cache_answer(t);
1004
1005 if (t->answer_rcode == DNS_RCODE_SUCCESS)
1006 dns_transaction_complete(t, DNS_TRANSACTION_SUCCESS);
1007 else
3bbdc31d 1008 dns_transaction_complete(t, DNS_TRANSACTION_RCODE_FAILURE);
7cc6ed7b
LP
1009
1010 return;
1011
1012fail:
fd8a3017 1013 dns_transaction_complete_errno(t, r);
547973de
LP
1014}
1015
eac7cda2
LP
1016static int dns_transaction_has_positive_answer(DnsTransaction *t, DnsAnswerFlags *flags) {
1017 int r;
1018
1019 assert(t);
1020
1021 /* Checks whether the answer is positive, i.e. either a direct
1022 * answer to the question, or a CNAME/DNAME for it */
1023
42df9532 1024 r = dns_answer_match_key(t->answer, dns_transaction_key(t), flags);
eac7cda2
LP
1025 if (r != 0)
1026 return r;
1027
42df9532 1028 r = dns_answer_find_cname_or_dname(t->answer, dns_transaction_key(t), NULL, flags);
eac7cda2
LP
1029 if (r != 0)
1030 return r;
1031
1032 return false;
1033}
1034
1035static int dns_transaction_fix_rcode(DnsTransaction *t) {
1036 int r;
1037
1038 assert(t);
1039
1040 /* Fix up the RCODE to SUCCESS if we get at least one matching RR in a response. Note that this contradicts the
1041 * DNS RFCs a bit. Specifically, RFC 6604 Section 3 clarifies that the RCODE shall say something about a
1042 * CNAME/DNAME chain element coming after the last chain element contained in the message, and not the first
1043 * one included. However, it also indicates that not all DNS servers implement this correctly. Moreover, when
1044 * using DNSSEC we usually only can prove the first element of a CNAME/DNAME chain anyway, hence let's settle
1045 * on always processing the RCODE as referring to the immediate look-up we do, i.e. the first element of a
1046 * CNAME/DNAME chain. This way, we uniformly handle CNAME/DNAME chains, regardless if the DNS server
1047 * incorrectly implements RCODE, whether DNSSEC is in use, or whether the DNS server only supplied us with an
1048 * incomplete CNAME/DNAME chain.
1049 *
1050 * Or in other words: if we get at least one positive reply in a message we patch NXDOMAIN to become SUCCESS,
1051 * and then rely on the CNAME chasing logic to figure out that there's actually a CNAME error with a new
1052 * lookup. */
1053
1054 if (t->answer_rcode != DNS_RCODE_NXDOMAIN)
1055 return 0;
1056
1057 r = dns_transaction_has_positive_answer(t, NULL);
1058 if (r <= 0)
1059 return r;
1060
1061 t->answer_rcode = DNS_RCODE_SUCCESS;
1062 return 0;
1063}
1064
43fc4baa 1065void dns_transaction_process_reply(DnsTransaction *t, DnsPacket *p, bool encrypted) {
acbf761b 1066 bool retry_with_tcp = false;
ec2c5e43
LP
1067 int r;
1068
1069 assert(t);
1070 assert(p);
9df3ba6c
TG
1071 assert(t->scope);
1072 assert(t->scope->manager);
ec2c5e43 1073
5a7e41a3
LP
1074 if (t->state != DNS_TRANSACTION_PENDING)
1075 return;
1076
bc837621
KV
1077 /* Increment the total failure counter only when it is the first attempt at querying and the upstream
1078 * server returns a failure response code. This ensures a more accurate count of the number of queries
1079 * that received a failure response code, as it doesn't consider retries. */
1080
1081 if (t->n_attempts == 1 && !IN_SET(DNS_PACKET_RCODE(p), DNS_RCODE_SUCCESS, DNS_RCODE_NXDOMAIN))
1082 t->scope->manager->n_failure_responses_total++;
1083
ec2c5e43
LP
1084 /* Note that this call might invalidate the query. Callers
1085 * should hence not attempt to access the query or transaction
1086 * after calling this function. */
1087
f7155840
LP
1088 log_debug("Processing incoming packet of size %zu on transaction %" PRIu16" (rcode=%s).",
1089 p->size,
0d609349 1090 t->id, FORMAT_DNS_RCODE(DNS_PACKET_RCODE(p)));
b5efcf29 1091
106784eb 1092 switch (t->scope->protocol) {
b5efcf29 1093
106784eb 1094 case DNS_PROTOCOL_LLMNR:
97ebebbc 1095 /* For LLMNR we will not accept any packets from other interfaces */
ec2c5e43 1096
97ebebbc 1097 if (p->ifindex != dns_scope_ifindex(t->scope))
ec2c5e43
LP
1098 return;
1099
1100 if (p->family != t->scope->family)
1101 return;
1102
1103 /* Tentative packets are not full responses but still
1104 * useful for identifying uniqueness conflicts during
1105 * probing. */
8b757a38 1106 if (DNS_PACKET_LLMNR_T(p)) {
ec2c5e43
LP
1107 dns_transaction_tentative(t, p);
1108 return;
1109 }
106784eb
DM
1110
1111 break;
1112
4e5bf5e1 1113 case DNS_PROTOCOL_MDNS:
4e5bf5e1 1114 /* For mDNS we will not accept any packets from other interfaces */
97ebebbc
LP
1115
1116 if (p->ifindex != dns_scope_ifindex(t->scope))
4e5bf5e1
DM
1117 return;
1118
1119 if (p->family != t->scope->family)
1120 return;
1121
1122 break;
1123
106784eb 1124 case DNS_PROTOCOL_DNS:
8ad182a1
LP
1125 /* Note that we do not need to verify the
1126 * addresses/port numbers of incoming traffic, as we
1127 * invoked connect() on our UDP socket in which case
1128 * the kernel already does the needed verification for
1129 * us. */
106784eb
DM
1130 break;
1131
1132 default:
04499a70 1133 assert_not_reached();
ec2c5e43
LP
1134 }
1135
899e3cda
ZJS
1136 if (t->received != p)
1137 DNS_PACKET_REPLACE(t->received, dns_packet_ref(p));
ec2c5e43 1138
c3bc53e6
LP
1139 t->answer_source = DNS_TRANSACTION_NETWORK;
1140
ec2c5e43
LP
1141 if (p->ipproto == IPPROTO_TCP) {
1142 if (DNS_PACKET_TC(p)) {
1143 /* Truncated via TCP? Somebody must be fucking with us */
1144 dns_transaction_complete(t, DNS_TRANSACTION_INVALID_REPLY);
1145 return;
1146 }
1147
1148 if (DNS_PACKET_ID(p) != t->id) {
1149 /* Not the reply to our query? Somebody must be fucking with us */
1150 dns_transaction_complete(t, DNS_TRANSACTION_INVALID_REPLY);
1151 return;
1152 }
1153 }
1154
3fcd8364
RP
1155 if (DNS_PACKET_TC(p)) {
1156
1157 /* Truncated packets for mDNS are not allowed. Give up immediately. */
1158 if (t->scope->protocol == DNS_PROTOCOL_MDNS) {
1159 dns_transaction_complete(t, DNS_TRANSACTION_INVALID_REPLY);
1160 return;
1161 }
1162
1163 /* Response was truncated, let's try again with good old TCP */
1164 log_debug("Reply truncated, retrying via TCP.");
1165 retry_with_tcp = true;
1166
1167 } else if (t->scope->protocol == DNS_PROTOCOL_DNS &&
1168 DNS_PACKET_IS_FRAGMENTED(p)) {
1169
1170 /* Report the fragment size, so that we downgrade from LARGE to regular EDNS0 if needed */
1171 if (t->server)
1172 dns_server_packet_udp_fragmented(t->server, dns_packet_size_unfragmented(p));
1173
1174 if (t->current_feature_level > DNS_SERVER_FEATURE_LEVEL_UDP) {
1175 /* Packet was fragmented. Let's retry with TCP to avoid fragmentation attack
1176 * issues. (We don't do that on the lowest feature level however, since crappy DNS
1177 * servers often do not implement TCP, hence falling back to TCP on fragmentation is
1178 * counter-productive there.) */
1179
1180 log_debug("Reply fragmented, retrying via TCP. (Largest fragment size: %zu; Datagram size: %zu)",
1181 p->fragsize, p->size);
1182 retry_with_tcp = true;
1183 }
1184 }
1185
1186 if (retry_with_tcp) {
1187 r = dns_transaction_emit_tcp(t);
1188 if (r == -ESRCH) {
1189 /* No servers found? Damn! */
1190 dns_transaction_complete(t, DNS_TRANSACTION_NO_SERVERS);
1191 return;
1192 }
1193 if (r == -EOPNOTSUPP) {
1194 /* Tried to ask for DNSSEC RRs, on a server that doesn't do DNSSEC */
1195 dns_transaction_complete(t, DNS_TRANSACTION_RR_TYPE_UNSUPPORTED);
1196 return;
1197 }
1198 if (r < 0) {
1199 /* On LLMNR, if we cannot connect to the host,
1200 * we immediately give up */
1201 if (t->scope->protocol != DNS_PROTOCOL_DNS)
1202 goto fail;
1203
1204 /* On DNS, couldn't send? Try immediately again, with a new server */
1205 if (dns_transaction_limited_retry(t))
1206 return;
1207
1208 /* No new server to try, give up */
1209 dns_transaction_complete(t, DNS_TRANSACTION_ATTEMPTS_MAX_REACHED);
1210 }
1211
1212 return;
1213 }
1214
1215 /* After the superficial checks, actually parse the message. */
1216 r = dns_packet_extract(p);
1217 if (r < 0) {
1218 if (t->server) {
1219 dns_server_packet_invalid(t->server, t->current_feature_level);
1220
1221 r = dns_transaction_maybe_restart(t);
1222 if (r < 0)
1223 goto fail;
1224 if (r > 0) /* Transaction got restarted... */
1225 return;
1226 }
1227
1228 dns_transaction_complete(t, DNS_TRANSACTION_INVALID_REPLY);
1229 return;
1230 }
1231
9df3ba6c 1232 switch (t->scope->protocol) {
8af5b883 1233
ac684446 1234 case DNS_PROTOCOL_DNS: {
9df3ba6c
TG
1235 assert(t->server);
1236
c08fd7be 1237 (void) dns_packet_ede_rcode(p, &t->answer_ede_rcode, &t->answer_ede_msg);
ac684446 1238
775ae354
LP
1239 if (!t->bypass &&
1240 IN_SET(DNS_PACKET_RCODE(p), DNS_RCODE_FORMERR, DNS_RCODE_SERVFAIL, DNS_RCODE_NOTIMP)) {
ac684446
RP
1241 /* If the server has replied with detailed error data, using a degraded feature set
1242 * will likely not help anyone. Examine the detailed error to determine the best
1243 * course of action. */
c08fd7be 1244 if (t->answer_ede_rcode >= 0 && DNS_PACKET_RCODE(p) == DNS_RCODE_SERVFAIL) {
ac684446
RP
1245 /* These codes are related to DNSSEC configuration errors. If accurate,
1246 * this is the domain operator's problem, and retrying won't help. */
c08fd7be 1247 if (dns_ede_rcode_is_dnssec(t->answer_ede_rcode)) {
ac684446 1248 log_debug("Server returned error: %s (%s%s%s). Lookup failed.",
c08fd7be
YW
1249 FORMAT_DNS_RCODE(DNS_PACKET_RCODE(p)),
1250 FORMAT_DNS_EDE_RCODE(t->answer_ede_rcode),
1251 isempty(t->answer_ede_msg) ? "" : ": ",
1252 strempty(t->answer_ede_msg));
a72cf22d
YW
1253
1254 t->answer_dnssec_result = DNSSEC_UPSTREAM_FAILURE;
9ae51762 1255 dns_transaction_complete(t, DNS_TRANSACTION_DNSSEC_FAILED);
ac684446
RP
1256 return;
1257 }
1258
1259 /* These codes probably indicate a transient error. Let's try again. */
c08fd7be 1260 if (IN_SET(t->answer_ede_rcode, DNS_EDE_RCODE_NOT_READY, DNS_EDE_RCODE_NET_ERROR)) {
ac684446 1261 log_debug("Server returned error: %s (%s%s%s), retrying transaction.",
c08fd7be
YW
1262 FORMAT_DNS_RCODE(DNS_PACKET_RCODE(p)),
1263 FORMAT_DNS_EDE_RCODE(t->answer_ede_rcode),
1264 isempty(t->answer_ede_msg) ? "" : ": ",
1265 strempty(t->answer_ede_msg));
ac684446
RP
1266 dns_transaction_retry(t, false);
1267 return;
1268 }
1269
1270 /* OK, the query failed, but we still shouldn't degrade the feature set for
1271 * this server. */
1272 log_debug("Server returned error: %s (%s%s%s)",
c08fd7be
YW
1273 FORMAT_DNS_RCODE(DNS_PACKET_RCODE(p)),
1274 FORMAT_DNS_EDE_RCODE(t->answer_ede_rcode),
1275 isempty(t->answer_ede_msg) ? "" : ": ",
1276 strempty(t->answer_ede_msg));
ac684446 1277 break;
c08fd7be 1278 }
4e0b8b17 1279
8af5b883 1280 /* Request failed, immediately try again with reduced features */
4e0b8b17 1281
7d581a65 1282 if (t->current_feature_level <= DNS_SERVER_FEATURE_LEVEL_UDP) {
44db02d0 1283
7d581a65 1284 /* This was already at UDP feature level? If so, it doesn't make sense to downgrade
44db02d0
LP
1285 * this transaction anymore, but let's see if it might make sense to send the request
1286 * to a different DNS server instead. If not let's process the response, and accept the
7d581a65
LP
1287 * rcode. Note that we don't retry on TCP, since that's a suitable way to mitigate
1288 * packet loss, but is not going to give us better rcodes should we actually have
1289 * managed to get them already at UDP level. */
1290
9147b591 1291 if (dns_transaction_limited_retry(t))
44db02d0 1292 return;
44db02d0
LP
1293
1294 /* Give up, accept the rcode */
0d609349 1295 log_debug("Server returned error: %s", FORMAT_DNS_RCODE(DNS_PACKET_RCODE(p)));
d001e0a3
LP
1296 break;
1297 }
1298
8a33aa19
SS
1299 /* SERVFAIL can happen for many reasons and may be transient.
1300 * To avoid unnecessary downgrades retry once with the initial level.
1301 * Check for clamp_feature_level_servfail having an invalid value as a sign that this is the
1302 * first attempt to downgrade. If so, clamp to the current value so that the transaction
1303 * is retried without actually downgrading. If the next try also fails we will downgrade by
1304 * hitting the else branch below. */
1305 if (DNS_PACKET_RCODE(p) == DNS_RCODE_SERVFAIL &&
1306 t->clamp_feature_level_servfail < 0) {
1307 t->clamp_feature_level_servfail = t->current_feature_level;
1308 log_debug("Server returned error %s, retrying transaction.",
0d609349 1309 FORMAT_DNS_RCODE(DNS_PACKET_RCODE(p)));
8a33aa19
SS
1310 } else {
1311 /* Reduce this feature level by one and try again. */
1312 switch (t->current_feature_level) {
1313 case DNS_SERVER_FEATURE_LEVEL_TLS_DO:
1314 t->clamp_feature_level_servfail = DNS_SERVER_FEATURE_LEVEL_TLS_PLAIN;
1315 break;
1316 case DNS_SERVER_FEATURE_LEVEL_TLS_PLAIN + 1:
1317 /* Skip plain TLS when TLS is not supported */
1318 t->clamp_feature_level_servfail = DNS_SERVER_FEATURE_LEVEL_TLS_PLAIN - 1;
1319 break;
1320 default:
1321 t->clamp_feature_level_servfail = t->current_feature_level - 1;
1322 }
1323
1324 log_debug("Server returned error %s, retrying transaction with reduced feature level %s.",
0d609349 1325 FORMAT_DNS_RCODE(DNS_PACKET_RCODE(p)),
8a33aa19 1326 dns_server_feature_level_to_string(t->clamp_feature_level_servfail));
5d67a7ae 1327 }
d001e0a3 1328
d001e0a3 1329 dns_transaction_retry(t, false /* use the same server */);
4e0b8b17 1330 return;
eb08640a
LP
1331 }
1332
1333 if (DNS_PACKET_RCODE(p) == DNS_RCODE_REFUSED) {
1334 /* This server refused our request? If so, try again, use a different server */
c08fd7be 1335 if (t->answer_ede_rcode >= 0)
ac684446 1336 log_debug("Server returned REFUSED (%s), switching servers, and retrying.",
c08fd7be 1337 FORMAT_DNS_EDE_RCODE(t->answer_ede_rcode));
ac684446
RP
1338 else
1339 log_debug("Server returned REFUSED, switching servers, and retrying.");
9147b591
LP
1340
1341 if (dns_transaction_limited_retry(t))
1342 return;
1343
1344 break;
eb08640a
LP
1345 }
1346
1347 if (DNS_PACKET_TC(p))
274b8748 1348 dns_server_packet_truncated(t->server, t->current_feature_level);
9df3ba6c
TG
1349
1350 break;
ac684446 1351 }
8af5b883 1352
9df3ba6c
TG
1353 case DNS_PROTOCOL_LLMNR:
1354 case DNS_PROTOCOL_MDNS:
5777c613 1355 dns_scope_packet_received(t->scope, p->timestamp - t->start_usec);
9df3ba6c 1356 break;
8af5b883 1357
9df3ba6c 1358 default:
04499a70 1359 assert_not_reached();
9df3ba6c
TG
1360 }
1361
ed9717fc 1362 if (t->server) {
d001e0a3
LP
1363 /* Report that we successfully received a valid packet with a good rcode after we initially got a bad
1364 * rcode and subsequently downgraded the protocol */
1365
1366 if (IN_SET(DNS_PACKET_RCODE(p), DNS_RCODE_SUCCESS, DNS_RCODE_NXDOMAIN) &&
1ed4e584
LP
1367 t->clamp_feature_level_servfail != _DNS_SERVER_FEATURE_LEVEL_INVALID)
1368 dns_server_packet_rcode_downgrade(t->server, t->clamp_feature_level_servfail);
d001e0a3
LP
1369
1370 /* Report that the OPT RR was missing */
ed9717fc
LP
1371 if (!p->opt)
1372 dns_server_packet_bad_opt(t->server, t->current_feature_level);
1373
d96275d8
LP
1374 /* Report that the server didn't copy our query DO bit from request to response */
1375 if (DNS_PACKET_DO(t->sent) && !DNS_PACKET_DO(t->received))
1376 dns_server_packet_do_off(t->server, t->current_feature_level);
1377
acbf761b
LP
1378 /* Report that we successfully received a packet. We keep track of the largest packet
1379 * size/fragment size we got. Which is useful for announcing the EDNS(0) packet size we can
1380 * receive to our server. */
1381 dns_server_packet_received(t->server, p->ipproto, t->current_feature_level, dns_packet_size_unfragmented(p));
ed9717fc 1382 }
de54e62b 1383
c02cf2f4
LP
1384 /* See if we know things we didn't know before that indicate we better restart the lookup immediately. */
1385 r = dns_transaction_maybe_restart(t);
7cc6ed7b
LP
1386 if (r < 0)
1387 goto fail;
c02cf2f4
LP
1388 if (r > 0) /* Transaction got restarted... */
1389 return;
1390
8facd1ce
LP
1391 /* When dealing with protocols other than mDNS only consider responses with equivalent query section
1392 * to the request. For mDNS this check doesn't make sense, because the section 6 of RFC6762 states
1393 * that "Multicast DNS responses MUST NOT contain any questions in the Question Section". */
1394 if (t->scope->protocol != DNS_PROTOCOL_MDNS) {
42df9532 1395 r = dns_packet_is_reply_for(p, dns_transaction_key(t));
8facd1ce
LP
1396 if (r < 0)
1397 goto fail;
1398 if (r == 0) {
1399 dns_transaction_complete(t, DNS_TRANSACTION_INVALID_REPLY);
1400 return;
547493c5 1401 }
8facd1ce 1402 }
29815b6c 1403
775ae354
LP
1404 /* Install the answer as answer to the transaction. We ref the answer twice here: the main `answer`
1405 * field is later replaced by the DNSSEC validated subset. The 'answer_auxiliary' field carries the
1406 * original complete record set, including RRSIG and friends. We use this when passing data to
1407 * clients that ask for DNSSEC metadata. */
1117a960 1408 DNS_ANSWER_REPLACE(t->answer, dns_answer_ref(p->answer));
8facd1ce
LP
1409 t->answer_rcode = DNS_PACKET_RCODE(p);
1410 t->answer_dnssec_result = _DNSSEC_RESULT_INVALID;
6f055e43 1411 SET_FLAG(t->answer_query_flags, SD_RESOLVED_AUTHENTICATED, false);
43fc4baa 1412 SET_FLAG(t->answer_query_flags, SD_RESOLVED_CONFIDENTIAL, encrypted);
79e24931 1413
8facd1ce
LP
1414 r = dns_transaction_fix_rcode(t);
1415 if (r < 0)
1416 goto fail;
eac7cda2 1417
8facd1ce
LP
1418 /* Block GC while starting requests for additional DNSSEC RRs */
1419 t->block_gc++;
1420 r = dns_transaction_request_dnssec_keys(t);
1421 t->block_gc--;
51e399bc 1422
8facd1ce
LP
1423 /* Maybe the transaction is ready for GC'ing now? If so, free it and return. */
1424 if (!dns_transaction_gc(t))
1425 return;
51e399bc 1426
8facd1ce
LP
1427 /* Requesting additional keys might have resulted in this transaction to fail, since the auxiliary
1428 * request failed for some reason. If so, we are not in pending state anymore, and we should exit
1429 * quickly. */
1430 if (t->state != DNS_TRANSACTION_PENDING)
1431 return;
1432 if (r < 0)
1433 goto fail;
1434 if (r > 0) {
1435 /* There are DNSSEC transactions pending now. Update the state accordingly. */
1436 t->state = DNS_TRANSACTION_VALIDATING;
80710ade 1437 dns_transaction_close_connection(t, true);
8facd1ce
LP
1438 dns_transaction_stop_timeout(t);
1439 return;
547493c5 1440 }
ec2c5e43 1441
547973de 1442 dns_transaction_process_dnssec(t);
7cc6ed7b
LP
1443 return;
1444
1445fail:
fd8a3017 1446 dns_transaction_complete_errno(t, r);
ec2c5e43
LP
1447}
1448
c19ffd9f
TG
1449static int on_dns_packet(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
1450 _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
99534007 1451 DnsTransaction *t = ASSERT_PTR(userdata);
c19ffd9f
TG
1452 int r;
1453
c19ffd9f
TG
1454 assert(t->scope);
1455
1456 r = manager_recv(t->scope->manager, fd, DNS_PROTOCOL_DNS, &p);
0bdea17c
DL
1457 if (r < 0) {
1458 if (ERRNO_IS_DISCONNECT(r)) {
1459 usec_t usec;
7e1851e3 1460
0bdea17c
DL
1461 /* UDP connection failures get reported via ICMP and then are possibly delivered to us on the
1462 * next recvmsg(). Treat this like a lost packet. */
7e1851e3 1463
0bdea17c
DL
1464 log_debug_errno(r, "Connection failure for DNS UDP packet: %m");
1465 assert_se(sd_event_now(t->scope->manager->event, CLOCK_BOOTTIME, &usec) >= 0);
1466 dns_server_packet_lost(t->server, IPPROTO_UDP, t->current_feature_level);
d68dbb37 1467
0bdea17c 1468 dns_transaction_close_connection(t, /* use_graveyard = */ false);
9147b591 1469
0bdea17c
DL
1470 if (dns_transaction_limited_retry(t)) /* Try a different server */
1471 return 0;
1472 }
fd8a3017 1473 dns_transaction_complete_errno(t, r);
7e1851e3
LP
1474 return 0;
1475 }
f731fd5b
ZJS
1476 if (r == 0)
1477 /* Spurious wakeup without any data */
1478 return 0;
7e1851e3
LP
1479
1480 r = dns_packet_validate_reply(p);
1481 if (r < 0) {
1482 log_debug_errno(r, "Received invalid DNS packet as response, ignoring: %m");
1483 return 0;
1484 }
1485 if (r == 0) {
e09f605e 1486 log_debug("Received inappropriate DNS packet as response, ignoring.");
7e1851e3
LP
1487 return 0;
1488 }
1489
1490 if (DNS_PACKET_ID(p) != t->id) {
e09f605e 1491 log_debug("Received packet with incorrect transaction ID, ignoring.");
7e1851e3
LP
1492 return 0;
1493 }
c19ffd9f 1494
43fc4baa 1495 dns_transaction_process_reply(t, p, false);
c19ffd9f
TG
1496 return 0;
1497}
1498
49cce12d 1499static int dns_transaction_emit_udp(DnsTransaction *t) {
c19ffd9f
TG
1500 int r;
1501
1502 assert(t);
c19ffd9f 1503
519ef046 1504 if (t->scope->protocol == DNS_PROTOCOL_DNS) {
c19ffd9f 1505
519ef046 1506 r = dns_transaction_pick_server(t);
471d40d9
TG
1507 if (r < 0)
1508 return r;
c19ffd9f 1509
49ef064c
LP
1510 if (manager_server_is_stub(t->scope->manager, t->server))
1511 return -ELOOP;
1512
5d67a7ae 1513 if (t->current_feature_level < DNS_SERVER_FEATURE_LEVEL_UDP || DNS_SERVER_FEATURE_LEVEL_IS_TLS(t->current_feature_level))
7d581a65 1514 return -EAGAIN; /* Sorry, can't do UDP, try TCP! */
519ef046 1515
775ae354 1516 if (!t->bypass && !dns_server_dnssec_supported(t->server) && dns_type_is_dnssec(dns_transaction_key(t)->type))
91adc4db
LP
1517 return -EOPNOTSUPP;
1518
519ef046
LP
1519 if (r > 0 || t->dns_udp_fd < 0) { /* Server changed, or no connection yet. */
1520 int fd;
1521
80710ade
LP
1522 dns_transaction_close_connection(t, true);
1523
1524 /* Before we allocate a new UDP socket, let's process the graveyard a bit to free some fds */
1525 manager_socket_graveyard_process(t->scope->manager);
c19ffd9f 1526
da9de738 1527 fd = dns_scope_socket_udp(t->scope, t->server);
519ef046
LP
1528 if (fd < 0)
1529 return fd;
1530
1531 r = sd_event_add_io(t->scope->manager->event, &t->dns_udp_event_source, fd, EPOLLIN, on_dns_packet, t);
1532 if (r < 0) {
1533 safe_close(fd);
1534 return r;
1535 }
1536
aa4a9deb 1537 (void) sd_event_source_set_description(t->dns_udp_event_source, "dns-transaction-udp");
519ef046
LP
1538 t->dns_udp_fd = fd;
1539 }
1540
775ae354
LP
1541 if (!t->bypass) {
1542 r = dns_server_adjust_opt(t->server, t->sent, t->current_feature_level);
1543 if (r < 0)
1544 return r;
1545 }
519ef046 1546 } else
80710ade 1547 dns_transaction_close_connection(t, true);
519ef046 1548
d79677ab 1549 r = dns_scope_emit_udp(t->scope, t->dns_udp_fd, t->server ? t->server->family : AF_UNSPEC, t->sent);
471d40d9
TG
1550 if (r < 0)
1551 return r;
c19ffd9f 1552
519ef046 1553 dns_transaction_reset_answer(t);
be808ea0 1554
471d40d9 1555 return 0;
c19ffd9f
TG
1556}
1557
ec2c5e43 1558static int on_transaction_timeout(sd_event_source *s, usec_t usec, void *userdata) {
99534007 1559 DnsTransaction *t = ASSERT_PTR(userdata);
ec2c5e43
LP
1560
1561 assert(s);
ec2c5e43 1562
bc837621
KV
1563 t->seen_timeout = true;
1564
213cb4f7
LP
1565 if (t->initial_jitter_scheduled && !t->initial_jitter_elapsed) {
1566 log_debug("Initial jitter phase for transaction %" PRIu16 " elapsed.", t->id);
1567 t->initial_jitter_elapsed = true;
1568 } else {
ef7ce6df
DM
1569 /* Timeout reached? Increase the timeout for the server used */
1570 switch (t->scope->protocol) {
49cce12d 1571
ef7ce6df
DM
1572 case DNS_PROTOCOL_DNS:
1573 assert(t->server);
3da3cdd5 1574 dns_server_packet_lost(t->server, t->stream ? IPPROTO_TCP : IPPROTO_UDP, t->current_feature_level);
ef7ce6df 1575 break;
49cce12d 1576
ef7ce6df
DM
1577 case DNS_PROTOCOL_LLMNR:
1578 case DNS_PROTOCOL_MDNS:
1579 dns_scope_packet_lost(t->scope, usec - t->start_usec);
ef7ce6df 1580 break;
49cce12d 1581
ef7ce6df 1582 default:
04499a70 1583 assert_not_reached();
ef7ce6df
DM
1584 }
1585
213cb4f7 1586 log_debug("Timeout reached on transaction %" PRIu16 ".", t->id);
be808ea0
TG
1587 }
1588
213cb4f7
LP
1589 dns_transaction_retry(t, /* next_server= */ true); /* try a different server, but given this means
1590 * packet loss, let's do so even if we already
1591 * tried a bunch */
ec2c5e43
LP
1592 return 0;
1593}
1594
87b91644
YW
1595static int dns_transaction_setup_timeout(
1596 DnsTransaction *t,
1597 usec_t timeout_usec /* relative */,
1598 usec_t next_usec /* CLOCK_BOOTTIME */) {
1599
1600 int r;
1601
1602 assert(t);
1603
1604 dns_transaction_stop_timeout(t);
1605
1606 r = sd_event_add_time_relative(
1607 t->scope->manager->event,
1608 &t->timeout_event_source,
1609 CLOCK_BOOTTIME,
1610 timeout_usec, 0,
1611 on_transaction_timeout, t);
1612 if (r < 0)
1613 return r;
1614
1615 (void) sd_event_source_set_description(t->timeout_event_source, "dns-transaction-timeout");
1616
1617 t->next_attempt_after = next_usec;
1618 t->state = DNS_TRANSACTION_PENDING;
1619 return 0;
1620}
1621
9df3ba6c
TG
1622static usec_t transaction_get_resend_timeout(DnsTransaction *t) {
1623 assert(t);
1624 assert(t->scope);
1625
1626 switch (t->scope->protocol) {
49cce12d 1627
9df3ba6c 1628 case DNS_PROTOCOL_DNS:
dc349f5f
LP
1629
1630 /* When we do TCP, grant a much longer timeout, as in this case there's no need for us to quickly
1631 * resend, as the kernel does that anyway for us, and we really don't want to interrupt it in that
1632 * needlessly. */
1633 if (t->stream)
1634 return TRANSACTION_TCP_TIMEOUT_USEC;
1635
dbc4661a 1636 return DNS_TIMEOUT_USEC;
49cce12d 1637
9df3ba6c 1638 case DNS_PROTOCOL_MDNS:
53fda2bb
DR
1639 if (t->probing)
1640 return MDNS_PROBING_INTERVAL_USEC;
4b2ceb8a
YW
1641
1642 /* See RFC 6762 Section 5.1 suggests that timeout should be a few seconds. */
1643 assert(t->n_attempts > 0);
1644 return (1 << (t->n_attempts - 1)) * USEC_PER_SEC;
49cce12d 1645
11a27c2e 1646 case DNS_PROTOCOL_LLMNR:
9df3ba6c 1647 return t->scope->resend_timeout;
49cce12d 1648
9df3ba6c 1649 default:
04499a70 1650 assert_not_reached();
9df3ba6c
TG
1651 }
1652}
1653
3f0a7b3a
LP
1654static void dns_transaction_randomize_answer(DnsTransaction *t) {
1655 int r;
1656
1657 assert(t);
1658
1659 /* Randomizes the order of the answer array. This is done for all cached responses, so that we return
1660 * a different order each time. We do this only for DNS traffic, in order to do some minimal, crappy
1661 * load balancing. We don't do this for LLMNR or mDNS, since the order (preferring link-local
1662 * addresses, and such like) might have meaning there, and load balancing is pointless. */
1663
1664 if (t->scope->protocol != DNS_PROTOCOL_DNS)
1665 return;
1666
1667 /* No point in randomizing, if there's just one RR */
1668 if (dns_answer_size(t->answer) <= 1)
1669 return;
1670
1671 r = dns_answer_reserve_or_clone(&t->answer, 0);
1672 if (r < 0) /* If this fails, just don't randomize, this is non-essential stuff after all */
1673 return (void) log_debug_errno(r, "Failed to clone answer record, not randomizing RR order of answer: %m");
1674
1675 dns_answer_randomize(t->answer);
1676}
1677
c842ff24 1678static int dns_transaction_prepare(DnsTransaction *t, usec_t ts) {
ec2c5e43
LP
1679 int r;
1680
1681 assert(t);
1682
4ea8b443
ZJS
1683 /* Returns 0 if dns_transaction_complete() has been called. In that case the transaction and query
1684 * candidate objects may have been invalidated and must not be accessed. Returns 1 if the transaction
1685 * has been prepared. */
1686
f535705a 1687 dns_transaction_stop_timeout(t);
ec2c5e43 1688
bc837621
KV
1689 if (t->n_attempts == 1 && t->seen_timeout)
1690 t->scope->manager->n_timeouts_total++;
1691
86b112a3 1692 if (!dns_scope_network_good(t->scope)) {
edbcc1fd
LP
1693 dns_transaction_complete(t, DNS_TRANSACTION_NETWORK_DOWN);
1694 return 0;
1695 }
1696
c3dbb132 1697 if (t->n_attempts >= TRANSACTION_ATTEMPTS_MAX(t->scope->protocol)) {
e53b8cc5
ZJS
1698 DnsTransactionState result;
1699
1700 if (t->scope->protocol == DNS_PROTOCOL_LLMNR)
1701 /* If we didn't find anything on LLMNR, it's not an error, but a failure to resolve
1702 * the name. */
1703 result = DNS_TRANSACTION_NOT_FOUND;
1704 else
1705 result = DNS_TRANSACTION_ATTEMPTS_MAX_REACHED;
1706
1707 dns_transaction_complete(t, result);
ec2c5e43
LP
1708 return 0;
1709 }
1710
cbe4216d 1711 if (t->scope->protocol == DNS_PROTOCOL_LLMNR && t->tried_stream) {
ec2c5e43
LP
1712 /* If we already tried via a stream, then we don't
1713 * retry on LLMNR. See RFC 4795, Section 2.7. */
1714 dns_transaction_complete(t, DNS_TRANSACTION_ATTEMPTS_MAX_REACHED);
1715 return 0;
1716 }
1717
1718 t->n_attempts++;
9df3ba6c 1719 t->start_usec = ts;
c61d2b44
LP
1720
1721 dns_transaction_reset_answer(t);
c5b4f861 1722 dns_transaction_flush_dnssec_transactions(t);
ec2c5e43 1723
0d2cd476 1724 /* Check the trust anchor. Do so only on classic DNS, since DNSSEC does not apply otherwise. */
775ae354
LP
1725 if (t->scope->protocol == DNS_PROTOCOL_DNS &&
1726 !FLAGS_SET(t->query_flags, SD_RESOLVED_NO_TRUST_ANCHOR)) {
42df9532 1727 r = dns_trust_anchor_lookup_positive(&t->scope->manager->trust_anchor, dns_transaction_key(t), &t->answer);
0d2cd476
LP
1728 if (r < 0)
1729 return r;
1730 if (r > 0) {
1731 t->answer_rcode = DNS_RCODE_SUCCESS;
1732 t->answer_source = DNS_TRANSACTION_TRUST_ANCHOR;
43fc4baa 1733 SET_FLAG(t->answer_query_flags, SD_RESOLVED_AUTHENTICATED|SD_RESOLVED_CONFIDENTIAL, true);
0d2cd476
LP
1734 dns_transaction_complete(t, DNS_TRANSACTION_SUCCESS);
1735 return 0;
1736 }
b2b796b8 1737
42df9532
LP
1738 if (dns_name_is_root(dns_resource_key_name(dns_transaction_key(t))) &&
1739 dns_transaction_key(t)->type == DNS_TYPE_DS) {
b2b796b8 1740
775ae354
LP
1741 /* Hmm, this is a request for the root DS? A DS RR doesn't exist in the root zone,
1742 * and if our trust anchor didn't know it either, this means we cannot do any DNSSEC
1743 * logic anymore. */
b2b796b8 1744
1ed8c0fb 1745 if (t->scope->dnssec_mode == DNSSEC_ALLOW_DOWNGRADE) {
775ae354
LP
1746 /* We are in downgrade mode. In this case, synthesize an unsigned empty
1747 * response, so that the any lookup depending on this one can continue
1748 * assuming there was no DS, and hence the root zone was unsigned. */
b2b796b8
LP
1749
1750 t->answer_rcode = DNS_RCODE_SUCCESS;
1751 t->answer_source = DNS_TRANSACTION_TRUST_ANCHOR;
6f055e43 1752 SET_FLAG(t->answer_query_flags, SD_RESOLVED_AUTHENTICATED, false);
43fc4baa 1753 SET_FLAG(t->answer_query_flags, SD_RESOLVED_CONFIDENTIAL, true);
b2b796b8
LP
1754 dns_transaction_complete(t, DNS_TRANSACTION_SUCCESS);
1755 } else
775ae354
LP
1756 /* If we are not in downgrade mode, then fail the lookup, because we cannot
1757 * reasonably answer it. There might be DS RRs, but we don't know them, and
1758 * the DNS server won't tell them to us (and even if it would, we couldn't
1759 * validate and trust them. */
b2b796b8
LP
1760 dns_transaction_complete(t, DNS_TRANSACTION_NO_TRUST_ANCHOR);
1761
1762 return 0;
1763 }
0d2cd476
LP
1764 }
1765
775ae354
LP
1766 /* Check the zone. */
1767 if (!FLAGS_SET(t->query_flags, SD_RESOLVED_NO_ZONE)) {
42df9532 1768 r = dns_zone_lookup(&t->scope->zone, dns_transaction_key(t), dns_scope_ifindex(t->scope), &t->answer, NULL, NULL);
d746bb3e
LP
1769 if (r < 0)
1770 return r;
1771 if (r > 0) {
ae6a4bbf 1772 t->answer_rcode = DNS_RCODE_SUCCESS;
c3bc53e6 1773 t->answer_source = DNS_TRANSACTION_ZONE;
43fc4baa 1774 SET_FLAG(t->answer_query_flags, SD_RESOLVED_AUTHENTICATED|SD_RESOLVED_CONFIDENTIAL, true);
d746bb3e
LP
1775 dns_transaction_complete(t, DNS_TRANSACTION_SUCCESS);
1776 return 0;
1777 }
1778 }
1779
775ae354
LP
1780 /* Check the cache. */
1781 if (!FLAGS_SET(t->query_flags, SD_RESOLVED_NO_CACHE)) {
2c27fbca 1782
775ae354
LP
1783 /* Before trying the cache, let's make sure we figured out a server to use. Should this cause
1784 * a change of server this might flush the cache. */
5cdb8930 1785 (void) dns_scope_get_dns_server(t->scope);
2c27fbca 1786
4d926a69
LP
1787 /* Let's then prune all outdated entries */
1788 dns_cache_prune(&t->scope->cache);
1789
5ed91481
KV
1790 /* For the initial attempt or when no stale data is requested, disable serve stale
1791 * and answer the question from the cache (honors ttl property).
1792 * On the second attempt, if StaleRetentionSec is greater than zero,
1793 * try to answer the question using stale date (honors until property) */
1794 uint64_t query_flags = t->query_flags;
1795 if (t->n_attempts == 1 || t->scope->manager->stale_retention_usec == 0)
1796 query_flags |= SD_RESOLVED_NO_STALE;
1797
775ae354
LP
1798 r = dns_cache_lookup(
1799 &t->scope->cache,
1800 dns_transaction_key(t),
5ed91481 1801 query_flags,
775ae354
LP
1802 &t->answer_rcode,
1803 &t->answer,
1804 &t->received,
6f055e43 1805 &t->answer_query_flags,
775ae354 1806 &t->answer_dnssec_result);
4d926a69
LP
1807 if (r < 0)
1808 return r;
1809 if (r > 0) {
3f0a7b3a
LP
1810 dns_transaction_randomize_answer(t);
1811
775ae354
LP
1812 if (t->bypass && t->scope->protocol == DNS_PROTOCOL_DNS && !t->received)
1813 /* When bypass mode is on, do not use cached data unless it came with a full
1814 * packet. */
1815 dns_transaction_reset_answer(t);
1816 else {
5ed91481 1817 if (t->n_attempts > 1 && !FLAGS_SET(query_flags, SD_RESOLVED_NO_STALE)) {
bc837621
KV
1818
1819 if (t->answer_rcode == DNS_RCODE_SUCCESS) {
1820 if (t->seen_timeout)
1821 t->scope->manager->n_timeouts_served_stale_total++;
1822 else
1823 t->scope->manager->n_failure_responses_served_stale_total++;
1824 }
1825
5ed91481
KV
1826 char key_str[DNS_RESOURCE_KEY_STRING_MAX];
1827 log_debug("Serve Stale response rcode=%s for %s",
1828 FORMAT_DNS_RCODE(t->answer_rcode),
1829 dns_resource_key_to_string(dns_transaction_key(t), key_str, sizeof key_str));
1830 }
1831
775ae354
LP
1832 t->answer_source = DNS_TRANSACTION_CACHE;
1833 if (t->answer_rcode == DNS_RCODE_SUCCESS)
1834 dns_transaction_complete(t, DNS_TRANSACTION_SUCCESS);
37baa00f
YW
1835 else {
1836 if (t->received)
1837 (void) dns_packet_ede_rcode(t->received, &t->answer_ede_rcode, &t->answer_ede_msg);
1838
775ae354 1839 dns_transaction_complete(t, DNS_TRANSACTION_RCODE_FAILURE);
37baa00f 1840 }
775ae354
LP
1841 return 0;
1842 }
4d926a69 1843 }
ec2c5e43
LP
1844 }
1845
775ae354
LP
1846 if (FLAGS_SET(t->query_flags, SD_RESOLVED_NO_NETWORK)) {
1847 dns_transaction_complete(t, DNS_TRANSACTION_NO_SOURCE);
1848 return 0;
1849 }
1850
1effe965
DM
1851 return 1;
1852}
1853
325513bc
YW
1854static int dns_packet_append_zone(DnsPacket *p, DnsTransaction *t, DnsResourceKey *k, unsigned *nscount) {
1855 _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL;
1856 bool tentative;
1857 int r;
1858
1859 assert(p);
1860 assert(t);
1861 assert(k);
1862
1863 if (k->type != DNS_TYPE_ANY)
1864 return 0;
1865
1866 r = dns_zone_lookup(&t->scope->zone, k, t->scope->link->ifindex, &answer, NULL, &tentative);
1867 if (r < 0)
1868 return r;
1869
1870 return dns_packet_append_answer(p, answer, nscount);
1871}
1872
7645e5a8 1873static int mdns_make_dummy_packet(DnsTransaction *t, DnsPacket **ret_packet, Set **ret_keys) {
0afa57e2 1874 _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
0d5ee47d 1875 _cleanup_set_free_ Set *keys = NULL;
325513bc 1876 bool add_known_answers = false;
7645e5a8 1877 unsigned qdcount;
0afa57e2
DM
1878 usec_t ts;
1879 int r;
1880
1881 assert(t);
7645e5a8 1882 assert(t->scope);
0afa57e2 1883 assert(t->scope->protocol == DNS_PROTOCOL_MDNS);
7645e5a8
YW
1884 assert(ret_packet);
1885 assert(ret_keys);
0afa57e2 1886
0afa57e2
DM
1887 r = dns_packet_new_query(&p, t->scope->protocol, 0, false);
1888 if (r < 0)
1889 return r;
1890
42df9532 1891 r = dns_packet_append_key(p, dns_transaction_key(t), 0, NULL);
0afa57e2
DM
1892 if (r < 0)
1893 return r;
1894
1895 qdcount = 1;
1896
42df9532 1897 if (dns_key_is_shared(dns_transaction_key(t)))
7778dfff
DM
1898 add_known_answers = true;
1899
325513bc
YW
1900 r = dns_packet_append_zone(p, t, dns_transaction_key(t), NULL);
1901 if (r < 0)
1902 return r;
1903
1904 /* Save appended keys */
1905 r = set_ensure_put(&keys, &dns_resource_key_hash_ops, dns_transaction_key(t));
1906 if (r < 0)
1907 return r;
0d5ee47d 1908
ba4e0427 1909 assert_se(sd_event_now(t->scope->manager->event, CLOCK_BOOTTIME, &ts) >= 0);
0afa57e2 1910
7645e5a8 1911 LIST_FOREACH(transactions_by_scope, other, t->scope->transactions) {
0afa57e2 1912
7645e5a8
YW
1913 /* Skip ourselves */
1914 if (other == t)
1915 continue;
0afa57e2 1916
7645e5a8
YW
1917 if (other->state != DNS_TRANSACTION_PENDING)
1918 continue;
0afa57e2 1919
7645e5a8
YW
1920 if (other->next_attempt_after > ts)
1921 continue;
0afa57e2 1922
7645e5a8
YW
1923 if (!set_contains(keys, dns_transaction_key(other))) {
1924 size_t saved_packet_size;
0afa57e2 1925
7645e5a8
YW
1926 r = dns_packet_append_key(p, dns_transaction_key(other), 0, &saved_packet_size);
1927 /* If we can't stuff more questions into the packet, just give up.
1928 * One of the 'other' transactions will fire later and take care of the rest. */
1929 if (r == -EMSGSIZE)
1930 break;
325513bc
YW
1931 if (r < 0)
1932 return r;
0afa57e2 1933
7645e5a8
YW
1934 r = dns_packet_append_zone(p, t, dns_transaction_key(other), NULL);
1935 if (r == -EMSGSIZE) {
1936 dns_packet_truncate(p, saved_packet_size);
325513bc
YW
1937 break;
1938 }
7645e5a8
YW
1939 if (r < 0)
1940 return r;
aa4a9deb 1941
7645e5a8 1942 r = set_ensure_put(&keys, &dns_resource_key_hash_ops, dns_transaction_key(other));
325513bc
YW
1943 if (r < 0)
1944 return r;
7645e5a8
YW
1945 }
1946
1947 r = dns_transaction_prepare(other, ts);
1948 if (r < 0)
1949 return r;
1950 if (r == 0)
1951 /* In this case, not only this transaction, but multiple transactions may be
1952 * freed. Hence, we need to restart the loop. */
1953 return -EAGAIN;
0afa57e2 1954
7645e5a8
YW
1955 usec_t timeout = transaction_get_resend_timeout(other);
1956 r = dns_transaction_setup_timeout(other, timeout, usec_add(ts, timeout));
1957 if (r < 0)
1958 return r;
7778dfff 1959
7645e5a8
YW
1960 if (dns_key_is_shared(dns_transaction_key(other)))
1961 add_known_answers = true;
0d5ee47d 1962
7645e5a8
YW
1963 qdcount++;
1964 if (qdcount >= UINT16_MAX)
1965 break;
0afa57e2
DM
1966 }
1967
7645e5a8
YW
1968 DNS_PACKET_HEADER(p)->qdcount = htobe16(qdcount);
1969
1970 /* Append known answers section if we're asking for any shared record */
7778dfff 1971 if (add_known_answers) {
325513bc 1972 r = dns_cache_export_shared_to_packet(&t->scope->cache, p, ts, 0);
7778dfff
DM
1973 if (r < 0)
1974 return r;
7645e5a8 1975 }
325513bc 1976
7645e5a8
YW
1977 *ret_packet = TAKE_PTR(p);
1978 *ret_keys = TAKE_PTR(keys);
1979 return add_known_answers;
1980}
1981
1982static int dns_transaction_make_packet_mdns(DnsTransaction *t) {
1983 _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL, *dummy = NULL;
1984 _cleanup_set_free_ Set *keys = NULL;
1985 bool add_known_answers;
1986 DnsResourceKey *k;
1987 unsigned c;
1988 int r;
1989
1990 assert(t);
1991 assert(t->scope->protocol == DNS_PROTOCOL_MDNS);
1992
1993 /* Discard any previously prepared packet, so we can start over and coalesce again */
1994 t->sent = dns_packet_unref(t->sent);
1995
1996 /* First, create a dummy packet to calculate the number of known answers to be appended in the first packet. */
1997 for (;;) {
1998 r = mdns_make_dummy_packet(t, &dummy, &keys);
1999 if (r == -EAGAIN)
2000 continue;
2001 if (r < 0)
2002 return r;
2003
2004 add_known_answers = r;
2005 break;
7778dfff
DM
2006 }
2007
5162b2a1 2008 /* Then, create actual packet. */
325513bc
YW
2009 r = dns_packet_new_query(&p, t->scope->protocol, 0, false);
2010 if (r < 0)
2011 return r;
2012
2013 /* Questions */
7645e5a8 2014 c = 0;
325513bc
YW
2015 SET_FOREACH(k, keys) {
2016 r = dns_packet_append_key(p, k, 0, NULL);
2017 if (r < 0)
2018 return r;
7645e5a8 2019 c++;
325513bc 2020 }
7645e5a8 2021 DNS_PACKET_HEADER(p)->qdcount = htobe16(c);
0d5ee47d 2022
325513bc
YW
2023 /* Known answers */
2024 if (add_known_answers) {
7645e5a8
YW
2025 usec_t ts;
2026
2027 assert_se(sd_event_now(t->scope->manager->event, CLOCK_BOOTTIME, &ts) >= 0);
2028
2029 r = dns_cache_export_shared_to_packet(&t->scope->cache, p, ts, be16toh(DNS_PACKET_HEADER(dummy)->ancount));
0d5ee47d
DR
2030 if (r < 0)
2031 return r;
325513bc 2032 }
0d5ee47d 2033
325513bc 2034 /* Authorities */
7645e5a8 2035 c = 0;
325513bc 2036 SET_FOREACH(k, keys) {
7645e5a8 2037 r = dns_packet_append_zone(p, t, k, &c);
0d5ee47d
DR
2038 if (r < 0)
2039 return r;
0d5ee47d 2040 }
7645e5a8 2041 DNS_PACKET_HEADER(p)->nscount = htobe16(c);
0d5ee47d 2042
1cc6c93a 2043 t->sent = TAKE_PTR(p);
0afa57e2
DM
2044 return 0;
2045}
2046
2047static int dns_transaction_make_packet(DnsTransaction *t) {
2048 _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
2049 int r;
2050
2051 assert(t);
2052
2053 if (t->scope->protocol == DNS_PROTOCOL_MDNS)
2054 return dns_transaction_make_packet_mdns(t);
2055
2056 if (t->sent)
2057 return 0;
2058
775ae354
LP
2059 if (t->bypass && t->bypass->protocol == t->scope->protocol) {
2060 /* If bypass logic is enabled and the protocol if the original packet and our scope match,
2061 * take the original packet, copy it, and patch in our new ID */
2062 r = dns_packet_dup(&p, t->bypass);
2063 if (r < 0)
2064 return r;
2065 } else {
2066 r = dns_packet_new_query(
2067 &p, t->scope->protocol,
2068 /* min_alloc_dsize = */ 0,
2069 /* dnssec_cd = */ !FLAGS_SET(t->query_flags, SD_RESOLVED_NO_VALIDATE) &&
2070 t->scope->dnssec_mode != DNSSEC_NO);
2071 if (r < 0)
2072 return r;
0afa57e2 2073
775ae354
LP
2074 r = dns_packet_append_key(p, dns_transaction_key(t), 0, NULL);
2075 if (r < 0)
2076 return r;
2077
2078 DNS_PACKET_HEADER(p)->qdcount = htobe16(1);
2079 }
0afa57e2 2080
0afa57e2
DM
2081 DNS_PACKET_HEADER(p)->id = t->id;
2082
1cc6c93a 2083 t->sent = TAKE_PTR(p);
0afa57e2
DM
2084 return 0;
2085}
2086
1effe965
DM
2087int dns_transaction_go(DnsTransaction *t) {
2088 usec_t ts;
2089 int r;
202b76ae 2090 char key_str[DNS_RESOURCE_KEY_STRING_MAX];
1effe965
DM
2091
2092 assert(t);
2093
4ea8b443
ZJS
2094 /* Returns > 0 if the transaction is now pending, returns 0 if could be processed immediately and has
2095 * finished now. In the latter case, the transaction and query candidate objects must not be accessed.
2096 */
5278bbfe 2097
ba4e0427 2098 assert_se(sd_event_now(t->scope->manager->event, CLOCK_BOOTTIME, &ts) >= 0);
547973de 2099
c842ff24 2100 r = dns_transaction_prepare(t, ts);
1effe965
DM
2101 if (r <= 0)
2102 return r;
2103
213cb4f7
LP
2104 log_debug("Firing %s transaction %" PRIu16 " for <%s> scope %s on %s/%s (validate=%s).",
2105 t->bypass ? "bypass" : "regular",
a5784c49 2106 t->id,
42df9532 2107 dns_resource_key_to_string(dns_transaction_key(t), key_str, sizeof key_str),
a5784c49 2108 dns_protocol_to_string(t->scope->protocol),
6ff79f76 2109 t->scope->link ? t->scope->link->ifname : "*",
775ae354
LP
2110 af_to_name_short(t->scope->family),
2111 yes_no(!FLAGS_SET(t->query_flags, SD_RESOLVED_NO_VALIDATE)));
1effe965 2112
ef7ce6df 2113 if (!t->initial_jitter_scheduled &&
3742095b 2114 IN_SET(t->scope->protocol, DNS_PROTOCOL_LLMNR, DNS_PROTOCOL_MDNS)) {
765647ba 2115 usec_t jitter;
6e068472 2116
765647ba
YW
2117 /* RFC 4795 Section 2.7 suggests all LLMNR queries should be delayed by a random time from 0 to
2118 * JITTER_INTERVAL.
2119 * RFC 6762 Section 8.1 suggests initial probe queries should be delayed by a random time from
2120 * 0 to 250ms. */
6e068472 2121
ef7ce6df 2122 t->initial_jitter_scheduled = true;
87b91644 2123 t->n_attempts = 0;
6e068472 2124
ea12bcc7 2125 switch (t->scope->protocol) {
519ef046 2126
ea12bcc7 2127 case DNS_PROTOCOL_LLMNR:
9ee18bf4 2128 jitter = random_u64_range(LLMNR_JITTER_INTERVAL_USEC);
ea12bcc7 2129 break;
519ef046 2130
ea12bcc7 2131 case DNS_PROTOCOL_MDNS:
765647ba
YW
2132 if (t->probing)
2133 jitter = random_u64_range(MDNS_PROBING_INTERVAL_USEC);
2134 else
2135 jitter = 0;
ea12bcc7
DM
2136 break;
2137 default:
04499a70 2138 assert_not_reached();
ea12bcc7 2139 }
6e068472 2140
87b91644 2141 r = dns_transaction_setup_timeout(t, jitter, ts);
6e068472
LP
2142 if (r < 0)
2143 return r;
2144
2f9c3b2a
LP
2145 log_debug("Delaying %s transaction %" PRIu16 " for " USEC_FMT "us.",
2146 dns_protocol_to_string(t->scope->protocol),
2147 t->id,
2148 jitter);
4ea8b443 2149 return 1;
6e068472
LP
2150 }
2151
ec2c5e43
LP
2152 /* Otherwise, we need to ask the network */
2153 r = dns_transaction_make_packet(t);
ec2c5e43
LP
2154 if (r < 0)
2155 return r;
2156
2157 if (t->scope->protocol == DNS_PROTOCOL_LLMNR &&
42df9532
LP
2158 (dns_name_endswith(dns_resource_key_name(dns_transaction_key(t)), "in-addr.arpa") > 0 ||
2159 dns_name_endswith(dns_resource_key_name(dns_transaction_key(t)), "ip6.arpa") > 0)) {
ec2c5e43
LP
2160
2161 /* RFC 4795, Section 2.4. says reverse lookups shall
2162 * always be made via TCP on LLMNR */
98767d75 2163 r = dns_transaction_emit_tcp(t);
ec2c5e43 2164 } else {
be808ea0
TG
2165 /* Try via UDP, and if that fails due to large size or lack of
2166 * support try via TCP */
49cce12d 2167 r = dns_transaction_emit_udp(t);
29ab0552
LP
2168 if (r == -EMSGSIZE)
2169 log_debug("Sending query via TCP since it is too large.");
dc349f5f 2170 else if (r == -EAGAIN)
6c0bacc1 2171 log_debug("Sending query via TCP since UDP isn't supported or DNS-over-TLS is selected.");
3dd6336a
JB
2172 else if (r == -EPERM)
2173 log_debug("Sending query via TCP since UDP is blocked.");
2174 if (IN_SET(r, -EMSGSIZE, -EAGAIN, -EPERM))
98767d75 2175 r = dns_transaction_emit_tcp(t);
ec2c5e43 2176 }
49ef064c
LP
2177 if (r == -ELOOP) {
2178 if (t->scope->protocol != DNS_PROTOCOL_DNS)
2179 return r;
2180
2181 /* One of our own stub listeners */
2182 log_debug_errno(r, "Detected that specified DNS server is our own extra listener, switching DNS servers.");
2183
5e8bc852 2184 dns_scope_next_dns_server(t->scope, t->server);
49ef064c
LP
2185
2186 if (dns_scope_get_dns_server(t->scope) == t->server) {
2187 log_debug_errno(r, "Still pointing to extra listener after switching DNS servers, refusing operation.");
2188 dns_transaction_complete(t, DNS_TRANSACTION_STUB_LOOP);
2189 return 0;
2190 }
be808ea0 2191
49ef064c
LP
2192 return dns_transaction_go(t);
2193 }
ec2c5e43
LP
2194 if (r == -ESRCH) {
2195 /* No servers to send this to? */
2196 dns_transaction_complete(t, DNS_TRANSACTION_NO_SERVERS);
2197 return 0;
91adc4db
LP
2198 }
2199 if (r == -EOPNOTSUPP) {
2200 /* Tried to ask for DNSSEC RRs, on a server that doesn't do DNSSEC */
2201 dns_transaction_complete(t, DNS_TRANSACTION_RR_TYPE_UNSUPPORTED);
2202 return 0;
2203 }
13d84288 2204 if (t->scope->protocol == DNS_PROTOCOL_LLMNR && ERRNO_IS_NEG_DISCONNECT(r)) {
e94968ba 2205 /* On LLMNR, if we cannot connect to a host via TCP when doing reverse lookups. This means we cannot
0791110f
LP
2206 * answer this request with this protocol. */
2207 dns_transaction_complete(t, DNS_TRANSACTION_NOT_FOUND);
2208 return 0;
2209 }
91adc4db 2210 if (r < 0) {
7cc6ed7b
LP
2211 if (t->scope->protocol != DNS_PROTOCOL_DNS)
2212 return r;
13b551ac 2213
ec2c5e43 2214 /* Couldn't send? Try immediately again, with a new server */
5e8bc852 2215 dns_scope_next_dns_server(t->scope, t->server);
ec2c5e43
LP
2216
2217 return dns_transaction_go(t);
2218 }
2219
87b91644
YW
2220 usec_t timeout = transaction_get_resend_timeout(t);
2221 r = dns_transaction_setup_timeout(t, timeout, usec_add(ts, timeout));
ec2c5e43
LP
2222 if (r < 0)
2223 return r;
2224
ec2c5e43
LP
2225 return 1;
2226}
2227
f2992dc1
LP
2228static int dns_transaction_find_cyclic(DnsTransaction *t, DnsTransaction *aux) {
2229 DnsTransaction *n;
f2992dc1
LP
2230 int r;
2231
2232 assert(t);
2233 assert(aux);
2234
2235 /* Try to find cyclic dependencies between transaction objects */
2236
2237 if (t == aux)
2238 return 1;
2239
90e74a66 2240 SET_FOREACH(n, aux->dnssec_transactions) {
f2992dc1
LP
2241 r = dns_transaction_find_cyclic(t, n);
2242 if (r != 0)
2243 return r;
2244 }
2245
3eb6aa00 2246 return 0;
f2992dc1
LP
2247}
2248
547973de 2249static int dns_transaction_add_dnssec_transaction(DnsTransaction *t, DnsResourceKey *key, DnsTransaction **ret) {
29bd6012 2250 _cleanup_(dns_transaction_gcp) DnsTransaction *aux = NULL;
547973de
LP
2251 int r;
2252
2253 assert(t);
2254 assert(ret);
2255 assert(key);
2256
775ae354 2257 aux = dns_scope_find_transaction(t->scope, key, t->query_flags);
547973de 2258 if (!aux) {
775ae354 2259 r = dns_transaction_new(&aux, t->scope, key, NULL, t->query_flags);
547973de
LP
2260 if (r < 0)
2261 return r;
2262 } else {
2263 if (set_contains(t->dnssec_transactions, aux)) {
2264 *ret = aux;
2265 return 0;
2266 }
f2992dc1
LP
2267
2268 r = dns_transaction_find_cyclic(t, aux);
2269 if (r < 0)
2270 return r;
2271 if (r > 0) {
202b76ae
ZJS
2272 char s[DNS_RESOURCE_KEY_STRING_MAX], saux[DNS_RESOURCE_KEY_STRING_MAX];
2273
baaa35ad
ZJS
2274 return log_debug_errno(SYNTHETIC_ERRNO(ELOOP),
2275 "Potential cyclic dependency, refusing to add transaction %" PRIu16 " (%s) as dependency for %" PRIu16 " (%s).",
2276 aux->id,
42df9532 2277 dns_resource_key_to_string(dns_transaction_key(t), s, sizeof s),
baaa35ad 2278 t->id,
42df9532 2279 dns_resource_key_to_string(dns_transaction_key(aux), saux, sizeof saux));
f2992dc1 2280 }
547973de
LP
2281 }
2282
35aa04e9
LP
2283 r = set_ensure_allocated(&aux->notify_transactions_done, NULL);
2284 if (r < 0)
29bd6012 2285 return r;
547973de 2286
de7fef4b 2287 r = set_ensure_put(&t->dnssec_transactions, NULL, aux);
547973de 2288 if (r < 0)
a75cb4e2 2289 return r;
547973de 2290
de7fef4b 2291 r = set_ensure_put(&aux->notify_transactions, NULL, t);
547973de
LP
2292 if (r < 0) {
2293 (void) set_remove(t->dnssec_transactions, aux);
29bd6012 2294 return r;
547973de
LP
2295 }
2296
29bd6012 2297 *ret = TAKE_PTR(aux);
547973de 2298 return 1;
547973de
LP
2299}
2300
2301static int dns_transaction_request_dnssec_rr(DnsTransaction *t, DnsResourceKey *key) {
2302 _cleanup_(dns_answer_unrefp) DnsAnswer *a = NULL;
2303 DnsTransaction *aux;
2304 int r;
2305
2306 assert(t);
2307 assert(key);
2308
2309 /* Try to get the data from the trust anchor */
8e54f5d9 2310 r = dns_trust_anchor_lookup_positive(&t->scope->manager->trust_anchor, key, &a);
547973de
LP
2311 if (r < 0)
2312 return r;
2313 if (r > 0) {
2314 r = dns_answer_extend(&t->validated_keys, a);
2315 if (r < 0)
2316 return r;
2317
2318 return 0;
2319 }
2320
2321 /* This didn't work, ask for it via the network/cache then. */
2322 r = dns_transaction_add_dnssec_transaction(t, key, &aux);
f2992dc1
LP
2323 if (r == -ELOOP) /* This would result in a cyclic dependency */
2324 return 0;
547973de
LP
2325 if (r < 0)
2326 return r;
2327
2328 if (aux->state == DNS_TRANSACTION_NULL) {
2329 r = dns_transaction_go(aux);
2330 if (r < 0)
2331 return r;
2332 }
2333
f2992dc1 2334 return 1;
547973de
LP
2335}
2336
8a516214
LP
2337static int dns_transaction_negative_trust_anchor_lookup(DnsTransaction *t, const char *name) {
2338 int r;
2339
2340 assert(t);
2341
c629ff58 2342 /* Check whether the specified name is in the NTA
8a516214
LP
2343 * database, either in the global one, or the link-local
2344 * one. */
2345
2346 r = dns_trust_anchor_lookup_negative(&t->scope->manager->trust_anchor, name);
2347 if (r != 0)
2348 return r;
2349
2350 if (!t->scope->link)
2351 return 0;
2352
7e8a93b7 2353 return link_negative_trust_anchor_lookup(t->scope->link, name);
8a516214
LP
2354}
2355
26b23d11 2356static int dns_transaction_has_negative_answer(DnsTransaction *t) {
105e1512
LP
2357 int r;
2358
2359 assert(t);
2360
2361 /* Checks whether the answer is negative, and lacks NSEC/NSEC3
2362 * RRs to prove it */
2363
2364 r = dns_transaction_has_positive_answer(t, NULL);
2365 if (r < 0)
2366 return r;
2367 if (r > 0)
2368 return false;
2369
8e54f5d9
LP
2370 /* Is this key explicitly listed as a negative trust anchor?
2371 * If so, it's nothing we need to care about */
42df9532 2372 r = dns_transaction_negative_trust_anchor_lookup(t, dns_resource_key_name(dns_transaction_key(t)));
8e54f5d9
LP
2373 if (r < 0)
2374 return r;
26b23d11 2375 return !r;
105e1512
LP
2376}
2377
2378static int dns_transaction_is_primary_response(DnsTransaction *t, DnsResourceRecord *rr) {
2379 int r;
2380
2381 assert(t);
2382 assert(rr);
2383
2384 /* Check if the specified RR is the "primary" response,
2385 * i.e. either matches the question precisely or is a
4cb94977 2386 * CNAME/DNAME for it. */
105e1512 2387
42df9532 2388 r = dns_resource_key_match_rr(dns_transaction_key(t), rr, NULL);
105e1512
LP
2389 if (r != 0)
2390 return r;
2391
42df9532 2392 return dns_resource_key_match_cname_or_dname(dns_transaction_key(t), rr->key, NULL);
105e1512
LP
2393}
2394
92ec902a
LP
2395static bool dns_transaction_dnssec_supported(DnsTransaction *t) {
2396 assert(t);
2397
2398 /* Checks whether our transaction's DNS server is assumed to be compatible with DNSSEC. Returns false as soon
2399 * as we changed our mind about a server, and now believe it is incompatible with DNSSEC. */
2400
2401 if (t->scope->protocol != DNS_PROTOCOL_DNS)
2402 return false;
2403
2404 /* If we have picked no server, then we are working from the cache or some other source, and DNSSEC might well
2405 * be supported, hence return true. */
2406 if (!t->server)
2407 return true;
2408
d001e0a3
LP
2409 /* Note that we do not check the feature level actually used for the transaction but instead the feature level
2410 * the server is known to support currently, as the transaction feature level might be lower than what the
2411 * server actually supports, since we might have downgraded this transaction's feature level because we got a
2412 * SERVFAIL earlier and wanted to check whether downgrading fixes it. */
92ec902a
LP
2413
2414 return dns_server_dnssec_supported(t->server);
2415}
2416
2417static bool dns_transaction_dnssec_supported_full(DnsTransaction *t) {
2418 DnsTransaction *dt;
92ec902a
LP
2419
2420 assert(t);
2421
2422 /* Checks whether our transaction our any of the auxiliary transactions couldn't do DNSSEC. */
2423
2424 if (!dns_transaction_dnssec_supported(t))
2425 return false;
2426
90e74a66 2427 SET_FOREACH(dt, t->dnssec_transactions)
92ec902a
LP
2428 if (!dns_transaction_dnssec_supported(dt))
2429 return false;
2430
2431 return true;
2432}
2433
547973de
LP
2434int dns_transaction_request_dnssec_keys(DnsTransaction *t) {
2435 DnsResourceRecord *rr;
105e1512 2436
547973de
LP
2437 int r;
2438
2439 assert(t);
2440
105e1512
LP
2441 /*
2442 * Retrieve all auxiliary RRs for the answer we got, so that
2443 * we can verify signatures or prove that RRs are rightfully
2444 * unsigned. Specifically:
2445 *
2446 * - For RRSIG we get the matching DNSKEY
2447 * - For DNSKEY we get the matching DS
2448 * - For unsigned SOA/NS we get the matching DS
b63fca62 2449 * - For unsigned CNAME/DNAME/DS we get the parent SOA RR
105e1512 2450 * - For other unsigned RRs we get the matching SOA RR
4bbc06cc
LP
2451 * - For SOA/NS queries with no matching response RR, and no NSEC/NSEC3, the DS RR
2452 * - For DS queries with no matching response RRs, and no NSEC/NSEC3, the parent's SOA RR
105e1512
LP
2453 * - For other queries with no matching response RRs, and no NSEC/NSEC3, the SOA RR
2454 */
2455
775ae354 2456 if (FLAGS_SET(t->query_flags, SD_RESOLVED_NO_VALIDATE) || t->scope->dnssec_mode == DNSSEC_NO)
547973de 2457 return 0;
92ec902a
LP
2458 if (t->answer_source != DNS_TRANSACTION_NETWORK)
2459 return 0; /* We only need to validate stuff from the network */
2460 if (!dns_transaction_dnssec_supported(t))
5238e957 2461 return 0; /* If we can't do DNSSEC anyway there's no point in getting the auxiliary RRs */
b652d4a2 2462
547973de
LP
2463 DNS_ANSWER_FOREACH(rr, t->answer) {
2464
105e1512
LP
2465 if (dns_type_is_pseudo(rr->key->type))
2466 continue;
2467
8e54f5d9 2468 /* If this RR is in the negative trust anchor, we don't need to validate it. */
1c02e7ba 2469 r = dns_transaction_negative_trust_anchor_lookup(t, dns_resource_key_name(rr->key));
8e54f5d9
LP
2470 if (r < 0)
2471 return r;
2472 if (r > 0)
2473 continue;
2474
547973de
LP
2475 switch (rr->key->type) {
2476
2477 case DNS_TYPE_RRSIG: {
2478 /* For each RRSIG we request the matching DNSKEY */
2479 _cleanup_(dns_resource_key_unrefp) DnsResourceKey *dnskey = NULL;
2480
2481 /* If this RRSIG is about a DNSKEY RR and the
2482 * signer is the same as the owner, then we
2483 * already have the DNSKEY, and we don't have
2484 * to look for more. */
2485 if (rr->rrsig.type_covered == DNS_TYPE_DNSKEY) {
1c02e7ba 2486 r = dns_name_equal(rr->rrsig.signer, dns_resource_key_name(rr->key));
547973de
LP
2487 if (r < 0)
2488 return r;
2489 if (r > 0)
2490 continue;
2491 }
2492
105e1512
LP
2493 /* If the signer is not a parent of our
2494 * original query, then this is about an
2495 * auxiliary RRset, but not anything we asked
2496 * for. In this case we aren't interested,
2497 * because we don't want to request additional
2498 * RRs for stuff we didn't really ask for, and
2499 * also to avoid request loops, where
2500 * additional RRs from one transaction result
5238e957 2501 * in another transaction whose additional RRs
105e1512
LP
2502 * point back to the original transaction, and
2503 * we deadlock. */
42df9532 2504 r = dns_name_endswith(dns_resource_key_name(dns_transaction_key(t)), rr->rrsig.signer);
547973de
LP
2505 if (r < 0)
2506 return r;
2507 if (r == 0)
2508 continue;
2509
2510 dnskey = dns_resource_key_new(rr->key->class, DNS_TYPE_DNSKEY, rr->rrsig.signer);
2511 if (!dnskey)
2512 return -ENOMEM;
2513
1c02e7ba
ZJS
2514 log_debug("Requesting DNSKEY to validate transaction %" PRIu16" (%s, RRSIG with key tag: %" PRIu16 ").",
2515 t->id, dns_resource_key_name(rr->key), rr->rrsig.key_tag);
547973de
LP
2516 r = dns_transaction_request_dnssec_rr(t, dnskey);
2517 if (r < 0)
2518 return r;
2519 break;
2520 }
2521
2522 case DNS_TYPE_DNSKEY: {
2523 /* For each DNSKEY we request the matching DS */
2524 _cleanup_(dns_resource_key_unrefp) DnsResourceKey *ds = NULL;
2525
105e1512
LP
2526 /* If the DNSKEY we are looking at is not for
2527 * zone we are interested in, nor any of its
2528 * parents, we aren't interested, and don't
2529 * request it. After all, we don't want to end
2530 * up in request loops, and want to keep
2531 * additional traffic down. */
2532
42df9532 2533 r = dns_name_endswith(dns_resource_key_name(dns_transaction_key(t)), dns_resource_key_name(rr->key));
105e1512
LP
2534 if (r < 0)
2535 return r;
2536 if (r == 0)
2537 continue;
2538
1c02e7ba 2539 ds = dns_resource_key_new(rr->key->class, DNS_TYPE_DS, dns_resource_key_name(rr->key));
547973de
LP
2540 if (!ds)
2541 return -ENOMEM;
2542
1c02e7ba
ZJS
2543 log_debug("Requesting DS to validate transaction %" PRIu16" (%s, DNSKEY with key tag: %" PRIu16 ").",
2544 t->id, dns_resource_key_name(rr->key), dnssec_keytag(rr, false));
105e1512
LP
2545 r = dns_transaction_request_dnssec_rr(t, ds);
2546 if (r < 0)
2547 return r;
547973de 2548
105e1512
LP
2549 break;
2550 }
2551
105e1512
LP
2552 case DNS_TYPE_SOA:
2553 case DNS_TYPE_NS: {
2554 _cleanup_(dns_resource_key_unrefp) DnsResourceKey *ds = NULL;
2555
2556 /* For an unsigned SOA or NS, try to acquire
2557 * the matching DS RR, as we are at a zone cut
2558 * then, and whether a DS exists tells us
2559 * whether the zone is signed. Do so only if
2560 * this RR matches our original question,
2561 * however. */
2562
42df9532 2563 r = dns_resource_key_match_rr(dns_transaction_key(t), rr, NULL);
105e1512
LP
2564 if (r < 0)
2565 return r;
6993d264
LP
2566 if (r == 0) {
2567 /* Hmm, so this SOA RR doesn't match our original question. In this case, maybe this is
d51c4fca 2568 * a negative reply, and we need the SOA RR's TTL in order to cache a negative entry?
6993d264
LP
2569 * If so, we need to validate it, too. */
2570
42df9532 2571 r = dns_answer_match_key(t->answer, dns_transaction_key(t), NULL);
6993d264
LP
2572 if (r < 0)
2573 return r;
2574 if (r > 0) /* positive reply, we won't need the SOA and hence don't need to validate
2575 * it. */
2576 continue;
d5acaa51
LP
2577
2578 /* Only bother with this if the SOA/NS RR we are looking at is actually a parent of
2579 * what we are looking for, otherwise there's no value in it for us. */
42df9532 2580 r = dns_name_endswith(dns_resource_key_name(dns_transaction_key(t)), dns_resource_key_name(rr->key));
d5acaa51
LP
2581 if (r < 0)
2582 return r;
2583 if (r == 0)
2584 continue;
6993d264 2585 }
105e1512
LP
2586
2587 r = dnssec_has_rrsig(t->answer, rr->key);
2588 if (r < 0)
2589 return r;
2590 if (r > 0)
2591 continue;
2592
1c02e7ba 2593 ds = dns_resource_key_new(rr->key->class, DNS_TYPE_DS, dns_resource_key_name(rr->key));
105e1512
LP
2594 if (!ds)
2595 return -ENOMEM;
2596
1c02e7ba
ZJS
2597 log_debug("Requesting DS to validate transaction %" PRIu16 " (%s, unsigned SOA/NS RRset).",
2598 t->id, dns_resource_key_name(rr->key));
547973de
LP
2599 r = dns_transaction_request_dnssec_rr(t, ds);
2600 if (r < 0)
2601 return r;
2602
2603 break;
105e1512
LP
2604 }
2605
b63fca62 2606 case DNS_TYPE_DS:
105e1512
LP
2607 case DNS_TYPE_CNAME:
2608 case DNS_TYPE_DNAME: {
2609 _cleanup_(dns_resource_key_unrefp) DnsResourceKey *soa = NULL;
2610 const char *name;
2611
2612 /* CNAMEs and DNAMEs cannot be located at a
2613 * zone apex, hence ask for the parent SOA for
2614 * unsigned CNAME/DNAME RRs, maybe that's the
2615 * apex. But do all that only if this is
2616 * actually a response to our original
b63fca62
LP
2617 * question.
2618 *
2619 * Similar for DS RRs, which are signed when
2620 * the parent SOA is signed. */
105e1512
LP
2621
2622 r = dns_transaction_is_primary_response(t, rr);
2623 if (r < 0)
2624 return r;
2625 if (r == 0)
2626 continue;
2627
2628 r = dnssec_has_rrsig(t->answer, rr->key);
2629 if (r < 0)
2630 return r;
2631 if (r > 0)
2632 continue;
2633
43e6779a
LP
2634 r = dns_answer_has_dname_for_cname(t->answer, rr);
2635 if (r < 0)
2636 return r;
2637 if (r > 0)
2638 continue;
2639
1c02e7ba 2640 name = dns_resource_key_name(rr->key);
105e1512
LP
2641 r = dns_name_parent(&name);
2642 if (r < 0)
2643 return r;
2644 if (r == 0)
2645 continue;
2646
2647 soa = dns_resource_key_new(rr->key->class, DNS_TYPE_SOA, name);
2648 if (!soa)
2649 return -ENOMEM;
2650
1c02e7ba
ZJS
2651 log_debug("Requesting parent SOA to validate transaction %" PRIu16 " (%s, unsigned CNAME/DNAME/DS RRset).",
2652 t->id, dns_resource_key_name(rr->key));
105e1512
LP
2653 r = dns_transaction_request_dnssec_rr(t, soa);
2654 if (r < 0)
2655 return r;
2656
2657 break;
2658 }
2659
2660 default: {
2661 _cleanup_(dns_resource_key_unrefp) DnsResourceKey *soa = NULL;
2662
b63fca62
LP
2663 /* For other unsigned RRsets (including
2664 * NSEC/NSEC3!), look for proof the zone is
2665 * unsigned, by requesting the SOA RR of the
2666 * zone. However, do so only if they are
2667 * directly relevant to our original
105e1512
LP
2668 * question. */
2669
2670 r = dns_transaction_is_primary_response(t, rr);
2671 if (r < 0)
2672 return r;
2673 if (r == 0)
2674 continue;
2675
2676 r = dnssec_has_rrsig(t->answer, rr->key);
2677 if (r < 0)
2678 return r;
2679 if (r > 0)
2680 continue;
2681
1c02e7ba 2682 soa = dns_resource_key_new(rr->key->class, DNS_TYPE_SOA, dns_resource_key_name(rr->key));
105e1512
LP
2683 if (!soa)
2684 return -ENOMEM;
2685
1c02e7ba
ZJS
2686 log_debug("Requesting SOA to validate transaction %" PRIu16 " (%s, unsigned non-SOA/NS RRset <%s>).",
2687 t->id, dns_resource_key_name(rr->key), dns_resource_record_to_string(rr));
105e1512
LP
2688 r = dns_transaction_request_dnssec_rr(t, soa);
2689 if (r < 0)
2690 return r;
2691 break;
547973de
LP
2692 }}
2693 }
2694
105e1512
LP
2695 /* Above, we requested everything necessary to validate what
2696 * we got. Now, let's request what we need to validate what we
2697 * didn't get... */
2698
26b23d11 2699 r = dns_transaction_has_negative_answer(t);
105e1512
LP
2700 if (r < 0)
2701 return r;
2702 if (r > 0) {
26b23d11 2703 const char *name, *signed_status;
4bbc06cc 2704 uint16_t type = 0;
105e1512 2705
42df9532 2706 name = dns_resource_key_name(dns_transaction_key(t));
26b23d11 2707 signed_status = dns_answer_contains_nsec_or_nsec3(t->answer) ? "signed" : "unsigned";
105e1512 2708
4bbc06cc
LP
2709 /* If this was a SOA or NS request, then check if there's a DS RR for the same domain. Note that this
2710 * could also be used as indication that we are not at a zone apex, but in real world setups there are
2711 * too many broken DNS servers (Hello, incapdns.net!) where non-terminal zones return NXDOMAIN even
2712 * though they have further children. If this was a DS request, then it's signed when the parent zone
2713 * is signed, hence ask the parent SOA in that case. If this was any other RR then ask for the SOA RR,
2714 * to see if that is signed. */
105e1512 2715
42df9532 2716 if (dns_transaction_key(t)->type == DNS_TYPE_DS) {
105e1512 2717 r = dns_name_parent(&name);
4bbc06cc
LP
2718 if (r > 0) {
2719 type = DNS_TYPE_SOA;
e2341b6b
DT
2720 log_debug("Requesting parent SOA (%s %s) to validate transaction %" PRIu16 " (%s, %s empty DS response).",
2721 special_glyph(SPECIAL_GLYPH_ARROW_RIGHT), name, t->id,
2722 dns_resource_key_name(dns_transaction_key(t)), signed_status);
4bbc06cc 2723 } else
105e1512 2724 name = NULL;
4bbc06cc 2725
42df9532 2726 } else if (IN_SET(dns_transaction_key(t)->type, DNS_TYPE_SOA, DNS_TYPE_NS)) {
4bbc06cc
LP
2727
2728 type = DNS_TYPE_DS;
e2341b6b
DT
2729 log_debug("Requesting DS (%s %s) to validate transaction %" PRIu16 " (%s, %s empty SOA/NS response).",
2730 special_glyph(SPECIAL_GLYPH_ARROW_RIGHT), name, t->id, name, signed_status);
4bbc06cc
LP
2731
2732 } else {
2733 type = DNS_TYPE_SOA;
e2341b6b
DT
2734 log_debug("Requesting SOA (%s %s) to validate transaction %" PRIu16 " (%s, %s empty non-SOA/NS/DS response).",
2735 special_glyph(SPECIAL_GLYPH_ARROW_RIGHT), name, t->id, name, signed_status);
4bbc06cc 2736 }
105e1512
LP
2737
2738 if (name) {
2739 _cleanup_(dns_resource_key_unrefp) DnsResourceKey *soa = NULL;
2740
42df9532 2741 soa = dns_resource_key_new(dns_transaction_key(t)->class, type, name);
105e1512
LP
2742 if (!soa)
2743 return -ENOMEM;
2744
2745 r = dns_transaction_request_dnssec_rr(t, soa);
2746 if (r < 0)
2747 return r;
2748 }
2749 }
2750
2751 return dns_transaction_dnssec_is_live(t);
547973de
LP
2752}
2753
2754void dns_transaction_notify(DnsTransaction *t, DnsTransaction *source) {
547973de 2755 assert(t);
547973de
LP
2756 assert(source);
2757
942eb2e7
LP
2758 /* Invoked whenever any of our auxiliary DNSSEC transactions completed its work. If the state is still PENDING,
2759 we are still in the loop that adds further DNSSEC transactions, hence don't check if we are ready yet. If
2760 the state is VALIDATING however, we should check if we are complete now. */
105e1512 2761
942eb2e7
LP
2762 if (t->state == DNS_TRANSACTION_VALIDATING)
2763 dns_transaction_process_dnssec(t);
547973de
LP
2764}
2765
105e1512 2766static int dns_transaction_validate_dnskey_by_ds(DnsTransaction *t) {
04617bf8
LP
2767 DnsAnswerItem *item;
2768 int r;
105e1512
LP
2769
2770 assert(t);
2771
2772 /* Add all DNSKEY RRs from the answer that are validated by DS
2773 * RRs from the list of validated keys to the list of
2774 * validated keys. */
2775
04617bf8 2776 DNS_ANSWER_FOREACH_ITEM(item, t->answer) {
105e1512 2777
04617bf8 2778 r = dnssec_verify_dnskey_by_ds_search(item->rr, t->validated_keys);
105e1512
LP
2779 if (r < 0)
2780 return r;
2781 if (r == 0)
2782 continue;
2783
2784 /* If so, the DNSKEY is validated too. */
04617bf8 2785 r = dns_answer_add_extend(&t->validated_keys, item->rr, item->ifindex, item->flags|DNS_ANSWER_AUTHENTICATED, item->rrsig);
105e1512
LP
2786 if (r < 0)
2787 return r;
2788 }
2789
2790 return 0;
2791}
2792
2793static int dns_transaction_requires_rrsig(DnsTransaction *t, DnsResourceRecord *rr) {
56352fe9
LP
2794 int r;
2795
2796 assert(t);
2797 assert(rr);
2798
105e1512
LP
2799 /* Checks if the RR we are looking for must be signed with an
2800 * RRSIG. This is used for positive responses. */
24a5b982 2801
b652d4a2 2802 if (t->scope->dnssec_mode == DNSSEC_NO)
105e1512 2803 return false;
56352fe9 2804
105e1512
LP
2805 if (dns_type_is_pseudo(rr->key->type))
2806 return -EINVAL;
56352fe9 2807
1c02e7ba 2808 r = dns_transaction_negative_trust_anchor_lookup(t, dns_resource_key_name(rr->key));
8e54f5d9
LP
2809 if (r < 0)
2810 return r;
2811 if (r > 0)
2812 return false;
2813
105e1512 2814 switch (rr->key->type) {
56352fe9 2815
105e1512
LP
2816 case DNS_TYPE_RRSIG:
2817 /* RRSIGs are the signatures themselves, they need no signing. */
2818 return false;
2819
2820 case DNS_TYPE_SOA:
2821 case DNS_TYPE_NS: {
2822 DnsTransaction *dt;
105e1512 2823
b63fca62 2824 /* For SOA or NS RRs we look for a matching DS transaction */
105e1512 2825
90e74a66 2826 SET_FOREACH(dt, t->dnssec_transactions) {
105e1512 2827
42df9532 2828 if (dns_transaction_key(dt)->class != rr->key->class)
105e1512 2829 continue;
42df9532 2830 if (dns_transaction_key(dt)->type != DNS_TYPE_DS)
105e1512
LP
2831 continue;
2832
42df9532 2833 r = dns_name_equal(dns_resource_key_name(dns_transaction_key(dt)), dns_resource_key_name(rr->key));
105e1512
LP
2834 if (r < 0)
2835 return r;
2836 if (r == 0)
2837 continue;
2838
2839 /* We found a DS transactions for the SOA/NS
2840 * RRs we are looking at. If it discovered signed DS
2841 * RRs, then we need to be signed, too. */
2842
6f055e43 2843 if (!FLAGS_SET(dt->answer_query_flags, SD_RESOLVED_AUTHENTICATED))
097a2517 2844 return false;
105e1512 2845
42df9532 2846 return dns_answer_match_key(dt->answer, dns_transaction_key(dt), NULL);
105e1512
LP
2847 }
2848
2849 /* We found nothing that proves this is safe to leave
2850 * this unauthenticated, hence ask inist on
2851 * authentication. */
2852 return true;
2853 }
2854
b63fca62 2855 case DNS_TYPE_DS:
105e1512
LP
2856 case DNS_TYPE_CNAME:
2857 case DNS_TYPE_DNAME: {
2858 const char *parent = NULL;
2859 DnsTransaction *dt;
105e1512 2860
b63fca62
LP
2861 /*
2862 * CNAME/DNAME RRs cannot be located at a zone apex, hence look directly for the parent SOA.
2863 *
2864 * DS RRs are signed if the parent is signed, hence also look at the parent SOA
2865 */
105e1512 2866
90e74a66 2867 SET_FOREACH(dt, t->dnssec_transactions) {
105e1512 2868
42df9532 2869 if (dns_transaction_key(dt)->class != rr->key->class)
105e1512 2870 continue;
42df9532 2871 if (dns_transaction_key(dt)->type != DNS_TYPE_SOA)
105e1512
LP
2872 continue;
2873
2874 if (!parent) {
1c02e7ba 2875 parent = dns_resource_key_name(rr->key);
105e1512
LP
2876 r = dns_name_parent(&parent);
2877 if (r < 0)
2878 return r;
2879 if (r == 0) {
b63fca62
LP
2880 if (rr->key->type == DNS_TYPE_DS)
2881 return true;
2882
105e1512 2883 /* A CNAME/DNAME without a parent? That's sooo weird. */
baaa35ad
ZJS
2884 return log_debug_errno(SYNTHETIC_ERRNO(EBADMSG),
2885 "Transaction %" PRIu16 " claims CNAME/DNAME at root. Refusing.", t->id);
105e1512
LP
2886 }
2887 }
2888
42df9532 2889 r = dns_name_equal(dns_resource_key_name(dns_transaction_key(dt)), parent);
105e1512
LP
2890 if (r < 0)
2891 return r;
2892 if (r == 0)
2893 continue;
2894
3b4cc143 2895 return FLAGS_SET(dt->answer_query_flags, SD_RESOLVED_AUTHENTICATED);
105e1512
LP
2896 }
2897
2898 return true;
2899 }
2900
2901 default: {
2902 DnsTransaction *dt;
105e1512 2903
b63fca62 2904 /* Any other kind of RR (including DNSKEY/NSEC/NSEC3). Let's see if our SOA lookup was authenticated */
105e1512 2905
90e74a66 2906 SET_FOREACH(dt, t->dnssec_transactions) {
105e1512 2907
42df9532 2908 if (dns_transaction_key(dt)->class != rr->key->class)
105e1512 2909 continue;
42df9532 2910 if (dns_transaction_key(dt)->type != DNS_TYPE_SOA)
105e1512
LP
2911 continue;
2912
42df9532 2913 r = dns_name_equal(dns_resource_key_name(dns_transaction_key(dt)), dns_resource_key_name(rr->key));
105e1512
LP
2914 if (r < 0)
2915 return r;
2916 if (r == 0)
2917 continue;
2918
6f055e43
LP
2919 /* We found the transaction that was supposed to find the SOA RR for us. It was
2920 * successful, but found no RR for us. This means we are not at a zone cut. In this
2921 * case, we require authentication if the SOA lookup was authenticated too. */
3b4cc143 2922 return FLAGS_SET(dt->answer_query_flags, SD_RESOLVED_AUTHENTICATED);
105e1512
LP
2923 }
2924
2925 return true;
2926 }}
56352fe9
LP
2927}
2928
d33b6cf3
LP
2929static int dns_transaction_in_private_tld(DnsTransaction *t, const DnsResourceKey *key) {
2930 DnsTransaction *dt;
2931 const char *tld;
d33b6cf3
LP
2932 int r;
2933
2934 /* If DNSSEC downgrade mode is on, checks whether the
2935 * specified RR is one level below a TLD we have proven not to
2936 * exist. In such a case we assume that this is a private
2937 * domain, and permit it.
2938 *
2939 * This detects cases like the Fritz!Box router networks. Each
2940 * Fritz!Box router serves a private "fritz.box" zone, in the
2941 * non-existing TLD "box". Requests for the "fritz.box" domain
2942 * are served by the router itself, while requests for the
2943 * "box" domain will result in NXDOMAIN.
2944 *
2945 * Note that this logic is unable to detect cases where a
2946 * router serves a private DNS zone directly under
2947 * non-existing TLD. In such a case we cannot detect whether
2948 * the TLD is supposed to exist or not, as all requests we
2949 * make for it will be answered by the router's zone, and not
2950 * by the root zone. */
2951
2952 assert(t);
2953
2954 if (t->scope->dnssec_mode != DNSSEC_ALLOW_DOWNGRADE)
2955 return false; /* In strict DNSSEC mode what doesn't exist, doesn't exist */
2956
1c02e7ba 2957 tld = dns_resource_key_name(key);
d33b6cf3
LP
2958 r = dns_name_parent(&tld);
2959 if (r < 0)
2960 return r;
2961 if (r == 0)
2962 return false; /* Already the root domain */
2963
2964 if (!dns_name_is_single_label(tld))
2965 return false;
2966
90e74a66 2967 SET_FOREACH(dt, t->dnssec_transactions) {
d33b6cf3 2968
42df9532 2969 if (dns_transaction_key(dt)->class != key->class)
d33b6cf3
LP
2970 continue;
2971
42df9532 2972 r = dns_name_equal(dns_resource_key_name(dns_transaction_key(dt)), tld);
d33b6cf3
LP
2973 if (r < 0)
2974 return r;
2975 if (r == 0)
2976 continue;
2977
2978 /* We found an auxiliary lookup we did for the TLD. If
2979 * that returned with NXDOMAIN, we know the TLD didn't
2980 * exist, and hence this might be a private zone. */
2981
2982 return dt->answer_rcode == DNS_RCODE_NXDOMAIN;
2983 }
2984
2985 return false;
2986}
2987
105e1512 2988static int dns_transaction_requires_nsec(DnsTransaction *t) {
4bbc06cc 2989 char key_str[DNS_RESOURCE_KEY_STRING_MAX];
105e1512
LP
2990 DnsTransaction *dt;
2991 const char *name;
4bbc06cc 2992 uint16_t type = 0;
105e1512 2993 int r;
56352fe9
LP
2994
2995 assert(t);
2996
105e1512
LP
2997 /* Checks if we need to insist on NSEC/NSEC3 RRs for proving
2998 * this negative reply */
56352fe9 2999
b652d4a2 3000 if (t->scope->dnssec_mode == DNSSEC_NO)
105e1512 3001 return false;
56352fe9 3002
42df9532 3003 if (dns_type_is_pseudo(dns_transaction_key(t)->type))
105e1512
LP
3004 return -EINVAL;
3005
42df9532 3006 r = dns_transaction_negative_trust_anchor_lookup(t, dns_resource_key_name(dns_transaction_key(t)));
8e54f5d9
LP
3007 if (r < 0)
3008 return r;
3009 if (r > 0)
3010 return false;
3011
42df9532 3012 r = dns_transaction_in_private_tld(t, dns_transaction_key(t));
d33b6cf3
LP
3013 if (r < 0)
3014 return r;
3015 if (r > 0) {
3016 /* The lookup is from a TLD that is proven not to
3017 * exist, and we are in downgrade mode, hence ignore
13e785f7 3018 * that fact that we didn't get any NSEC RRs. */
d33b6cf3 3019
202b76ae 3020 log_info("Detected a negative query %s in a private DNS zone, permitting unsigned response.",
42df9532 3021 dns_resource_key_to_string(dns_transaction_key(t), key_str, sizeof key_str));
d33b6cf3
LP
3022 return false;
3023 }
3024
42df9532 3025 name = dns_resource_key_name(dns_transaction_key(t));
105e1512 3026
42df9532 3027 if (dns_transaction_key(t)->type == DNS_TYPE_DS) {
105e1512 3028
4bbc06cc
LP
3029 /* We got a negative reply for this DS lookup? DS RRs are signed when their parent zone is signed,
3030 * hence check the parent SOA in this case. */
105e1512
LP
3031
3032 r = dns_name_parent(&name);
56352fe9
LP
3033 if (r < 0)
3034 return r;
3035 if (r == 0)
105e1512 3036 return true;
4bbc06cc
LP
3037
3038 type = DNS_TYPE_SOA;
3039
42df9532 3040 } else if (IN_SET(dns_transaction_key(t)->type, DNS_TYPE_SOA, DNS_TYPE_NS))
4bbc06cc
LP
3041 /* We got a negative reply for this SOA/NS lookup? If so, check if there's a DS RR for this */
3042 type = DNS_TYPE_DS;
3043 else
3044 /* For all other negative replies, check for the SOA lookup */
3045 type = DNS_TYPE_SOA;
105e1512
LP
3046
3047 /* For all other RRs we check the SOA on the same level to see
3048 * if it's signed. */
3049
90e74a66 3050 SET_FOREACH(dt, t->dnssec_transactions) {
105e1512 3051
42df9532 3052 if (dns_transaction_key(dt)->class != dns_transaction_key(t)->class)
105e1512 3053 continue;
42df9532 3054 if (dns_transaction_key(dt)->type != type)
56352fe9
LP
3055 continue;
3056
42df9532 3057 r = dns_name_equal(dns_resource_key_name(dns_transaction_key(dt)), name);
56352fe9
LP
3058 if (r < 0)
3059 return r;
105e1512
LP
3060 if (r == 0)
3061 continue;
3062
6f055e43 3063 return FLAGS_SET(dt->answer_query_flags, SD_RESOLVED_AUTHENTICATED);
56352fe9
LP
3064 }
3065
105e1512
LP
3066 /* If in doubt, require NSEC/NSEC3 */
3067 return true;
56352fe9
LP
3068}
3069
94aa7071
LP
3070static int dns_transaction_dnskey_authenticated(DnsTransaction *t, DnsResourceRecord *rr) {
3071 DnsResourceRecord *rrsig;
3072 bool found = false;
3073 int r;
3074
3075 /* Checks whether any of the DNSKEYs used for the RRSIGs for
3076 * the specified RRset is authenticated (i.e. has a matching
3077 * DS RR). */
3078
1c02e7ba 3079 r = dns_transaction_negative_trust_anchor_lookup(t, dns_resource_key_name(rr->key));
8e54f5d9
LP
3080 if (r < 0)
3081 return r;
3082 if (r > 0)
3083 return false;
3084
94aa7071
LP
3085 DNS_ANSWER_FOREACH(rrsig, t->answer) {
3086 DnsTransaction *dt;
94aa7071
LP
3087
3088 r = dnssec_key_match_rrsig(rr->key, rrsig);
3089 if (r < 0)
3090 return r;
3091 if (r == 0)
3092 continue;
3093
90e74a66 3094 SET_FOREACH(dt, t->dnssec_transactions) {
94aa7071 3095
42df9532 3096 if (dns_transaction_key(dt)->class != rr->key->class)
94aa7071
LP
3097 continue;
3098
42df9532 3099 if (dns_transaction_key(dt)->type == DNS_TYPE_DNSKEY) {
94aa7071 3100
42df9532 3101 r = dns_name_equal(dns_resource_key_name(dns_transaction_key(dt)), rrsig->rrsig.signer);
94aa7071
LP
3102 if (r < 0)
3103 return r;
3104 if (r == 0)
3105 continue;
3106
6f055e43
LP
3107 /* OK, we found an auxiliary DNSKEY lookup. If that lookup is authenticated,
3108 * report this. */
94aa7071 3109
6f055e43 3110 if (FLAGS_SET(dt->answer_query_flags, SD_RESOLVED_AUTHENTICATED))
94aa7071
LP
3111 return true;
3112
3113 found = true;
3114
42df9532 3115 } else if (dns_transaction_key(dt)->type == DNS_TYPE_DS) {
94aa7071 3116
42df9532 3117 r = dns_name_equal(dns_resource_key_name(dns_transaction_key(dt)), rrsig->rrsig.signer);
94aa7071
LP
3118 if (r < 0)
3119 return r;
3120 if (r == 0)
3121 continue;
3122
6f055e43
LP
3123 /* OK, we found an auxiliary DS lookup. If that lookup is authenticated and
3124 * non-zero, we won! */
94aa7071 3125
6f055e43 3126 if (!FLAGS_SET(dt->answer_query_flags, SD_RESOLVED_AUTHENTICATED))
94aa7071
LP
3127 return false;
3128
42df9532 3129 return dns_answer_match_key(dt->answer, dns_transaction_key(dt), NULL);
94aa7071
LP
3130 }
3131 }
3132 }
3133
3134 return found ? false : -ENXIO;
3135}
3136
b652d4a2
LP
3137static int dns_transaction_known_signed(DnsTransaction *t, DnsResourceRecord *rr) {
3138 assert(t);
3139 assert(rr);
3140
3141 /* We know that the root domain is signed, hence if it appears
3142 * not to be signed, there's a problem with the DNS server */
3143
3144 return rr->key->class == DNS_CLASS_IN &&
1c02e7ba 3145 dns_name_is_root(dns_resource_key_name(rr->key));
b652d4a2
LP
3146}
3147
0f87f3e8
LP
3148static int dns_transaction_check_revoked_trust_anchors(DnsTransaction *t) {
3149 DnsResourceRecord *rr;
3150 int r;
3151
3152 assert(t);
3153
3154 /* Maybe warn the user that we encountered a revoked DNSKEY
3155 * for a key from our trust anchor. Note that we don't care
3156 * whether the DNSKEY can be authenticated or not. It's
3157 * sufficient if it is self-signed. */
3158
3159 DNS_ANSWER_FOREACH(rr, t->answer) {
d424da2a 3160 r = dns_trust_anchor_check_revoked(&t->scope->manager->trust_anchor, rr, t->answer);
0f87f3e8
LP
3161 if (r < 0)
3162 return r;
3163 }
3164
3165 return 0;
3166}
3167
c9c72065
LP
3168static int dns_transaction_invalidate_revoked_keys(DnsTransaction *t) {
3169 bool changed;
3170 int r;
3171
3172 assert(t);
3173
3174 /* Removes all DNSKEY/DS objects from t->validated_keys that
3175 * our trust anchors database considers revoked. */
3176
3177 do {
3178 DnsResourceRecord *rr;
3179
3180 changed = false;
3181
3182 DNS_ANSWER_FOREACH(rr, t->validated_keys) {
3183 r = dns_trust_anchor_is_revoked(&t->scope->manager->trust_anchor, rr);
3184 if (r < 0)
3185 return r;
3186 if (r > 0) {
3187 r = dns_answer_remove_by_rr(&t->validated_keys, rr);
3188 if (r < 0)
3189 return r;
3190
3191 assert(r > 0);
3192 changed = true;
3193 break;
3194 }
3195 }
3196 } while (changed);
3197
3198 return 0;
3199}
3200
942eb2e7
LP
3201static int dns_transaction_copy_validated(DnsTransaction *t) {
3202 DnsTransaction *dt;
942eb2e7
LP
3203 int r;
3204
3205 assert(t);
3206
3207 /* Copy all validated RRs from the auxiliary DNSSEC transactions into our set of validated RRs */
3208
90e74a66 3209 SET_FOREACH(dt, t->dnssec_transactions) {
942eb2e7
LP
3210
3211 if (DNS_TRANSACTION_IS_LIVE(dt->state))
3212 continue;
3213
6f055e43 3214 if (!FLAGS_SET(dt->answer_query_flags, SD_RESOLVED_AUTHENTICATED))
942eb2e7
LP
3215 continue;
3216
3217 r = dns_answer_extend(&t->validated_keys, dt->answer);
3218 if (r < 0)
3219 return r;
3220 }
3221
3222 return 0;
3223}
3224
c690b20a
ZJS
3225typedef enum {
3226 DNSSEC_PHASE_DNSKEY, /* Phase #1, only validate DNSKEYs */
3227 DNSSEC_PHASE_NSEC, /* Phase #2, only validate NSEC+NSEC3 */
3228 DNSSEC_PHASE_ALL, /* Phase #3, validate everything else */
3229} Phase;
3230
3231static int dnssec_validate_records(
3232 DnsTransaction *t,
3233 Phase phase,
3234 bool *have_nsec,
67d0ce88 3235 unsigned *nvalidations,
c690b20a
ZJS
3236 DnsAnswer **validated) {
3237
547973de 3238 DnsResourceRecord *rr;
56352fe9 3239 int r;
547973de 3240
67d0ce88
RP
3241 assert(nvalidations);
3242
c690b20a 3243 /* Returns negative on error, 0 if validation failed, 1 to restart validation, 2 when finished. */
547973de 3244
c690b20a 3245 DNS_ANSWER_FOREACH(rr, t->answer) {
71aee23d 3246 _unused_ _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr_ref = dns_resource_record_ref(rr);
c690b20a
ZJS
3247 DnsResourceRecord *rrsig = NULL;
3248 DnssecResult result;
547973de 3249
c690b20a
ZJS
3250 switch (rr->key->type) {
3251 case DNS_TYPE_RRSIG:
3252 continue;
547973de 3253
c690b20a
ZJS
3254 case DNS_TYPE_DNSKEY:
3255 /* We validate DNSKEYs only in the DNSKEY and ALL phases */
3256 if (phase == DNSSEC_PHASE_NSEC)
3257 continue;
3258 break;
547973de 3259
c690b20a
ZJS
3260 case DNS_TYPE_NSEC:
3261 case DNS_TYPE_NSEC3:
3262 *have_nsec = true;
547973de 3263
c690b20a
ZJS
3264 /* We validate NSEC/NSEC3 only in the NSEC and ALL phases */
3265 if (phase == DNSSEC_PHASE_DNSKEY)
3266 continue;
3267 break;
105e1512 3268
c690b20a
ZJS
3269 default:
3270 /* We validate all other RRs only in the ALL phases */
3271 if (phase != DNSSEC_PHASE_ALL)
3272 continue;
3273 }
b652d4a2 3274
04617bf8
LP
3275 r = dnssec_verify_rrset_search(
3276 t->answer,
3277 rr->key,
3278 t->validated_keys,
3279 USEC_INFINITY,
3280 &result,
3281 &rrsig);
c690b20a
ZJS
3282 if (r < 0)
3283 return r;
67d0ce88 3284 *nvalidations += r;
547973de 3285
c690b20a 3286 log_debug("Looking at %s: %s", strna(dns_resource_record_to_string(rr)), dnssec_result_to_string(result));
0f87f3e8 3287
c690b20a 3288 if (result == DNSSEC_VALIDATED) {
04617bf8 3289 assert(rrsig);
942eb2e7 3290
c690b20a
ZJS
3291 if (rr->key->type == DNS_TYPE_DNSKEY) {
3292 /* If we just validated a DNSKEY RRset, then let's add these keys to
3293 * the set of validated keys for this transaction. */
547973de 3294
04617bf8 3295 r = dns_answer_copy_by_key(&t->validated_keys, t->answer, rr->key, DNS_ANSWER_AUTHENTICATED, rrsig);
c690b20a
ZJS
3296 if (r < 0)
3297 return r;
c9c72065 3298
c690b20a
ZJS
3299 /* Some of the DNSKEYs we just added might already have been revoked,
3300 * remove them again in that case. */
3301 r = dns_transaction_invalidate_revoked_keys(t);
3302 if (r < 0)
3303 return r;
3304 }
547973de 3305
04617bf8
LP
3306 /* Add the validated RRset to the new list of validated RRsets, and remove it from
3307 * the unvalidated RRsets. We mark the RRset as authenticated and cacheable. */
3308 r = dns_answer_move_by_key(validated, &t->answer, rr->key, DNS_ANSWER_AUTHENTICATED|DNS_ANSWER_CACHEABLE, rrsig);
c690b20a
ZJS
3309 if (r < 0)
3310 return r;
547973de 3311
c690b20a 3312 manager_dnssec_verdict(t->scope->manager, DNSSEC_SECURE, rr->key);
0c7bff0a 3313
c690b20a
ZJS
3314 /* Exit the loop, we dropped something from the answer, start from the beginning */
3315 return 1;
3316 }
547973de 3317
c690b20a
ZJS
3318 /* If we haven't read all DNSKEYs yet a negative result of the validation is irrelevant, as
3319 * there might be more DNSKEYs coming. Similar, if we haven't read all NSEC/NSEC3 RRs yet,
3320 * we cannot do positive wildcard proofs yet, as those require the NSEC/NSEC3 RRs. */
3321 if (phase != DNSSEC_PHASE_ALL)
3322 continue;
0c7bff0a 3323
c690b20a
ZJS
3324 if (result == DNSSEC_VALIDATED_WILDCARD) {
3325 bool authenticated = false;
3326 const char *source;
0c7bff0a 3327
04617bf8
LP
3328 assert(rrsig);
3329
c690b20a 3330 /* This RRset validated, but as a wildcard. This means we need
13e785f7 3331 * to prove via NSEC/NSEC3 that no matching non-wildcard RR exists. */
0c7bff0a 3332
c690b20a
ZJS
3333 /* First step, determine the source of synthesis */
3334 r = dns_resource_record_source(rrsig, &source);
3335 if (r < 0)
3336 return r;
0c7bff0a 3337
c690b20a 3338 r = dnssec_test_positive_wildcard(*validated,
1c02e7ba 3339 dns_resource_key_name(rr->key),
c690b20a
ZJS
3340 source,
3341 rrsig->rrsig.signer,
3342 &authenticated);
0c7bff0a 3343
c690b20a
ZJS
3344 /* Unless the NSEC proof showed that the key really doesn't exist something is off. */
3345 if (r == 0)
3346 result = DNSSEC_INVALID;
3347 else {
04617bf8
LP
3348 r = dns_answer_move_by_key(
3349 validated,
3350 &t->answer,
3351 rr->key,
3352 authenticated ? (DNS_ANSWER_AUTHENTICATED|DNS_ANSWER_CACHEABLE) : 0,
3353 rrsig);
c690b20a
ZJS
3354 if (r < 0)
3355 return r;
3356
3357 manager_dnssec_verdict(t->scope->manager, authenticated ? DNSSEC_SECURE : DNSSEC_INSECURE, rr->key);
3358
3359 /* Exit the loop, we dropped something from the answer, start from the beginning */
3360 return 1;
0c7bff0a 3361 }
c690b20a 3362 }
0c7bff0a 3363
c690b20a
ZJS
3364 if (result == DNSSEC_NO_SIGNATURE) {
3365 r = dns_transaction_requires_rrsig(t, rr);
547973de
LP
3366 if (r < 0)
3367 return r;
c690b20a
ZJS
3368 if (r == 0) {
3369 /* Data does not require signing. In that case, just copy it over,
13e785f7 3370 * but remember that this is by no means authenticated. */
04617bf8
LP
3371 r = dns_answer_move_by_key(
3372 validated,
3373 &t->answer,
3374 rr->key,
3375 0,
3376 NULL);
c690b20a
ZJS
3377 if (r < 0)
3378 return r;
3379
3380 manager_dnssec_verdict(t->scope->manager, DNSSEC_INSECURE, rr->key);
3381 return 1;
3382 }
547973de 3383
c690b20a
ZJS
3384 r = dns_transaction_known_signed(t, rr);
3385 if (r < 0)
3386 return r;
3387 if (r > 0) {
3388 /* This is an RR we know has to be signed. If it isn't this means
3389 * the server is not attaching RRSIGs, hence complain. */
547973de 3390
c690b20a 3391 dns_server_packet_rrsig_missing(t->server, t->current_feature_level);
547973de 3392
c690b20a 3393 if (t->scope->dnssec_mode == DNSSEC_ALLOW_DOWNGRADE) {
547973de 3394
c690b20a 3395 /* Downgrading is OK? If so, just consider the information unsigned */
c9c72065 3396
04617bf8 3397 r = dns_answer_move_by_key(validated, &t->answer, rr->key, 0, NULL);
c9c72065
LP
3398 if (r < 0)
3399 return r;
547973de 3400
c690b20a
ZJS
3401 manager_dnssec_verdict(t->scope->manager, DNSSEC_INSECURE, rr->key);
3402 return 1;
3403 }
a150ff5e 3404
c690b20a
ZJS
3405 /* Otherwise, fail */
3406 t->answer_dnssec_result = DNSSEC_INCOMPATIBLE_SERVER;
3407 return 0;
f3cf586d 3408 }
547973de 3409
c690b20a
ZJS
3410 r = dns_transaction_in_private_tld(t, rr->key);
3411 if (r < 0)
3412 return r;
3413 if (r > 0) {
202b76ae 3414 char s[DNS_RESOURCE_KEY_STRING_MAX];
b652d4a2 3415
c690b20a
ZJS
3416 /* The data is from a TLD that is proven not to exist, and we are in downgrade
3417 * mode, hence ignore the fact that this was not signed. */
0c7bff0a 3418
202b76ae
ZJS
3419 log_info("Detected RRset %s is in a private DNS zone, permitting unsigned RRs.",
3420 dns_resource_key_to_string(rr->key, s, sizeof s));
0c7bff0a 3421
04617bf8 3422 r = dns_answer_move_by_key(validated, &t->answer, rr->key, 0, NULL);
0c7bff0a
LP
3423 if (r < 0)
3424 return r;
0c7bff0a 3425
c690b20a
ZJS
3426 manager_dnssec_verdict(t->scope->manager, DNSSEC_INSECURE, rr->key);
3427 return 1;
3428 }
3429 }
0c7bff0a 3430
1ca36001
JM
3431 /* https://datatracker.ietf.org/doc/html/rfc6840#section-5.2 */
3432 if (result == DNSSEC_UNSUPPORTED_ALGORITHM) {
3433 r = dns_answer_move_by_key(validated, &t->answer, rr->key, 0, NULL);
3434 if (r < 0)
3435 return r;
3436
3437 manager_dnssec_verdict(t->scope->manager, DNSSEC_INSECURE, rr->key);
3438 return 1;
3439 }
3440
c690b20a
ZJS
3441 if (IN_SET(result,
3442 DNSSEC_MISSING_KEY,
1ca36001 3443 DNSSEC_SIGNATURE_EXPIRED)) {
0c7bff0a 3444
c690b20a
ZJS
3445 r = dns_transaction_dnskey_authenticated(t, rr);
3446 if (r < 0 && r != -ENXIO)
3447 return r;
3448 if (r == 0) {
3449 /* The DNSKEY transaction was not authenticated, this means there's
3450 * no DS for this, which means it's OK if no keys are found for this signature. */
0c7bff0a 3451
04617bf8 3452 r = dns_answer_move_by_key(validated, &t->answer, rr->key, 0, NULL);
f3cf586d
LP
3453 if (r < 0)
3454 return r;
b652d4a2 3455
c690b20a
ZJS
3456 manager_dnssec_verdict(t->scope->manager, DNSSEC_INSECURE, rr->key);
3457 return 1;
3458 }
3459 }
b652d4a2 3460
c690b20a
ZJS
3461 r = dns_transaction_is_primary_response(t, rr);
3462 if (r < 0)
3463 return r;
3464 if (r > 0) {
3465 /* Look for a matching DNAME for this CNAME */
3466 r = dns_answer_has_dname_for_cname(t->answer, rr);
3467 if (r < 0)
3468 return r;
3469 if (r == 0) {
3470 /* Also look among the stuff we already validated */
3471 r = dns_answer_has_dname_for_cname(*validated, rr);
f3cf586d
LP
3472 if (r < 0)
3473 return r;
c690b20a 3474 }
d33b6cf3 3475
c690b20a
ZJS
3476 if (r == 0) {
3477 if (IN_SET(result,
3478 DNSSEC_INVALID,
3479 DNSSEC_SIGNATURE_EXPIRED,
3480 DNSSEC_NO_SIGNATURE))
3481 manager_dnssec_verdict(t->scope->manager, DNSSEC_BOGUS, rr->key);
67d0ce88
RP
3482 else /* DNSSEC_MISSING_KEY, DNSSEC_UNSUPPORTED_ALGORITHM,
3483 or DNSSEC_TOO_MANY_VALIDATIONS */
c690b20a
ZJS
3484 manager_dnssec_verdict(t->scope->manager, DNSSEC_INDETERMINATE, rr->key);
3485
3486 /* This is a primary response to our question, and it failed validation.
3487 * That's fatal. */
3488 t->answer_dnssec_result = result;
3489 return 0;
3490 }
d33b6cf3 3491
c690b20a
ZJS
3492 /* This is a primary response, but we do have a DNAME RR
3493 * in the RR that can replay this CNAME, hence rely on
3494 * that, and we can remove the CNAME in favour of it. */
3495 }
d33b6cf3 3496
c690b20a
ZJS
3497 /* This is just some auxiliary data. Just remove the RRset and continue. */
3498 r = dns_answer_remove_by_key(&t->answer, rr->key);
3499 if (r < 0)
3500 return r;
d33b6cf3 3501
c690b20a
ZJS
3502 /* We dropped something from the answer, start from the beginning. */
3503 return 1;
3504 }
f3cf586d 3505
c690b20a
ZJS
3506 return 2; /* Finito. */
3507}
94aa7071 3508
c690b20a
ZJS
3509int dns_transaction_validate_dnssec(DnsTransaction *t) {
3510 _cleanup_(dns_answer_unrefp) DnsAnswer *validated = NULL;
3511 Phase phase;
3512 DnsAnswerFlags flags;
3513 int r;
202b76ae 3514 char key_str[DNS_RESOURCE_KEY_STRING_MAX];
94aa7071 3515
c690b20a 3516 assert(t);
94aa7071 3517
775ae354 3518 /* We have now collected all DS and DNSKEY RRs in t->validated_keys, let's see which RRs we can now
c690b20a 3519 * authenticate with that. */
94aa7071 3520
775ae354 3521 if (FLAGS_SET(t->query_flags, SD_RESOLVED_NO_VALIDATE) || t->scope->dnssec_mode == DNSSEC_NO)
c690b20a 3522 return 0;
a150ff5e 3523
c690b20a
ZJS
3524 /* Already validated */
3525 if (t->answer_dnssec_result != _DNSSEC_RESULT_INVALID)
3526 return 0;
105e1512 3527
c690b20a
ZJS
3528 /* Our own stuff needs no validation */
3529 if (IN_SET(t->answer_source, DNS_TRANSACTION_ZONE, DNS_TRANSACTION_TRUST_ANCHOR)) {
3530 t->answer_dnssec_result = DNSSEC_VALIDATED;
6f055e43 3531 SET_FLAG(t->answer_query_flags, SD_RESOLVED_AUTHENTICATED, true);
c690b20a
ZJS
3532 return 0;
3533 }
a150ff5e 3534
c690b20a
ZJS
3535 /* Cached stuff is not affected by validation. */
3536 if (t->answer_source != DNS_TRANSACTION_NETWORK)
3537 return 0;
f3cf586d 3538
c690b20a
ZJS
3539 if (!dns_transaction_dnssec_supported_full(t)) {
3540 /* The server does not support DNSSEC, or doesn't augment responses with RRSIGs. */
3541 t->answer_dnssec_result = DNSSEC_INCOMPATIBLE_SERVER;
d001e0a3 3542 log_debug("Not validating response for %" PRIu16 ", used server feature level does not support DNSSEC.", t->id);
c690b20a
ZJS
3543 return 0;
3544 }
f3cf586d 3545
202b76ae
ZJS
3546 log_debug("Validating response from transaction %" PRIu16 " (%s).",
3547 t->id,
42df9532 3548 dns_resource_key_to_string(dns_transaction_key(t), key_str, sizeof key_str));
547973de 3549
c690b20a
ZJS
3550 /* First, see if this response contains any revoked trust
3551 * anchors we care about */
3552 r = dns_transaction_check_revoked_trust_anchors(t);
3553 if (r < 0)
3554 return r;
43e6779a 3555
c690b20a
ZJS
3556 /* Third, copy all RRs we acquired successfully from auxiliary RRs over. */
3557 r = dns_transaction_copy_validated(t);
3558 if (r < 0)
3559 return r;
43e6779a 3560
c690b20a
ZJS
3561 /* Second, see if there are DNSKEYs we already know a
3562 * validated DS for. */
3563 r = dns_transaction_validate_dnskey_by_ds(t);
3564 if (r < 0)
3565 return r;
43e6779a 3566
c690b20a
ZJS
3567 /* Fourth, remove all DNSKEY and DS RRs again that our trust
3568 * anchor says are revoked. After all we might have marked
3569 * some keys revoked above, but they might still be lingering
3570 * in our validated_keys list. */
3571 r = dns_transaction_invalidate_revoked_keys(t);
3572 if (r < 0)
3573 return r;
f3cf586d 3574
c690b20a 3575 phase = DNSSEC_PHASE_DNSKEY;
67d0ce88 3576 for (unsigned nvalidations = 0;;) {
c690b20a 3577 bool have_nsec = false;
f3cf586d 3578
67d0ce88 3579 r = dnssec_validate_records(t, phase, &have_nsec, &nvalidations, &validated);
c690b20a
ZJS
3580 if (r <= 0)
3581 return r;
547973de 3582
67d0ce88
RP
3583 if (nvalidations > DNSSEC_VALIDATION_MAX) {
3584 /* This reply requires an onerous number of signature validations to verify. Let's
3585 * not waste our time trying, as this shouldn't happen for well-behaved domains
3586 * anyway. */
3587 t->answer_dnssec_result = DNSSEC_TOO_MANY_VALIDATIONS;
3588 return 0;
3589 }
3590
c690b20a
ZJS
3591 /* Try again as long as we managed to achieve something */
3592 if (r == 1)
547973de
LP
3593 continue;
3594
c690b20a 3595 if (phase == DNSSEC_PHASE_DNSKEY && have_nsec) {
0c7bff0a 3596 /* OK, we processed all DNSKEYs, and there are NSEC/NSEC3 RRs, look at those now. */
c690b20a 3597 phase = DNSSEC_PHASE_NSEC;
0c7bff0a
LP
3598 continue;
3599 }
3600
c690b20a
ZJS
3601 if (phase != DNSSEC_PHASE_ALL) {
3602 /* OK, we processed all DNSKEYs and NSEC/NSEC3 RRs, look at all the rest now.
3603 * Note that in this third phase we start to remove RRs we couldn't validate. */
3604 phase = DNSSEC_PHASE_ALL;
56352fe9 3605 continue;
547973de
LP
3606 }
3607
56352fe9 3608 /* We're done */
547973de
LP
3609 break;
3610 }
3611
1117a960 3612 DNS_ANSWER_REPLACE(t->answer, TAKE_PTR(validated));
547973de 3613
72667f08
LP
3614 /* At this point the answer only contains validated
3615 * RRsets. Now, let's see if it actually answers the question
3616 * we asked. If so, great! If it doesn't, then see if
3617 * NSEC/NSEC3 can prove this. */
105e1512 3618 r = dns_transaction_has_positive_answer(t, &flags);
72667f08 3619 if (r > 0) {
105e1512
LP
3620 /* Yes, it answers the question! */
3621
3622 if (flags & DNS_ANSWER_AUTHENTICATED) {
3623 /* The answer is fully authenticated, yay. */
019036a4 3624 t->answer_dnssec_result = DNSSEC_VALIDATED;
105e1512 3625 t->answer_rcode = DNS_RCODE_SUCCESS;
6f055e43 3626 SET_FLAG(t->answer_query_flags, SD_RESOLVED_AUTHENTICATED, true);
105e1512
LP
3627 } else {
3628 /* The answer is not fully authenticated. */
019036a4 3629 t->answer_dnssec_result = DNSSEC_UNSIGNED;
6f055e43 3630 SET_FLAG(t->answer_query_flags, SD_RESOLVED_AUTHENTICATED, false);
105e1512
LP
3631 }
3632
72667f08
LP
3633 } else if (r == 0) {
3634 DnssecNsecResult nr;
ed29bfdc 3635 bool authenticated = false;
72667f08
LP
3636
3637 /* Bummer! Let's check NSEC/NSEC3 */
42df9532 3638 r = dnssec_nsec_test(t->answer, dns_transaction_key(t), &nr, &authenticated, &t->answer_nsec_ttl);
72667f08
LP
3639 if (r < 0)
3640 return r;
3641
3642 switch (nr) {
3643
3644 case DNSSEC_NSEC_NXDOMAIN:
3645 /* NSEC proves the domain doesn't exist. Very good. */
202b76ae 3646 log_debug("Proved NXDOMAIN via NSEC/NSEC3 for transaction %u (%s)", t->id, key_str);
019036a4 3647 t->answer_dnssec_result = DNSSEC_VALIDATED;
72667f08 3648 t->answer_rcode = DNS_RCODE_NXDOMAIN;
6f055e43 3649 SET_FLAG(t->answer_query_flags, SD_RESOLVED_AUTHENTICATED, authenticated);
7aa8ce98 3650
42df9532 3651 manager_dnssec_verdict(t->scope->manager, authenticated ? DNSSEC_SECURE : DNSSEC_INSECURE, dns_transaction_key(t));
72667f08
LP
3652 break;
3653
3654 case DNSSEC_NSEC_NODATA:
3655 /* NSEC proves that there's no data here, very good. */
202b76ae 3656 log_debug("Proved NODATA via NSEC/NSEC3 for transaction %u (%s)", t->id, key_str);
019036a4 3657 t->answer_dnssec_result = DNSSEC_VALIDATED;
72667f08 3658 t->answer_rcode = DNS_RCODE_SUCCESS;
6f055e43 3659 SET_FLAG(t->answer_query_flags, SD_RESOLVED_AUTHENTICATED, authenticated);
7aa8ce98 3660
42df9532 3661 manager_dnssec_verdict(t->scope->manager, authenticated ? DNSSEC_SECURE : DNSSEC_INSECURE, dns_transaction_key(t));
72667f08
LP
3662 break;
3663
105e1512
LP
3664 case DNSSEC_NSEC_OPTOUT:
3665 /* NSEC3 says the data might not be signed */
202b76ae 3666 log_debug("Data is NSEC3 opt-out via NSEC/NSEC3 for transaction %u (%s)", t->id, key_str);
019036a4 3667 t->answer_dnssec_result = DNSSEC_UNSIGNED;
6f055e43 3668 SET_FLAG(t->answer_query_flags, SD_RESOLVED_AUTHENTICATED, false);
7aa8ce98 3669
42df9532 3670 manager_dnssec_verdict(t->scope->manager, DNSSEC_INSECURE, dns_transaction_key(t));
105e1512
LP
3671 break;
3672
72667f08
LP
3673 case DNSSEC_NSEC_NO_RR:
3674 /* No NSEC data? Bummer! */
105e1512
LP
3675
3676 r = dns_transaction_requires_nsec(t);
3677 if (r < 0)
3678 return r;
7aa8ce98 3679 if (r > 0) {
019036a4 3680 t->answer_dnssec_result = DNSSEC_NO_SIGNATURE;
42df9532 3681 manager_dnssec_verdict(t->scope->manager, DNSSEC_BOGUS, dns_transaction_key(t));
7aa8ce98 3682 } else {
019036a4 3683 t->answer_dnssec_result = DNSSEC_UNSIGNED;
6f055e43 3684 SET_FLAG(t->answer_query_flags, SD_RESOLVED_AUTHENTICATED, false);
42df9532 3685 manager_dnssec_verdict(t->scope->manager, DNSSEC_INSECURE, dns_transaction_key(t));
105e1512
LP
3686 }
3687
3688 break;
3689
3690 case DNSSEC_NSEC_UNSUPPORTED_ALGORITHM:
3691 /* We don't know the NSEC3 algorithm used? */
019036a4 3692 t->answer_dnssec_result = DNSSEC_UNSUPPORTED_ALGORITHM;
42df9532 3693 manager_dnssec_verdict(t->scope->manager, DNSSEC_INDETERMINATE, dns_transaction_key(t));
72667f08
LP
3694 break;
3695
3696 case DNSSEC_NSEC_FOUND:
146035b3 3697 case DNSSEC_NSEC_CNAME:
72667f08 3698 /* NSEC says it needs to be there, but we couldn't find it? Bummer! */
019036a4 3699 t->answer_dnssec_result = DNSSEC_NSEC_MISMATCH;
42df9532 3700 manager_dnssec_verdict(t->scope->manager, DNSSEC_BOGUS, dns_transaction_key(t));
72667f08
LP
3701 break;
3702
3703 default:
04499a70 3704 assert_not_reached();
72667f08
LP
3705 }
3706 }
3707
547973de
LP
3708 return 1;
3709}
3710
ec2c5e43 3711static const char* const dns_transaction_state_table[_DNS_TRANSACTION_STATE_MAX] = {
e3e64a1a
ZJS
3712 [DNS_TRANSACTION_NULL] = "null",
3713 [DNS_TRANSACTION_PENDING] = "pending",
3714 [DNS_TRANSACTION_VALIDATING] = "validating",
3715 [DNS_TRANSACTION_RCODE_FAILURE] = "rcode-failure",
3716 [DNS_TRANSACTION_SUCCESS] = "success",
3717 [DNS_TRANSACTION_NO_SERVERS] = "no-servers",
3718 [DNS_TRANSACTION_TIMEOUT] = "timeout",
ec2c5e43 3719 [DNS_TRANSACTION_ATTEMPTS_MAX_REACHED] = "attempts-max-reached",
e3e64a1a
ZJS
3720 [DNS_TRANSACTION_INVALID_REPLY] = "invalid-reply",
3721 [DNS_TRANSACTION_ERRNO] = "errno",
3722 [DNS_TRANSACTION_ABORTED] = "aborted",
3723 [DNS_TRANSACTION_DNSSEC_FAILED] = "dnssec-failed",
3724 [DNS_TRANSACTION_NO_TRUST_ANCHOR] = "no-trust-anchor",
3725 [DNS_TRANSACTION_RR_TYPE_UNSUPPORTED] = "rr-type-unsupported",
3726 [DNS_TRANSACTION_NETWORK_DOWN] = "network-down",
3727 [DNS_TRANSACTION_NOT_FOUND] = "not-found",
3728 [DNS_TRANSACTION_NO_SOURCE] = "no-source",
3729 [DNS_TRANSACTION_STUB_LOOP] = "stub-loop",
ec2c5e43
LP
3730};
3731DEFINE_STRING_TABLE_LOOKUP(dns_transaction_state, DnsTransactionState);
c3bc53e6
LP
3732
3733static const char* const dns_transaction_source_table[_DNS_TRANSACTION_SOURCE_MAX] = {
e3e64a1a
ZJS
3734 [DNS_TRANSACTION_NETWORK] = "network",
3735 [DNS_TRANSACTION_CACHE] = "cache",
3736 [DNS_TRANSACTION_ZONE] = "zone",
0d2cd476 3737 [DNS_TRANSACTION_TRUST_ANCHOR] = "trust-anchor",
c3bc53e6
LP
3738};
3739DEFINE_STRING_TABLE_LOOKUP(dns_transaction_source, DnsTransactionSource);