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