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