1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 This file is part of systemd.
5 Copyright 2014 Lennart Poettering
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.
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.
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/>.
21 #include "alloc-util.h"
22 #include "dns-domain.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"
31 /* How long to wait for the query in total */
32 #define QUERY_TIMEOUT_USEC (60 * USEC_PER_SEC)
35 #define QUERIES_MAX 2048
36 #define AUXILIARY_QUERIES_MAX 64
38 static int dns_query_candidate_new(DnsQueryCandidate
**ret
, DnsQuery
*q
, DnsScope
*s
) {
45 c
= new0(DnsQueryCandidate
, 1);
52 LIST_PREPEND(candidates_by_query
, q
->candidates
, c
);
53 LIST_PREPEND(candidates_by_scope
, s
->query_candidates
, c
);
59 static void dns_query_candidate_stop(DnsQueryCandidate
*c
) {
64 while ((t
= set_steal_first(c
->transactions
))) {
65 set_remove(t
->notify_query_candidates
, c
);
66 set_remove(t
->notify_query_candidates_done
, c
);
67 dns_transaction_gc(t
);
71 DnsQueryCandidate
* dns_query_candidate_free(DnsQueryCandidate
*c
) {
76 dns_query_candidate_stop(c
);
78 set_free(c
->transactions
);
79 dns_search_domain_unref(c
->search_domain
);
82 LIST_REMOVE(candidates_by_query
, c
->query
->candidates
, c
);
85 LIST_REMOVE(candidates_by_scope
, c
->scope
->query_candidates
, c
);
90 static int dns_query_candidate_next_search_domain(DnsQueryCandidate
*c
) {
91 DnsSearchDomain
*next
= NULL
;
95 if (c
->search_domain
&& c
->search_domain
->linked
)
96 next
= c
->search_domain
->domains_next
;
98 next
= dns_scope_get_search_domains(c
->scope
);
101 if (!next
) /* We hit the end of the list */
104 if (!next
->route_only
)
107 /* Skip over route-only domains */
108 next
= next
->domains_next
;
111 dns_search_domain_unref(c
->search_domain
);
112 c
->search_domain
= dns_search_domain_ref(next
);
117 static int dns_query_candidate_add_transaction(DnsQueryCandidate
*c
, DnsResourceKey
*key
) {
124 t
= dns_scope_find_transaction(c
->scope
, key
, true);
126 r
= dns_transaction_new(&t
, c
->scope
, key
);
130 if (set_contains(c
->transactions
, t
))
134 r
= set_ensure_allocated(&c
->transactions
, NULL
);
138 r
= set_ensure_allocated(&t
->notify_query_candidates
, NULL
);
142 r
= set_ensure_allocated(&t
->notify_query_candidates_done
, NULL
);
146 r
= set_put(t
->notify_query_candidates
, c
);
150 r
= set_put(c
->transactions
, t
);
152 (void) set_remove(t
->notify_query_candidates
, c
);
156 t
->clamp_ttl
= c
->query
->clamp_ttl
;
160 dns_transaction_gc(t
);
164 static int dns_query_candidate_go(DnsQueryCandidate
*c
) {
172 /* Start the transactions that are not started yet */
173 SET_FOREACH(t
, c
->transactions
, i
) {
174 if (t
->state
!= DNS_TRANSACTION_NULL
)
177 r
= dns_transaction_go(t
);
184 /* If there was nothing to start, then let's proceed immediately */
186 dns_query_candidate_notify(c
);
191 static DnsTransactionState
dns_query_candidate_state(DnsQueryCandidate
*c
) {
192 DnsTransactionState state
= DNS_TRANSACTION_NO_SERVERS
;
198 if (c
->error_code
!= 0)
199 return DNS_TRANSACTION_ERRNO
;
201 SET_FOREACH(t
, c
->transactions
, i
) {
205 case DNS_TRANSACTION_NULL
:
206 /* If there's a NULL transaction pending, then
207 * this means not all transactions where
208 * started yet, and we were called from within
209 * the stackframe that is supposed to start
210 * remaining transactions. In this case,
211 * simply claim the candidate is pending. */
213 case DNS_TRANSACTION_PENDING
:
214 case DNS_TRANSACTION_VALIDATING
:
215 /* If there's one transaction currently in
216 * VALIDATING state, then this means there's
217 * also one in PENDING state, hence we can
218 * return PENDING immediately. */
219 return DNS_TRANSACTION_PENDING
;
221 case DNS_TRANSACTION_SUCCESS
:
226 if (state
!= DNS_TRANSACTION_SUCCESS
)
236 static bool dns_query_candidate_is_routable(DnsQueryCandidate
*c
, uint16_t type
) {
241 /* Checks whether the specified RR type matches an address family that is routable on the link(s) the scope of
242 * this candidate belongs to. Specifically, whether there's a routable IPv4 address on it if we query an A RR,
243 * or a routable IPv6 address if we query an AAAA RR. */
245 if (!c
->query
->suppress_unroutable_family
)
248 if (c
->scope
->protocol
!= DNS_PROTOCOL_DNS
)
251 family
= dns_type_to_af(type
);
256 return link_relevant(c
->scope
->link
, family
, false);
258 return manager_routable(c
->scope
->manager
, family
);
261 static int dns_query_candidate_setup_transactions(DnsQueryCandidate
*c
) {
262 DnsQuestion
*question
;
268 dns_query_candidate_stop(c
);
270 question
= dns_query_question_for_protocol(c
->query
, c
->scope
->protocol
);
272 /* Create one transaction per question key */
273 DNS_QUESTION_FOREACH(key
, question
) {
274 _cleanup_(dns_resource_key_unrefp
) DnsResourceKey
*new_key
= NULL
;
275 DnsResourceKey
*qkey
;
277 if (!dns_query_candidate_is_routable(c
, key
->type
))
280 if (c
->search_domain
) {
281 r
= dns_resource_key_new_append_suffix(&new_key
, key
, c
->search_domain
->name
);
289 if (!dns_scope_good_key(c
->scope
, qkey
))
292 r
= dns_query_candidate_add_transaction(c
, qkey
);
302 dns_query_candidate_stop(c
);
306 void dns_query_candidate_notify(DnsQueryCandidate
*c
) {
307 DnsTransactionState state
;
312 state
= dns_query_candidate_state(c
);
314 if (DNS_TRANSACTION_IS_LIVE(state
))
317 if (state
!= DNS_TRANSACTION_SUCCESS
&& c
->search_domain
) {
319 r
= dns_query_candidate_next_search_domain(c
);
324 /* OK, there's another search domain to try, let's do so. */
326 r
= dns_query_candidate_setup_transactions(c
);
331 /* New transactions where queued. Start them and wait */
333 r
= dns_query_candidate_go(c
);
343 dns_query_ready(c
->query
);
347 log_warning_errno(r
, "Failed to follow search domains: %m");
349 dns_query_ready(c
->query
);
352 static void dns_query_stop(DnsQuery
*q
) {
353 DnsQueryCandidate
*c
;
357 q
->timeout_event_source
= sd_event_source_unref(q
->timeout_event_source
);
359 LIST_FOREACH(candidates_by_query
, c
, q
->candidates
)
360 dns_query_candidate_stop(c
);
363 static void dns_query_free_candidates(DnsQuery
*q
) {
366 while (q
->candidates
)
367 dns_query_candidate_free(q
->candidates
);
370 static void dns_query_reset_answer(DnsQuery
*q
) {
373 q
->answer
= dns_answer_unref(q
->answer
);
375 q
->answer_dnssec_result
= _DNSSEC_RESULT_INVALID
;
377 q
->answer_authenticated
= false;
378 q
->answer_protocol
= _DNS_PROTOCOL_INVALID
;
379 q
->answer_family
= AF_UNSPEC
;
380 q
->answer_search_domain
= dns_search_domain_unref(q
->answer_search_domain
);
383 DnsQuery
*dns_query_free(DnsQuery
*q
) {
387 while (q
->auxiliary_queries
)
388 dns_query_free(q
->auxiliary_queries
);
390 if (q
->auxiliary_for
) {
391 assert(q
->auxiliary_for
->n_auxiliary_queries
> 0);
392 q
->auxiliary_for
->n_auxiliary_queries
--;
393 LIST_REMOVE(auxiliary_queries
, q
->auxiliary_for
->auxiliary_queries
, q
);
396 dns_query_free_candidates(q
);
398 dns_question_unref(q
->question_idna
);
399 dns_question_unref(q
->question_utf8
);
401 dns_query_reset_answer(q
);
403 sd_bus_message_unref(q
->request
);
404 sd_bus_track_unref(q
->bus_track
);
406 dns_packet_unref(q
->request_dns_packet
);
407 dns_packet_unref(q
->reply_dns_packet
);
409 if (q
->request_dns_stream
) {
410 /* Detach the stream from our query, in case something else keeps a reference to it. */
411 q
->request_dns_stream
->complete
= NULL
;
412 q
->request_dns_stream
->on_packet
= NULL
;
413 q
->request_dns_stream
->query
= NULL
;
414 dns_stream_unref(q
->request_dns_stream
);
417 free(q
->request_address_string
);
420 LIST_REMOVE(queries
, q
->manager
->dns_queries
, q
);
421 q
->manager
->n_dns_queries
--;
430 DnsQuestion
*question_utf8
,
431 DnsQuestion
*question_idna
,
435 _cleanup_(dns_query_freep
) DnsQuery
*q
= NULL
;
439 char key_str
[DNS_RESOURCE_KEY_STRING_MAX
];
443 if (dns_question_size(question_utf8
) > 0) {
444 r
= dns_question_is_valid_for_query(question_utf8
);
453 /* If the IDNA and UTF8 questions are the same, merge their references */
454 r
= dns_question_is_equal(question_idna
, question_utf8
);
458 question_idna
= question_utf8
;
460 if (dns_question_size(question_idna
) > 0) {
461 r
= dns_question_is_valid_for_query(question_idna
);
471 if (!good
) /* don't allow empty queries */
474 if (m
->n_dns_queries
>= QUERIES_MAX
)
477 q
= new0(DnsQuery
, 1);
481 q
->question_utf8
= dns_question_ref(question_utf8
);
482 q
->question_idna
= dns_question_ref(question_idna
);
483 q
->ifindex
= ifindex
;
485 q
->answer_dnssec_result
= _DNSSEC_RESULT_INVALID
;
486 q
->answer_protocol
= _DNS_PROTOCOL_INVALID
;
487 q
->answer_family
= AF_UNSPEC
;
489 /* First dump UTF8 question */
490 DNS_QUESTION_FOREACH(key
, question_utf8
)
491 log_debug("Looking up RR for %s.",
492 dns_resource_key_to_string(key
, key_str
, sizeof key_str
));
494 /* And then dump the IDNA question, but only what hasn't been dumped already through the UTF8 question. */
495 DNS_QUESTION_FOREACH(key
, question_idna
) {
496 r
= dns_question_contains(question_utf8
, key
);
502 log_debug("Looking up IDNA RR for %s.",
503 dns_resource_key_to_string(key
, key_str
, sizeof key_str
));
506 LIST_PREPEND(queries
, m
->dns_queries
, q
);
517 int dns_query_make_auxiliary(DnsQuery
*q
, DnsQuery
*auxiliary_for
) {
519 assert(auxiliary_for
);
521 /* Ensure that the query is not auxiliary yet, and
522 * nothing else is auxiliary to it either */
523 assert(!q
->auxiliary_for
);
524 assert(!q
->auxiliary_queries
);
526 /* Ensure that the unit we shall be made auxiliary for isn't
527 * auxiliary itself */
528 assert(!auxiliary_for
->auxiliary_for
);
530 if (auxiliary_for
->n_auxiliary_queries
>= AUXILIARY_QUERIES_MAX
)
533 LIST_PREPEND(auxiliary_queries
, auxiliary_for
->auxiliary_queries
, q
);
534 q
->auxiliary_for
= auxiliary_for
;
536 auxiliary_for
->n_auxiliary_queries
++;
540 static void dns_query_complete(DnsQuery
*q
, DnsTransactionState state
) {
542 assert(!DNS_TRANSACTION_IS_LIVE(state
));
543 assert(DNS_TRANSACTION_IS_LIVE(q
->state
));
545 /* Note that this call might invalidate the query. Callers
546 * should hence not attempt to access the query or transaction
547 * after calling this function. */
556 static int on_query_timeout(sd_event_source
*s
, usec_t usec
, void *userdata
) {
557 DnsQuery
*q
= userdata
;
562 dns_query_complete(q
, DNS_TRANSACTION_TIMEOUT
);
566 static int dns_query_add_candidate(DnsQuery
*q
, DnsScope
*s
) {
567 DnsQueryCandidate
*c
;
573 r
= dns_query_candidate_new(&c
, q
, s
);
577 /* If this a single-label domain on DNS, we might append a suitable search domain first. */
578 if ((q
->flags
& SD_RESOLVED_NO_SEARCH
) == 0) {
579 r
= dns_scope_name_needs_search_domain(s
, dns_question_first_name(q
->question_idna
));
583 /* OK, we need a search domain now. Let's find one for this scope */
585 r
= dns_query_candidate_next_search_domain(c
);
586 if (r
<= 0) /* if there's no search domain, then we won't add any transaction. */
591 r
= dns_query_candidate_setup_transactions(c
);
598 dns_query_candidate_free(c
);
602 static int dns_query_synthesize_reply(DnsQuery
*q
, DnsTransactionState
*state
) {
603 _cleanup_(dns_answer_unrefp
) DnsAnswer
*answer
= NULL
;
609 /* Tries to synthesize localhost RR replies (and others) where appropriate. Note that this is done *after* the
610 * the normal lookup finished. The data from the network hence takes precedence over the data we
611 * synthesize. (But note that many scopes refuse to resolve certain domain names) */
614 DNS_TRANSACTION_RCODE_FAILURE
,
615 DNS_TRANSACTION_NO_SERVERS
,
616 DNS_TRANSACTION_TIMEOUT
,
617 DNS_TRANSACTION_ATTEMPTS_MAX_REACHED
,
618 DNS_TRANSACTION_NETWORK_DOWN
,
619 DNS_TRANSACTION_NOT_FOUND
))
622 r
= dns_synthesize_answer(
628 /* If we get ENXIO this tells us to generate NXDOMAIN unconditionally. */
630 dns_query_reset_answer(q
);
631 q
->answer_rcode
= DNS_RCODE_NXDOMAIN
;
632 q
->answer_protocol
= dns_synthesize_protocol(q
->flags
);
633 q
->answer_family
= dns_synthesize_family(q
->flags
);
634 q
->answer_authenticated
= true;
635 *state
= DNS_TRANSACTION_RCODE_FAILURE
;
642 dns_query_reset_answer(q
);
646 q
->answer_rcode
= DNS_RCODE_SUCCESS
;
647 q
->answer_protocol
= dns_synthesize_protocol(q
->flags
);
648 q
->answer_family
= dns_synthesize_family(q
->flags
);
649 q
->answer_authenticated
= true;
651 *state
= DNS_TRANSACTION_SUCCESS
;
656 static int dns_query_try_etc_hosts(DnsQuery
*q
) {
657 _cleanup_(dns_answer_unrefp
) DnsAnswer
*answer
= NULL
;
662 /* Looks in /etc/hosts for matching entries. Note that this is done *before* the normal lookup is done. The
663 * data from /etc/hosts hence takes precedence over the network. */
665 r
= manager_etc_hosts_lookup(
672 dns_query_reset_answer(q
);
676 q
->answer_rcode
= DNS_RCODE_SUCCESS
;
677 q
->answer_protocol
= dns_synthesize_protocol(q
->flags
);
678 q
->answer_family
= dns_synthesize_family(q
->flags
);
679 q
->answer_authenticated
= true;
684 int dns_query_go(DnsQuery
*q
) {
685 DnsScopeMatch found
= DNS_SCOPE_NO
;
686 DnsScope
*s
, *first
= NULL
;
687 DnsQueryCandidate
*c
;
692 if (q
->state
!= DNS_TRANSACTION_NULL
)
695 r
= dns_query_try_etc_hosts(q
);
699 dns_query_complete(q
, DNS_TRANSACTION_SUCCESS
);
703 LIST_FOREACH(scopes
, s
, q
->manager
->dns_scopes
) {
707 name
= dns_question_first_name(dns_query_question_for_protocol(q
, s
->protocol
));
711 match
= dns_scope_good_domain(s
, q
->ifindex
, q
->flags
, name
);
715 if (match
== DNS_SCOPE_NO
)
720 if (match
== DNS_SCOPE_YES
) {
724 assert(match
== DNS_SCOPE_MAYBE
);
731 if (found
== DNS_SCOPE_NO
) {
732 DnsTransactionState state
= DNS_TRANSACTION_NO_SERVERS
;
734 r
= dns_query_synthesize_reply(q
, &state
);
738 dns_query_complete(q
, state
);
742 r
= dns_query_add_candidate(q
, first
);
746 LIST_FOREACH(scopes
, s
, first
->scopes_next
) {
750 name
= dns_question_first_name(dns_query_question_for_protocol(q
, s
->protocol
));
754 match
= dns_scope_good_domain(s
, q
->ifindex
, q
->flags
, name
);
761 r
= dns_query_add_candidate(q
, s
);
766 dns_query_reset_answer(q
);
768 r
= sd_event_add_time(
770 &q
->timeout_event_source
,
771 clock_boottime_or_monotonic(),
772 now(clock_boottime_or_monotonic()) + QUERY_TIMEOUT_USEC
, 0,
773 on_query_timeout
, q
);
777 (void) sd_event_source_set_description(q
->timeout_event_source
, "query-timeout");
779 q
->state
= DNS_TRANSACTION_PENDING
;
782 /* Start the transactions */
783 LIST_FOREACH(candidates_by_query
, c
, q
->candidates
) {
784 r
= dns_query_candidate_go(c
);
801 static void dns_query_accept(DnsQuery
*q
, DnsQueryCandidate
*c
) {
802 DnsTransactionState state
= DNS_TRANSACTION_NO_SERVERS
;
803 bool has_authenticated
= false, has_non_authenticated
= false;
804 DnssecResult dnssec_result_authenticated
= _DNSSEC_RESULT_INVALID
, dnssec_result_non_authenticated
= _DNSSEC_RESULT_INVALID
;
812 r
= dns_query_synthesize_reply(q
, &state
);
816 dns_query_complete(q
, state
);
820 if (c
->error_code
!= 0) {
821 /* If the candidate had an error condition of its own, start with that. */
822 state
= DNS_TRANSACTION_ERRNO
;
823 q
->answer
= dns_answer_unref(q
->answer
);
825 q
->answer_dnssec_result
= _DNSSEC_RESULT_INVALID
;
826 q
->answer_authenticated
= false;
827 q
->answer_errno
= c
->error_code
;
830 SET_FOREACH(t
, c
->transactions
, i
) {
834 case DNS_TRANSACTION_SUCCESS
: {
835 /* We found a successfully reply, merge it into the answer */
836 r
= dns_answer_extend(&q
->answer
, t
->answer
);
840 q
->answer_rcode
= t
->answer_rcode
;
843 if (t
->answer_authenticated
) {
844 has_authenticated
= true;
845 dnssec_result_authenticated
= t
->answer_dnssec_result
;
847 has_non_authenticated
= true;
848 dnssec_result_non_authenticated
= t
->answer_dnssec_result
;
851 state
= DNS_TRANSACTION_SUCCESS
;
855 case DNS_TRANSACTION_NULL
:
856 case DNS_TRANSACTION_PENDING
:
857 case DNS_TRANSACTION_VALIDATING
:
858 case DNS_TRANSACTION_ABORTED
:
859 /* Ignore transactions that didn't complete */
863 /* Any kind of failure? Store the data away, if there's nothing stored yet. */
864 if (state
== DNS_TRANSACTION_SUCCESS
)
867 /* If there's already an authenticated negative reply stored, then prefer that over any unauthenticated one */
868 if (q
->answer_authenticated
&& !t
->answer_authenticated
)
871 q
->answer
= dns_answer_unref(q
->answer
);
872 q
->answer_rcode
= t
->answer_rcode
;
873 q
->answer_dnssec_result
= t
->answer_dnssec_result
;
874 q
->answer_authenticated
= t
->answer_authenticated
;
875 q
->answer_errno
= t
->answer_errno
;
882 if (state
== DNS_TRANSACTION_SUCCESS
) {
883 q
->answer_authenticated
= has_authenticated
&& !has_non_authenticated
;
884 q
->answer_dnssec_result
= q
->answer_authenticated
? dnssec_result_authenticated
: dnssec_result_non_authenticated
;
887 q
->answer_protocol
= c
->scope
->protocol
;
888 q
->answer_family
= c
->scope
->family
;
890 dns_search_domain_unref(q
->answer_search_domain
);
891 q
->answer_search_domain
= dns_search_domain_ref(c
->search_domain
);
893 r
= dns_query_synthesize_reply(q
, &state
);
897 dns_query_complete(q
, state
);
901 q
->answer_errno
= -r
;
902 dns_query_complete(q
, DNS_TRANSACTION_ERRNO
);
905 void dns_query_ready(DnsQuery
*q
) {
907 DnsQueryCandidate
*bad
= NULL
, *c
;
908 bool pending
= false;
911 assert(DNS_TRANSACTION_IS_LIVE(q
->state
));
913 /* Note that this call might invalidate the query. Callers
914 * should hence not attempt to access the query or transaction
915 * after calling this function, unless the block_ready
916 * counter was explicitly bumped before doing so. */
918 if (q
->block_ready
> 0)
921 LIST_FOREACH(candidates_by_query
, c
, q
->candidates
) {
922 DnsTransactionState state
;
924 state
= dns_query_candidate_state(c
);
927 case DNS_TRANSACTION_SUCCESS
:
928 /* One of the candidates is successful,
929 * let's use it, and copy its data out */
930 dns_query_accept(q
, c
);
933 case DNS_TRANSACTION_NULL
:
934 case DNS_TRANSACTION_PENDING
:
935 case DNS_TRANSACTION_VALIDATING
:
936 /* One of the candidates is still going on,
937 * let's maybe wait for it */
942 /* Any kind of failure */
951 dns_query_accept(q
, bad
);
954 static int dns_query_cname_redirect(DnsQuery
*q
, const DnsResourceRecord
*cname
) {
955 _cleanup_(dns_question_unrefp
) DnsQuestion
*nq_idna
= NULL
, *nq_utf8
= NULL
;
960 q
->n_cname_redirects
++;
961 if (q
->n_cname_redirects
> CNAME_MAX
)
964 r
= dns_question_cname_redirect(q
->question_idna
, cname
, &nq_idna
);
968 log_debug("Following CNAME/DNAME %s → %s.", dns_question_first_name(q
->question_idna
), dns_question_first_name(nq_idna
));
970 k
= dns_question_is_equal(q
->question_idna
, q
->question_utf8
);
974 /* Same question? Shortcut new question generation */
975 nq_utf8
= dns_question_ref(nq_idna
);
978 k
= dns_question_cname_redirect(q
->question_utf8
, cname
, &nq_utf8
);
982 log_debug("Following UTF8 CNAME/DNAME %s → %s.", dns_question_first_name(q
->question_utf8
), dns_question_first_name(nq_utf8
));
985 if (r
== 0 && k
== 0) /* No actual cname happened? */
988 if (q
->answer_protocol
== DNS_PROTOCOL_DNS
) {
989 /* Don't permit CNAME redirects from unicast DNS to LLMNR or MulticastDNS, so that global resources
990 * cannot invade the local namespace. The opposite way we permit: local names may redirect to global
993 q
->flags
&= ~(SD_RESOLVED_LLMNR
|SD_RESOLVED_MDNS
); /* mask away the local protocols */
996 /* Turn off searching for the new name */
997 q
->flags
|= SD_RESOLVED_NO_SEARCH
;
999 dns_question_unref(q
->question_idna
);
1000 q
->question_idna
= nq_idna
;
1003 dns_question_unref(q
->question_utf8
);
1004 q
->question_utf8
= nq_utf8
;
1007 dns_query_free_candidates(q
);
1008 dns_query_reset_answer(q
);
1010 q
->state
= DNS_TRANSACTION_NULL
;
1015 int dns_query_process_cname(DnsQuery
*q
) {
1016 _cleanup_(dns_resource_record_unrefp
) DnsResourceRecord
*cname
= NULL
;
1017 DnsQuestion
*question
;
1018 DnsResourceRecord
*rr
;
1023 if (!IN_SET(q
->state
, DNS_TRANSACTION_SUCCESS
, DNS_TRANSACTION_NULL
))
1024 return DNS_QUERY_NOMATCH
;
1026 question
= dns_query_question_for_protocol(q
, q
->answer_protocol
);
1028 DNS_ANSWER_FOREACH(rr
, q
->answer
) {
1029 r
= dns_question_matches_rr(question
, rr
, DNS_SEARCH_DOMAIN_NAME(q
->answer_search_domain
));
1033 return DNS_QUERY_MATCH
; /* The answer matches directly, no need to follow cnames */
1035 r
= dns_question_matches_cname_or_dname(question
, rr
, DNS_SEARCH_DOMAIN_NAME(q
->answer_search_domain
));
1038 if (r
> 0 && !cname
)
1039 cname
= dns_resource_record_ref(rr
);
1043 return DNS_QUERY_NOMATCH
; /* No match and no cname to follow */
1045 if (q
->flags
& SD_RESOLVED_NO_CNAME
)
1048 if (!q
->answer_authenticated
)
1049 q
->previous_redirect_unauthenticated
= true;
1051 /* OK, let's actually follow the CNAME */
1052 r
= dns_query_cname_redirect(q
, cname
);
1056 /* Let's see if the answer can already answer the new
1057 * redirected question */
1058 r
= dns_query_process_cname(q
);
1059 if (r
!= DNS_QUERY_NOMATCH
)
1062 /* OK, it cannot, let's begin with the new query */
1063 r
= dns_query_go(q
);
1067 return DNS_QUERY_RESTARTED
; /* We restarted the query for a new cname */
1070 static int on_bus_track(sd_bus_track
*t
, void *userdata
) {
1071 DnsQuery
*q
= userdata
;
1076 log_debug("Client of active query vanished, aborting query.");
1077 dns_query_complete(q
, DNS_TRANSACTION_ABORTED
);
1081 int dns_query_bus_track(DnsQuery
*q
, sd_bus_message
*m
) {
1087 if (!q
->bus_track
) {
1088 r
= sd_bus_track_new(sd_bus_message_get_bus(m
), &q
->bus_track
, on_bus_track
, q
);
1093 r
= sd_bus_track_add_sender(q
->bus_track
, m
);
1100 DnsQuestion
* dns_query_question_for_protocol(DnsQuery
*q
, DnsProtocol protocol
) {
1105 case DNS_PROTOCOL_DNS
:
1106 return q
->question_idna
;
1108 case DNS_PROTOCOL_MDNS
:
1109 case DNS_PROTOCOL_LLMNR
:
1110 return q
->question_utf8
;
1117 const char *dns_query_string(DnsQuery
*q
) {
1121 /* Returns a somewhat useful human-readable lookup key string for this query */
1123 if (q
->request_address_string
)
1124 return q
->request_address_string
;
1126 if (q
->request_address_valid
) {
1127 r
= in_addr_to_string(q
->request_family
, &q
->request_address
, &q
->request_address_string
);
1129 return q
->request_address_string
;
1132 name
= dns_question_first_name(q
->question_utf8
);
1136 return dns_question_first_name(q
->question_idna
);
1139 bool dns_query_fully_authenticated(DnsQuery
*q
) {
1142 return q
->answer_authenticated
&& !q
->previous_redirect_unauthenticated
;