]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/resolve/resolved-dns-query.c
5f51340743e44782d341445ff2b887878666c1cd
[thirdparty/systemd.git] / src / resolve / resolved-dns-query.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
2 /***
3 This file is part of systemd.
4
5 Copyright 2014 Lennart Poettering
6
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
11
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
19 ***/
20
21 #include "alloc-util.h"
22 #include "dns-domain.h"
23 #include "dns-type.h"
24 #include "hostname-util.h"
25 #include "local-addresses.h"
26 #include "resolved-dns-query.h"
27 #include "resolved-dns-synthesize.h"
28 #include "resolved-etc-hosts.h"
29 #include "string-util.h"
30
31 #define CNAME_MAX 8
32 #define QUERIES_MAX 2048
33 #define AUXILIARY_QUERIES_MAX 64
34
35 static int dns_query_candidate_new(DnsQueryCandidate **ret, DnsQuery *q, DnsScope *s) {
36 DnsQueryCandidate *c;
37
38 assert(ret);
39 assert(q);
40 assert(s);
41
42 c = new0(DnsQueryCandidate, 1);
43 if (!c)
44 return -ENOMEM;
45
46 c->query = q;
47 c->scope = s;
48
49 LIST_PREPEND(candidates_by_query, q->candidates, c);
50 LIST_PREPEND(candidates_by_scope, s->query_candidates, c);
51
52 *ret = c;
53 return 0;
54 }
55
56 static void dns_query_candidate_stop(DnsQueryCandidate *c) {
57 DnsTransaction *t;
58
59 assert(c);
60
61 while ((t = set_steal_first(c->transactions))) {
62 set_remove(t->notify_query_candidates, c);
63 set_remove(t->notify_query_candidates_done, c);
64 dns_transaction_gc(t);
65 }
66 }
67
68 DnsQueryCandidate* dns_query_candidate_free(DnsQueryCandidate *c) {
69
70 if (!c)
71 return NULL;
72
73 dns_query_candidate_stop(c);
74
75 set_free(c->transactions);
76 dns_search_domain_unref(c->search_domain);
77
78 if (c->query)
79 LIST_REMOVE(candidates_by_query, c->query->candidates, c);
80
81 if (c->scope)
82 LIST_REMOVE(candidates_by_scope, c->scope->query_candidates, c);
83
84 return mfree(c);
85 }
86
87 static int dns_query_candidate_next_search_domain(DnsQueryCandidate *c) {
88 DnsSearchDomain *next = NULL;
89
90 assert(c);
91
92 if (c->search_domain && c->search_domain->linked)
93 next = c->search_domain->domains_next;
94 else
95 next = dns_scope_get_search_domains(c->scope);
96
97 for (;;) {
98 if (!next) /* We hit the end of the list */
99 return 0;
100
101 if (!next->route_only)
102 break;
103
104 /* Skip over route-only domains */
105 next = next->domains_next;
106 }
107
108 dns_search_domain_unref(c->search_domain);
109 c->search_domain = dns_search_domain_ref(next);
110
111 return 1;
112 }
113
114 static int dns_query_candidate_add_transaction(DnsQueryCandidate *c, DnsResourceKey *key) {
115 DnsTransaction *t;
116 int r;
117
118 assert(c);
119 assert(key);
120
121 t = dns_scope_find_transaction(c->scope, key, true);
122 if (!t) {
123 r = dns_transaction_new(&t, c->scope, key);
124 if (r < 0)
125 return r;
126 } else {
127 if (set_contains(c->transactions, t))
128 return 0;
129 }
130
131 r = set_ensure_allocated(&c->transactions, NULL);
132 if (r < 0)
133 goto gc;
134
135 r = set_ensure_allocated(&t->notify_query_candidates, NULL);
136 if (r < 0)
137 goto gc;
138
139 r = set_ensure_allocated(&t->notify_query_candidates_done, NULL);
140 if (r < 0)
141 goto gc;
142
143 r = set_put(t->notify_query_candidates, c);
144 if (r < 0)
145 goto gc;
146
147 r = set_put(c->transactions, t);
148 if (r < 0) {
149 (void) set_remove(t->notify_query_candidates, c);
150 goto gc;
151 }
152
153 t->clamp_ttl = c->query->clamp_ttl;
154 return 1;
155
156 gc:
157 dns_transaction_gc(t);
158 return r;
159 }
160
161 static int dns_query_candidate_go(DnsQueryCandidate *c) {
162 DnsTransaction *t;
163 Iterator i;
164 int r;
165 unsigned n = 0;
166
167 assert(c);
168
169 /* Start the transactions that are not started yet */
170 SET_FOREACH(t, c->transactions, i) {
171 if (t->state != DNS_TRANSACTION_NULL)
172 continue;
173
174 r = dns_transaction_go(t);
175 if (r < 0)
176 return r;
177
178 n++;
179 }
180
181 /* If there was nothing to start, then let's proceed immediately */
182 if (n == 0)
183 dns_query_candidate_notify(c);
184
185 return 0;
186 }
187
188 static DnsTransactionState dns_query_candidate_state(DnsQueryCandidate *c) {
189 DnsTransactionState state = DNS_TRANSACTION_NO_SERVERS;
190 DnsTransaction *t;
191 Iterator i;
192
193 assert(c);
194
195 if (c->error_code != 0)
196 return DNS_TRANSACTION_ERRNO;
197
198 SET_FOREACH(t, c->transactions, i) {
199
200 switch (t->state) {
201
202 case DNS_TRANSACTION_NULL:
203 /* If there's a NULL transaction pending, then
204 * this means not all transactions where
205 * started yet, and we were called from within
206 * the stackframe that is supposed to start
207 * remaining transactions. In this case,
208 * simply claim the candidate is pending. */
209
210 case DNS_TRANSACTION_PENDING:
211 case DNS_TRANSACTION_VALIDATING:
212 /* If there's one transaction currently in
213 * VALIDATING state, then this means there's
214 * also one in PENDING state, hence we can
215 * return PENDING immediately. */
216 return DNS_TRANSACTION_PENDING;
217
218 case DNS_TRANSACTION_SUCCESS:
219 state = t->state;
220 break;
221
222 default:
223 if (state != DNS_TRANSACTION_SUCCESS)
224 state = t->state;
225
226 break;
227 }
228 }
229
230 return state;
231 }
232
233 static bool dns_query_candidate_is_routable(DnsQueryCandidate *c, uint16_t type) {
234 int family;
235
236 assert(c);
237
238 /* Checks whether the specified RR type matches an address family that is routable on the link(s) the scope of
239 * this candidate belongs to. Specifically, whether there's a routable IPv4 address on it if we query an A RR,
240 * or a routable IPv6 address if we query an AAAA RR. */
241
242 if (!c->query->suppress_unroutable_family)
243 return true;
244
245 if (c->scope->protocol != DNS_PROTOCOL_DNS)
246 return true;
247
248 family = dns_type_to_af(type);
249 if (family < 0)
250 return true;
251
252 if (c->scope->link)
253 return link_relevant(c->scope->link, family, false);
254 else
255 return manager_routable(c->scope->manager, family);
256 }
257
258 static int dns_query_candidate_setup_transactions(DnsQueryCandidate *c) {
259 DnsQuestion *question;
260 DnsResourceKey *key;
261 int n = 0, r;
262
263 assert(c);
264
265 dns_query_candidate_stop(c);
266
267 question = dns_query_question_for_protocol(c->query, c->scope->protocol);
268
269 /* Create one transaction per question key */
270 DNS_QUESTION_FOREACH(key, question) {
271 _cleanup_(dns_resource_key_unrefp) DnsResourceKey *new_key = NULL;
272 DnsResourceKey *qkey;
273
274 if (!dns_query_candidate_is_routable(c, key->type))
275 continue;
276
277 if (c->search_domain) {
278 r = dns_resource_key_new_append_suffix(&new_key, key, c->search_domain->name);
279 if (r < 0)
280 goto fail;
281
282 qkey = new_key;
283 } else
284 qkey = key;
285
286 if (!dns_scope_good_key(c->scope, qkey))
287 continue;
288
289 r = dns_query_candidate_add_transaction(c, qkey);
290 if (r < 0)
291 goto fail;
292
293 n++;
294 }
295
296 return n;
297
298 fail:
299 dns_query_candidate_stop(c);
300 return r;
301 }
302
303 void dns_query_candidate_notify(DnsQueryCandidate *c) {
304 DnsTransactionState state;
305 int r;
306
307 assert(c);
308
309 state = dns_query_candidate_state(c);
310
311 if (DNS_TRANSACTION_IS_LIVE(state))
312 return;
313
314 if (state != DNS_TRANSACTION_SUCCESS && c->search_domain) {
315
316 r = dns_query_candidate_next_search_domain(c);
317 if (r < 0)
318 goto fail;
319
320 if (r > 0) {
321 /* OK, there's another search domain to try, let's do so. */
322
323 r = dns_query_candidate_setup_transactions(c);
324 if (r < 0)
325 goto fail;
326
327 if (r > 0) {
328 /* New transactions where queued. Start them and wait */
329
330 r = dns_query_candidate_go(c);
331 if (r < 0)
332 goto fail;
333
334 return;
335 }
336 }
337
338 }
339
340 dns_query_ready(c->query);
341 return;
342
343 fail:
344 log_warning_errno(r, "Failed to follow search domains: %m");
345 c->error_code = r;
346 dns_query_ready(c->query);
347 }
348
349 static void dns_query_stop(DnsQuery *q) {
350 DnsQueryCandidate *c;
351
352 assert(q);
353
354 q->timeout_event_source = sd_event_source_unref(q->timeout_event_source);
355
356 LIST_FOREACH(candidates_by_query, c, q->candidates)
357 dns_query_candidate_stop(c);
358 }
359
360 static void dns_query_free_candidates(DnsQuery *q) {
361 assert(q);
362
363 while (q->candidates)
364 dns_query_candidate_free(q->candidates);
365 }
366
367 static void dns_query_reset_answer(DnsQuery *q) {
368 assert(q);
369
370 q->answer = dns_answer_unref(q->answer);
371 q->answer_rcode = 0;
372 q->answer_dnssec_result = _DNSSEC_RESULT_INVALID;
373 q->answer_errno = 0;
374 q->answer_authenticated = false;
375 q->answer_protocol = _DNS_PROTOCOL_INVALID;
376 q->answer_family = AF_UNSPEC;
377 q->answer_search_domain = dns_search_domain_unref(q->answer_search_domain);
378 }
379
380 DnsQuery *dns_query_free(DnsQuery *q) {
381 if (!q)
382 return NULL;
383
384 while (q->auxiliary_queries)
385 dns_query_free(q->auxiliary_queries);
386
387 if (q->auxiliary_for) {
388 assert(q->auxiliary_for->n_auxiliary_queries > 0);
389 q->auxiliary_for->n_auxiliary_queries--;
390 LIST_REMOVE(auxiliary_queries, q->auxiliary_for->auxiliary_queries, q);
391 }
392
393 dns_query_free_candidates(q);
394
395 dns_question_unref(q->question_idna);
396 dns_question_unref(q->question_utf8);
397
398 dns_query_reset_answer(q);
399
400 sd_bus_message_unref(q->request);
401 sd_bus_track_unref(q->bus_track);
402
403 dns_packet_unref(q->request_dns_packet);
404 dns_packet_unref(q->reply_dns_packet);
405
406 if (q->request_dns_stream) {
407 /* Detach the stream from our query, in case something else keeps a reference to it. */
408 q->request_dns_stream->complete = NULL;
409 q->request_dns_stream->on_packet = NULL;
410 q->request_dns_stream->query = NULL;
411 dns_stream_unref(q->request_dns_stream);
412 }
413
414 free(q->request_address_string);
415
416 if (q->manager) {
417 LIST_REMOVE(queries, q->manager->dns_queries, q);
418 q->manager->n_dns_queries--;
419 }
420
421 return mfree(q);
422 }
423
424 int dns_query_new(
425 Manager *m,
426 DnsQuery **ret,
427 DnsQuestion *question_utf8,
428 DnsQuestion *question_idna,
429 int ifindex,
430 uint64_t flags) {
431
432 _cleanup_(dns_query_freep) DnsQuery *q = NULL;
433 DnsResourceKey *key;
434 bool good = false;
435 int r;
436 char key_str[DNS_RESOURCE_KEY_STRING_MAX];
437
438 assert(m);
439
440 if (dns_question_size(question_utf8) > 0) {
441 r = dns_question_is_valid_for_query(question_utf8);
442 if (r < 0)
443 return r;
444 if (r == 0)
445 return -EINVAL;
446
447 good = true;
448 }
449
450 /* If the IDNA and UTF8 questions are the same, merge their references */
451 r = dns_question_is_equal(question_idna, question_utf8);
452 if (r < 0)
453 return r;
454 if (r > 0)
455 question_idna = question_utf8;
456 else {
457 if (dns_question_size(question_idna) > 0) {
458 r = dns_question_is_valid_for_query(question_idna);
459 if (r < 0)
460 return r;
461 if (r == 0)
462 return -EINVAL;
463
464 good = true;
465 }
466 }
467
468 if (!good) /* don't allow empty queries */
469 return -EINVAL;
470
471 if (m->n_dns_queries >= QUERIES_MAX)
472 return -EBUSY;
473
474 q = new0(DnsQuery, 1);
475 if (!q)
476 return -ENOMEM;
477
478 q->question_utf8 = dns_question_ref(question_utf8);
479 q->question_idna = dns_question_ref(question_idna);
480 q->ifindex = ifindex;
481 q->flags = flags;
482 q->answer_dnssec_result = _DNSSEC_RESULT_INVALID;
483 q->answer_protocol = _DNS_PROTOCOL_INVALID;
484 q->answer_family = AF_UNSPEC;
485
486 /* First dump UTF8 question */
487 DNS_QUESTION_FOREACH(key, question_utf8)
488 log_debug("Looking up RR for %s.",
489 dns_resource_key_to_string(key, key_str, sizeof key_str));
490
491 /* And then dump the IDNA question, but only what hasn't been dumped already through the UTF8 question. */
492 DNS_QUESTION_FOREACH(key, question_idna) {
493 r = dns_question_contains(question_utf8, key);
494 if (r < 0)
495 return r;
496 if (r > 0)
497 continue;
498
499 log_debug("Looking up IDNA RR for %s.",
500 dns_resource_key_to_string(key, key_str, sizeof key_str));
501 }
502
503 LIST_PREPEND(queries, m->dns_queries, q);
504 m->n_dns_queries++;
505 q->manager = m;
506
507 if (ret)
508 *ret = q;
509 q = NULL;
510
511 return 0;
512 }
513
514 int dns_query_make_auxiliary(DnsQuery *q, DnsQuery *auxiliary_for) {
515 assert(q);
516 assert(auxiliary_for);
517
518 /* Ensure that the query is not auxiliary yet, and
519 * nothing else is auxiliary to it either */
520 assert(!q->auxiliary_for);
521 assert(!q->auxiliary_queries);
522
523 /* Ensure that the unit we shall be made auxiliary for isn't
524 * auxiliary itself */
525 assert(!auxiliary_for->auxiliary_for);
526
527 if (auxiliary_for->n_auxiliary_queries >= AUXILIARY_QUERIES_MAX)
528 return -EAGAIN;
529
530 LIST_PREPEND(auxiliary_queries, auxiliary_for->auxiliary_queries, q);
531 q->auxiliary_for = auxiliary_for;
532
533 auxiliary_for->n_auxiliary_queries++;
534 return 0;
535 }
536
537 static void dns_query_complete(DnsQuery *q, DnsTransactionState state) {
538 assert(q);
539 assert(!DNS_TRANSACTION_IS_LIVE(state));
540 assert(DNS_TRANSACTION_IS_LIVE(q->state));
541
542 /* Note that this call might invalidate the query. Callers
543 * should hence not attempt to access the query or transaction
544 * after calling this function. */
545
546 q->state = state;
547
548 dns_query_stop(q);
549 if (q->complete)
550 q->complete(q);
551 }
552
553 static int on_query_timeout(sd_event_source *s, usec_t usec, void *userdata) {
554 DnsQuery *q = userdata;
555
556 assert(s);
557 assert(q);
558
559 dns_query_complete(q, DNS_TRANSACTION_TIMEOUT);
560 return 0;
561 }
562
563 static int dns_query_add_candidate(DnsQuery *q, DnsScope *s) {
564 DnsQueryCandidate *c;
565 int r;
566
567 assert(q);
568 assert(s);
569
570 r = dns_query_candidate_new(&c, q, s);
571 if (r < 0)
572 return r;
573
574 /* If this a single-label domain on DNS, we might append a suitable search domain first. */
575 if ((q->flags & SD_RESOLVED_NO_SEARCH) == 0) {
576 r = dns_scope_name_needs_search_domain(s, dns_question_first_name(q->question_idna));
577 if (r < 0)
578 goto fail;
579 if (r > 0) {
580 /* OK, we need a search domain now. Let's find one for this scope */
581
582 r = dns_query_candidate_next_search_domain(c);
583 if (r <= 0) /* if there's no search domain, then we won't add any transaction. */
584 goto fail;
585 }
586 }
587
588 r = dns_query_candidate_setup_transactions(c);
589 if (r < 0)
590 goto fail;
591
592 return 0;
593
594 fail:
595 dns_query_candidate_free(c);
596 return r;
597 }
598
599 static int dns_query_synthesize_reply(DnsQuery *q, DnsTransactionState *state) {
600 _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL;
601 int r;
602
603 assert(q);
604 assert(state);
605
606 /* Tries to synthesize localhost RR replies (and others) where appropriate. Note that this is done *after* the
607 * the normal lookup finished. The data from the network hence takes precedence over the data we
608 * synthesize. (But note that many scopes refuse to resolve certain domain names) */
609
610 if (!IN_SET(*state,
611 DNS_TRANSACTION_RCODE_FAILURE,
612 DNS_TRANSACTION_NO_SERVERS,
613 DNS_TRANSACTION_TIMEOUT,
614 DNS_TRANSACTION_ATTEMPTS_MAX_REACHED,
615 DNS_TRANSACTION_NETWORK_DOWN,
616 DNS_TRANSACTION_NOT_FOUND))
617 return 0;
618
619 r = dns_synthesize_answer(
620 q->manager,
621 q->question_utf8,
622 q->ifindex,
623 &answer);
624 if (r == -ENXIO) {
625 /* If we get ENXIO this tells us to generate NXDOMAIN unconditionally. */
626
627 dns_query_reset_answer(q);
628 q->answer_rcode = DNS_RCODE_NXDOMAIN;
629 q->answer_protocol = dns_synthesize_protocol(q->flags);
630 q->answer_family = dns_synthesize_family(q->flags);
631 q->answer_authenticated = true;
632 *state = DNS_TRANSACTION_RCODE_FAILURE;
633
634 return 0;
635 }
636 if (r <= 0)
637 return r;
638
639 dns_query_reset_answer(q);
640
641 q->answer = answer;
642 answer = NULL;
643 q->answer_rcode = DNS_RCODE_SUCCESS;
644 q->answer_protocol = dns_synthesize_protocol(q->flags);
645 q->answer_family = dns_synthesize_family(q->flags);
646 q->answer_authenticated = true;
647
648 *state = DNS_TRANSACTION_SUCCESS;
649
650 return 1;
651 }
652
653 static int dns_query_try_etc_hosts(DnsQuery *q) {
654 _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL;
655 int r;
656
657 assert(q);
658
659 /* Looks in /etc/hosts for matching entries. Note that this is done *before* the normal lookup is done. The
660 * data from /etc/hosts hence takes precedence over the network. */
661
662 r = manager_etc_hosts_lookup(
663 q->manager,
664 q->question_utf8,
665 &answer);
666 if (r <= 0)
667 return r;
668
669 dns_query_reset_answer(q);
670
671 q->answer = answer;
672 answer = NULL;
673 q->answer_rcode = DNS_RCODE_SUCCESS;
674 q->answer_protocol = dns_synthesize_protocol(q->flags);
675 q->answer_family = dns_synthesize_family(q->flags);
676 q->answer_authenticated = true;
677
678 return 1;
679 }
680
681 int dns_query_go(DnsQuery *q) {
682 DnsScopeMatch found = DNS_SCOPE_NO;
683 DnsScope *s, *first = NULL;
684 DnsQueryCandidate *c;
685 int r;
686
687 assert(q);
688
689 if (q->state != DNS_TRANSACTION_NULL)
690 return 0;
691
692 r = dns_query_try_etc_hosts(q);
693 if (r < 0)
694 return r;
695 if (r > 0) {
696 dns_query_complete(q, DNS_TRANSACTION_SUCCESS);
697 return 1;
698 }
699
700 LIST_FOREACH(scopes, s, q->manager->dns_scopes) {
701 DnsScopeMatch match;
702 const char *name;
703
704 name = dns_question_first_name(dns_query_question_for_protocol(q, s->protocol));
705 if (!name)
706 continue;
707
708 match = dns_scope_good_domain(s, q->ifindex, q->flags, name);
709 if (match < 0)
710 return match;
711
712 if (match == DNS_SCOPE_NO)
713 continue;
714
715 found = match;
716
717 if (match == DNS_SCOPE_YES) {
718 first = s;
719 break;
720 } else {
721 assert(match == DNS_SCOPE_MAYBE);
722
723 if (!first)
724 first = s;
725 }
726 }
727
728 if (found == DNS_SCOPE_NO) {
729 DnsTransactionState state = DNS_TRANSACTION_NO_SERVERS;
730
731 r = dns_query_synthesize_reply(q, &state);
732 if (r < 0)
733 return r;
734
735 dns_query_complete(q, state);
736 return 1;
737 }
738
739 r = dns_query_add_candidate(q, first);
740 if (r < 0)
741 goto fail;
742
743 LIST_FOREACH(scopes, s, first->scopes_next) {
744 DnsScopeMatch match;
745 const char *name;
746
747 name = dns_question_first_name(dns_query_question_for_protocol(q, s->protocol));
748 if (!name)
749 continue;
750
751 match = dns_scope_good_domain(s, q->ifindex, q->flags, name);
752 if (match < 0)
753 goto fail;
754
755 if (match != found)
756 continue;
757
758 r = dns_query_add_candidate(q, s);
759 if (r < 0)
760 goto fail;
761 }
762
763 dns_query_reset_answer(q);
764
765 r = sd_event_add_time(
766 q->manager->event,
767 &q->timeout_event_source,
768 clock_boottime_or_monotonic(),
769 now(clock_boottime_or_monotonic()) + SD_RESOLVED_QUERY_TIMEOUT_USEC,
770 0, on_query_timeout, q);
771 if (r < 0)
772 goto fail;
773
774 (void) sd_event_source_set_description(q->timeout_event_source, "query-timeout");
775
776 q->state = DNS_TRANSACTION_PENDING;
777 q->block_ready++;
778
779 /* Start the transactions */
780 LIST_FOREACH(candidates_by_query, c, q->candidates) {
781 r = dns_query_candidate_go(c);
782 if (r < 0) {
783 q->block_ready--;
784 goto fail;
785 }
786 }
787
788 q->block_ready--;
789 dns_query_ready(q);
790
791 return 1;
792
793 fail:
794 dns_query_stop(q);
795 return r;
796 }
797
798 static void dns_query_accept(DnsQuery *q, DnsQueryCandidate *c) {
799 DnsTransactionState state = DNS_TRANSACTION_NO_SERVERS;
800 bool has_authenticated = false, has_non_authenticated = false;
801 DnssecResult dnssec_result_authenticated = _DNSSEC_RESULT_INVALID, dnssec_result_non_authenticated = _DNSSEC_RESULT_INVALID;
802 DnsTransaction *t;
803 Iterator i;
804 int r;
805
806 assert(q);
807
808 if (!c) {
809 r = dns_query_synthesize_reply(q, &state);
810 if (r < 0)
811 goto fail;
812
813 dns_query_complete(q, state);
814 return;
815 }
816
817 if (c->error_code != 0) {
818 /* If the candidate had an error condition of its own, start with that. */
819 state = DNS_TRANSACTION_ERRNO;
820 q->answer = dns_answer_unref(q->answer);
821 q->answer_rcode = 0;
822 q->answer_dnssec_result = _DNSSEC_RESULT_INVALID;
823 q->answer_authenticated = false;
824 q->answer_errno = c->error_code;
825 }
826
827 SET_FOREACH(t, c->transactions, i) {
828
829 switch (t->state) {
830
831 case DNS_TRANSACTION_SUCCESS: {
832 /* We found a successfully reply, merge it into the answer */
833 r = dns_answer_extend(&q->answer, t->answer);
834 if (r < 0)
835 goto fail;
836
837 q->answer_rcode = t->answer_rcode;
838 q->answer_errno = 0;
839
840 if (t->answer_authenticated) {
841 has_authenticated = true;
842 dnssec_result_authenticated = t->answer_dnssec_result;
843 } else {
844 has_non_authenticated = true;
845 dnssec_result_non_authenticated = t->answer_dnssec_result;
846 }
847
848 state = DNS_TRANSACTION_SUCCESS;
849 break;
850 }
851
852 case DNS_TRANSACTION_NULL:
853 case DNS_TRANSACTION_PENDING:
854 case DNS_TRANSACTION_VALIDATING:
855 case DNS_TRANSACTION_ABORTED:
856 /* Ignore transactions that didn't complete */
857 continue;
858
859 default:
860 /* Any kind of failure? Store the data away, if there's nothing stored yet. */
861 if (state == DNS_TRANSACTION_SUCCESS)
862 continue;
863
864 /* If there's already an authenticated negative reply stored, then prefer that over any unauthenticated one */
865 if (q->answer_authenticated && !t->answer_authenticated)
866 continue;
867
868 q->answer = dns_answer_unref(q->answer);
869 q->answer_rcode = t->answer_rcode;
870 q->answer_dnssec_result = t->answer_dnssec_result;
871 q->answer_authenticated = t->answer_authenticated;
872 q->answer_errno = t->answer_errno;
873
874 state = t->state;
875 break;
876 }
877 }
878
879 if (state == DNS_TRANSACTION_SUCCESS) {
880 q->answer_authenticated = has_authenticated && !has_non_authenticated;
881 q->answer_dnssec_result = q->answer_authenticated ? dnssec_result_authenticated : dnssec_result_non_authenticated;
882 }
883
884 q->answer_protocol = c->scope->protocol;
885 q->answer_family = c->scope->family;
886
887 dns_search_domain_unref(q->answer_search_domain);
888 q->answer_search_domain = dns_search_domain_ref(c->search_domain);
889
890 r = dns_query_synthesize_reply(q, &state);
891 if (r < 0)
892 goto fail;
893
894 dns_query_complete(q, state);
895 return;
896
897 fail:
898 q->answer_errno = -r;
899 dns_query_complete(q, DNS_TRANSACTION_ERRNO);
900 }
901
902 void dns_query_ready(DnsQuery *q) {
903
904 DnsQueryCandidate *bad = NULL, *c;
905 bool pending = false;
906
907 assert(q);
908 assert(DNS_TRANSACTION_IS_LIVE(q->state));
909
910 /* Note that this call might invalidate the query. Callers
911 * should hence not attempt to access the query or transaction
912 * after calling this function, unless the block_ready
913 * counter was explicitly bumped before doing so. */
914
915 if (q->block_ready > 0)
916 return;
917
918 LIST_FOREACH(candidates_by_query, c, q->candidates) {
919 DnsTransactionState state;
920
921 state = dns_query_candidate_state(c);
922 switch (state) {
923
924 case DNS_TRANSACTION_SUCCESS:
925 /* One of the candidates is successful,
926 * let's use it, and copy its data out */
927 dns_query_accept(q, c);
928 return;
929
930 case DNS_TRANSACTION_NULL:
931 case DNS_TRANSACTION_PENDING:
932 case DNS_TRANSACTION_VALIDATING:
933 /* One of the candidates is still going on,
934 * let's maybe wait for it */
935 pending = true;
936 break;
937
938 default:
939 /* Any kind of failure */
940 bad = c;
941 break;
942 }
943 }
944
945 if (pending)
946 return;
947
948 dns_query_accept(q, bad);
949 }
950
951 static int dns_query_cname_redirect(DnsQuery *q, const DnsResourceRecord *cname) {
952 _cleanup_(dns_question_unrefp) DnsQuestion *nq_idna = NULL, *nq_utf8 = NULL;
953 int r, k;
954
955 assert(q);
956
957 q->n_cname_redirects++;
958 if (q->n_cname_redirects > CNAME_MAX)
959 return -ELOOP;
960
961 r = dns_question_cname_redirect(q->question_idna, cname, &nq_idna);
962 if (r < 0)
963 return r;
964 else if (r > 0)
965 log_debug("Following CNAME/DNAME %s → %s.", dns_question_first_name(q->question_idna), dns_question_first_name(nq_idna));
966
967 k = dns_question_is_equal(q->question_idna, q->question_utf8);
968 if (k < 0)
969 return r;
970 if (k > 0) {
971 /* Same question? Shortcut new question generation */
972 nq_utf8 = dns_question_ref(nq_idna);
973 k = r;
974 } else {
975 k = dns_question_cname_redirect(q->question_utf8, cname, &nq_utf8);
976 if (k < 0)
977 return k;
978 else if (k > 0)
979 log_debug("Following UTF8 CNAME/DNAME %s → %s.", dns_question_first_name(q->question_utf8), dns_question_first_name(nq_utf8));
980 }
981
982 if (r == 0 && k == 0) /* No actual cname happened? */
983 return -ELOOP;
984
985 if (q->answer_protocol == DNS_PROTOCOL_DNS) {
986 /* Don't permit CNAME redirects from unicast DNS to LLMNR or MulticastDNS, so that global resources
987 * cannot invade the local namespace. The opposite way we permit: local names may redirect to global
988 * ones. */
989
990 q->flags &= ~(SD_RESOLVED_LLMNR|SD_RESOLVED_MDNS); /* mask away the local protocols */
991 }
992
993 /* Turn off searching for the new name */
994 q->flags |= SD_RESOLVED_NO_SEARCH;
995
996 dns_question_unref(q->question_idna);
997 q->question_idna = nq_idna;
998 nq_idna = NULL;
999
1000 dns_question_unref(q->question_utf8);
1001 q->question_utf8 = nq_utf8;
1002 nq_utf8 = NULL;
1003
1004 dns_query_free_candidates(q);
1005 dns_query_reset_answer(q);
1006
1007 q->state = DNS_TRANSACTION_NULL;
1008
1009 return 0;
1010 }
1011
1012 int dns_query_process_cname(DnsQuery *q) {
1013 _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *cname = NULL;
1014 DnsQuestion *question;
1015 DnsResourceRecord *rr;
1016 int r;
1017
1018 assert(q);
1019
1020 if (!IN_SET(q->state, DNS_TRANSACTION_SUCCESS, DNS_TRANSACTION_NULL))
1021 return DNS_QUERY_NOMATCH;
1022
1023 question = dns_query_question_for_protocol(q, q->answer_protocol);
1024
1025 DNS_ANSWER_FOREACH(rr, q->answer) {
1026 r = dns_question_matches_rr(question, rr, DNS_SEARCH_DOMAIN_NAME(q->answer_search_domain));
1027 if (r < 0)
1028 return r;
1029 if (r > 0)
1030 return DNS_QUERY_MATCH; /* The answer matches directly, no need to follow cnames */
1031
1032 r = dns_question_matches_cname_or_dname(question, rr, DNS_SEARCH_DOMAIN_NAME(q->answer_search_domain));
1033 if (r < 0)
1034 return r;
1035 if (r > 0 && !cname)
1036 cname = dns_resource_record_ref(rr);
1037 }
1038
1039 if (!cname)
1040 return DNS_QUERY_NOMATCH; /* No match and no cname to follow */
1041
1042 if (q->flags & SD_RESOLVED_NO_CNAME)
1043 return -ELOOP;
1044
1045 if (!q->answer_authenticated)
1046 q->previous_redirect_unauthenticated = true;
1047
1048 /* OK, let's actually follow the CNAME */
1049 r = dns_query_cname_redirect(q, cname);
1050 if (r < 0)
1051 return r;
1052
1053 /* Let's see if the answer can already answer the new
1054 * redirected question */
1055 r = dns_query_process_cname(q);
1056 if (r != DNS_QUERY_NOMATCH)
1057 return r;
1058
1059 /* OK, it cannot, let's begin with the new query */
1060 r = dns_query_go(q);
1061 if (r < 0)
1062 return r;
1063
1064 return DNS_QUERY_RESTARTED; /* We restarted the query for a new cname */
1065 }
1066
1067 static int on_bus_track(sd_bus_track *t, void *userdata) {
1068 DnsQuery *q = userdata;
1069
1070 assert(t);
1071 assert(q);
1072
1073 log_debug("Client of active query vanished, aborting query.");
1074 dns_query_complete(q, DNS_TRANSACTION_ABORTED);
1075 return 0;
1076 }
1077
1078 int dns_query_bus_track(DnsQuery *q, sd_bus_message *m) {
1079 int r;
1080
1081 assert(q);
1082 assert(m);
1083
1084 if (!q->bus_track) {
1085 r = sd_bus_track_new(sd_bus_message_get_bus(m), &q->bus_track, on_bus_track, q);
1086 if (r < 0)
1087 return r;
1088 }
1089
1090 r = sd_bus_track_add_sender(q->bus_track, m);
1091 if (r < 0)
1092 return r;
1093
1094 return 0;
1095 }
1096
1097 DnsQuestion* dns_query_question_for_protocol(DnsQuery *q, DnsProtocol protocol) {
1098 assert(q);
1099
1100 switch (protocol) {
1101
1102 case DNS_PROTOCOL_DNS:
1103 return q->question_idna;
1104
1105 case DNS_PROTOCOL_MDNS:
1106 case DNS_PROTOCOL_LLMNR:
1107 return q->question_utf8;
1108
1109 default:
1110 return NULL;
1111 }
1112 }
1113
1114 const char *dns_query_string(DnsQuery *q) {
1115 const char *name;
1116 int r;
1117
1118 /* Returns a somewhat useful human-readable lookup key string for this query */
1119
1120 if (q->request_address_string)
1121 return q->request_address_string;
1122
1123 if (q->request_address_valid) {
1124 r = in_addr_to_string(q->request_family, &q->request_address, &q->request_address_string);
1125 if (r >= 0)
1126 return q->request_address_string;
1127 }
1128
1129 name = dns_question_first_name(q->question_utf8);
1130 if (name)
1131 return name;
1132
1133 return dns_question_first_name(q->question_idna);
1134 }
1135
1136 bool dns_query_fully_authenticated(DnsQuery *q) {
1137 assert(q);
1138
1139 return q->answer_authenticated && !q->previous_redirect_unauthenticated;
1140 }