2 This file is part of systemd.
4 Copyright 2014 Lennart Poettering
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.
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.
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/>.
20 #include "alloc-util.h"
21 #include "dns-domain.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"
30 /* How long to wait for the query in total */
31 #define QUERY_TIMEOUT_USEC (30 * USEC_PER_SEC)
34 #define QUERIES_MAX 2048
35 #define AUXILIARY_QUERIES_MAX 64
37 static int dns_query_candidate_new(DnsQueryCandidate
**ret
, DnsQuery
*q
, DnsScope
*s
) {
44 c
= new0(DnsQueryCandidate
, 1);
51 LIST_PREPEND(candidates_by_query
, q
->candidates
, c
);
52 LIST_PREPEND(candidates_by_scope
, s
->query_candidates
, c
);
58 static void dns_query_candidate_stop(DnsQueryCandidate
*c
) {
63 while ((t
= set_steal_first(c
->transactions
))) {
64 set_remove(t
->notify_query_candidates
, c
);
65 set_remove(t
->notify_query_candidates_done
, c
);
66 dns_transaction_gc(t
);
70 DnsQueryCandidate
* dns_query_candidate_free(DnsQueryCandidate
*c
) {
75 dns_query_candidate_stop(c
);
77 set_free(c
->transactions
);
78 dns_search_domain_unref(c
->search_domain
);
81 LIST_REMOVE(candidates_by_query
, c
->query
->candidates
, c
);
84 LIST_REMOVE(candidates_by_scope
, c
->scope
->query_candidates
, c
);
91 static int dns_query_candidate_next_search_domain(DnsQueryCandidate
*c
) {
92 DnsSearchDomain
*next
= NULL
;
96 if (c
->search_domain
&& c
->search_domain
->linked
)
97 next
= c
->search_domain
->domains_next
;
99 next
= dns_scope_get_search_domains(c
->scope
);
102 if (!next
) /* We hit the end of the list */
105 if (!next
->route_only
)
108 /* Skip over route-only domains */
109 next
= next
->domains_next
;
112 dns_search_domain_unref(c
->search_domain
);
113 c
->search_domain
= dns_search_domain_ref(next
);
118 static int dns_query_candidate_add_transaction(DnsQueryCandidate
*c
, DnsResourceKey
*key
) {
125 t
= dns_scope_find_transaction(c
->scope
, key
, true);
127 r
= dns_transaction_new(&t
, c
->scope
, key
);
131 if (set_contains(c
->transactions
, t
))
135 r
= set_ensure_allocated(&c
->transactions
, NULL
);
139 r
= set_ensure_allocated(&t
->notify_query_candidates
, NULL
);
143 r
= set_ensure_allocated(&t
->notify_query_candidates_done
, NULL
);
147 r
= set_put(t
->notify_query_candidates
, c
);
151 r
= set_put(c
->transactions
, t
);
153 (void) set_remove(t
->notify_query_candidates
, c
);
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 free(q
->request_address_string
);
409 LIST_REMOVE(queries
, q
->manager
->dns_queries
, q
);
410 q
->manager
->n_dns_queries
--;
421 DnsQuestion
*question_utf8
,
422 DnsQuestion
*question_idna
,
423 int ifindex
, uint64_t flags
) {
425 _cleanup_(dns_query_freep
) DnsQuery
*q
= NULL
;
429 char key_str
[DNS_RESOURCE_KEY_STRING_MAX
];
433 if (dns_question_size(question_utf8
) > 0) {
434 r
= dns_question_is_valid_for_query(question_utf8
);
443 /* If the IDNA and UTF8 questions are the same, merge their references */
444 r
= dns_question_is_equal(question_idna
, question_utf8
);
448 question_idna
= question_utf8
;
450 if (dns_question_size(question_idna
) > 0) {
451 r
= dns_question_is_valid_for_query(question_idna
);
461 if (!good
) /* don't allow empty queries */
464 if (m
->n_dns_queries
>= QUERIES_MAX
)
467 q
= new0(DnsQuery
, 1);
471 q
->question_utf8
= dns_question_ref(question_utf8
);
472 q
->question_idna
= dns_question_ref(question_idna
);
473 q
->ifindex
= ifindex
;
475 q
->answer_dnssec_result
= _DNSSEC_RESULT_INVALID
;
476 q
->answer_protocol
= _DNS_PROTOCOL_INVALID
;
477 q
->answer_family
= AF_UNSPEC
;
479 /* First dump UTF8 question */
480 DNS_QUESTION_FOREACH(key
, question_utf8
)
481 log_debug("Looking up RR for %s.",
482 dns_resource_key_to_string(key
, key_str
, sizeof key_str
));
484 /* And then dump the IDNA question, but only what hasn't been dumped already through the UTF8 question. */
485 DNS_QUESTION_FOREACH(key
, question_idna
) {
486 r
= dns_question_contains(question_utf8
, key
);
492 log_debug("Looking up IDNA RR for %s.",
493 dns_resource_key_to_string(key
, key_str
, sizeof key_str
));
496 LIST_PREPEND(queries
, m
->dns_queries
, q
);
507 int dns_query_make_auxiliary(DnsQuery
*q
, DnsQuery
*auxiliary_for
) {
509 assert(auxiliary_for
);
511 /* Ensure that that the query is not auxiliary yet, and
512 * nothing else is auxiliary to it either */
513 assert(!q
->auxiliary_for
);
514 assert(!q
->auxiliary_queries
);
516 /* Ensure that the unit we shall be made auxiliary for isn't
517 * auxiliary itself */
518 assert(!auxiliary_for
->auxiliary_for
);
520 if (auxiliary_for
->n_auxiliary_queries
>= AUXILIARY_QUERIES_MAX
)
523 LIST_PREPEND(auxiliary_queries
, auxiliary_for
->auxiliary_queries
, q
);
524 q
->auxiliary_for
= auxiliary_for
;
526 auxiliary_for
->n_auxiliary_queries
++;
530 static void dns_query_complete(DnsQuery
*q
, DnsTransactionState state
) {
532 assert(!DNS_TRANSACTION_IS_LIVE(state
));
533 assert(DNS_TRANSACTION_IS_LIVE(q
->state
));
535 /* Note that this call might invalidate the query. Callers
536 * should hence not attempt to access the query or transaction
537 * after calling this function. */
546 static int on_query_timeout(sd_event_source
*s
, usec_t usec
, void *userdata
) {
547 DnsQuery
*q
= userdata
;
552 dns_query_complete(q
, DNS_TRANSACTION_TIMEOUT
);
556 static int dns_query_add_candidate(DnsQuery
*q
, DnsScope
*s
) {
557 DnsQueryCandidate
*c
;
563 r
= dns_query_candidate_new(&c
, q
, s
);
567 /* If this a single-label domain on DNS, we might append a suitable search domain first. */
568 if ((q
->flags
& SD_RESOLVED_NO_SEARCH
) == 0) {
569 r
= dns_scope_name_needs_search_domain(s
, dns_question_first_name(q
->question_idna
));
573 /* OK, we need a search domain now. Let's find one for this scope */
575 r
= dns_query_candidate_next_search_domain(c
);
576 if (r
<= 0) /* if there's no search domain, then we won't add any transaction. */
581 r
= dns_query_candidate_setup_transactions(c
);
588 dns_query_candidate_free(c
);
592 static int dns_query_synthesize_reply(DnsQuery
*q
, DnsTransactionState
*state
) {
593 _cleanup_(dns_answer_unrefp
) DnsAnswer
*answer
= NULL
;
599 /* Tries to synthesize localhost RR replies (and others) where appropriate. Note that this is done *after* the
600 * the normal lookup finished. The data from the network hence takes precedence over the data we
601 * synthesize. (But note that many scopes refuse to resolve certain domain names) */
604 DNS_TRANSACTION_RCODE_FAILURE
,
605 DNS_TRANSACTION_NO_SERVERS
,
606 DNS_TRANSACTION_TIMEOUT
,
607 DNS_TRANSACTION_ATTEMPTS_MAX_REACHED
,
608 DNS_TRANSACTION_NETWORK_DOWN
,
609 DNS_TRANSACTION_NOT_FOUND
))
612 r
= dns_synthesize_answer(
621 dns_query_reset_answer(q
);
625 q
->answer_rcode
= DNS_RCODE_SUCCESS
;
626 q
->answer_protocol
= dns_synthesize_protocol(q
->flags
);
627 q
->answer_family
= dns_synthesize_family(q
->flags
);
628 q
->answer_authenticated
= true;
630 *state
= DNS_TRANSACTION_SUCCESS
;
635 static int dns_query_try_etc_hosts(DnsQuery
*q
) {
636 _cleanup_(dns_answer_unrefp
) DnsAnswer
*answer
= NULL
;
641 /* Looks in /etc/hosts for matching entries. Note that this is done *before* the normal lookup is done. The
642 * data from /etc/hosts hence takes precedence over the network. */
644 r
= manager_etc_hosts_lookup(
651 dns_query_reset_answer(q
);
655 q
->answer_rcode
= DNS_RCODE_SUCCESS
;
656 q
->answer_protocol
= dns_synthesize_protocol(q
->flags
);
657 q
->answer_family
= dns_synthesize_family(q
->flags
);
658 q
->answer_authenticated
= true;
663 int dns_query_go(DnsQuery
*q
) {
664 DnsScopeMatch found
= DNS_SCOPE_NO
;
665 DnsScope
*s
, *first
= NULL
;
666 DnsQueryCandidate
*c
;
671 if (q
->state
!= DNS_TRANSACTION_NULL
)
674 r
= dns_query_try_etc_hosts(q
);
678 dns_query_complete(q
, DNS_TRANSACTION_SUCCESS
);
682 LIST_FOREACH(scopes
, s
, q
->manager
->dns_scopes
) {
686 name
= dns_question_first_name(dns_query_question_for_protocol(q
, s
->protocol
));
690 match
= dns_scope_good_domain(s
, q
->ifindex
, q
->flags
, name
);
694 if (match
== DNS_SCOPE_NO
)
699 if (match
== DNS_SCOPE_YES
) {
703 assert(match
== DNS_SCOPE_MAYBE
);
710 if (found
== DNS_SCOPE_NO
) {
711 DnsTransactionState state
= DNS_TRANSACTION_NO_SERVERS
;
713 r
= dns_query_synthesize_reply(q
, &state
);
717 dns_query_complete(q
, state
);
721 r
= dns_query_add_candidate(q
, first
);
725 LIST_FOREACH(scopes
, s
, first
->scopes_next
) {
729 name
= dns_question_first_name(dns_query_question_for_protocol(q
, s
->protocol
));
733 match
= dns_scope_good_domain(s
, q
->ifindex
, q
->flags
, name
);
740 r
= dns_query_add_candidate(q
, s
);
745 dns_query_reset_answer(q
);
747 r
= sd_event_add_time(
749 &q
->timeout_event_source
,
750 clock_boottime_or_monotonic(),
751 now(clock_boottime_or_monotonic()) + QUERY_TIMEOUT_USEC
, 0,
752 on_query_timeout
, q
);
756 (void) sd_event_source_set_description(q
->timeout_event_source
, "query-timeout");
758 q
->state
= DNS_TRANSACTION_PENDING
;
761 /* Start the transactions */
762 LIST_FOREACH(candidates_by_query
, c
, q
->candidates
) {
763 r
= dns_query_candidate_go(c
);
780 static void dns_query_accept(DnsQuery
*q
, DnsQueryCandidate
*c
) {
781 DnsTransactionState state
= DNS_TRANSACTION_NO_SERVERS
;
782 bool has_authenticated
= false, has_non_authenticated
= false;
783 DnssecResult dnssec_result_authenticated
= _DNSSEC_RESULT_INVALID
, dnssec_result_non_authenticated
= _DNSSEC_RESULT_INVALID
;
791 r
= dns_query_synthesize_reply(q
, &state
);
795 dns_query_complete(q
, state
);
799 if (c
->error_code
!= 0) {
800 /* If the candidate had an error condition of its own, start with that. */
801 state
= DNS_TRANSACTION_ERRNO
;
802 q
->answer
= dns_answer_unref(q
->answer
);
804 q
->answer_dnssec_result
= _DNSSEC_RESULT_INVALID
;
805 q
->answer_errno
= c
->error_code
;
808 SET_FOREACH(t
, c
->transactions
, i
) {
812 case DNS_TRANSACTION_SUCCESS
: {
813 /* We found a successfully reply, merge it into the answer */
814 r
= dns_answer_extend(&q
->answer
, t
->answer
);
818 q
->answer_rcode
= t
->answer_rcode
;
821 if (t
->answer_authenticated
) {
822 has_authenticated
= true;
823 dnssec_result_authenticated
= t
->answer_dnssec_result
;
825 has_non_authenticated
= true;
826 dnssec_result_non_authenticated
= t
->answer_dnssec_result
;
829 state
= DNS_TRANSACTION_SUCCESS
;
833 case DNS_TRANSACTION_NULL
:
834 case DNS_TRANSACTION_PENDING
:
835 case DNS_TRANSACTION_VALIDATING
:
836 case DNS_TRANSACTION_ABORTED
:
837 /* Ignore transactions that didn't complete */
841 /* Any kind of failure? Store the data away,
842 * if there's nothing stored yet. */
844 if (state
== DNS_TRANSACTION_SUCCESS
)
847 q
->answer
= dns_answer_unref(q
->answer
);
848 q
->answer_rcode
= t
->answer_rcode
;
849 q
->answer_dnssec_result
= t
->answer_dnssec_result
;
850 q
->answer_errno
= t
->answer_errno
;
857 if (state
== DNS_TRANSACTION_SUCCESS
) {
858 q
->answer_authenticated
= has_authenticated
&& !has_non_authenticated
;
859 q
->answer_dnssec_result
= q
->answer_authenticated
? dnssec_result_authenticated
: dnssec_result_non_authenticated
;
862 q
->answer_protocol
= c
->scope
->protocol
;
863 q
->answer_family
= c
->scope
->family
;
865 dns_search_domain_unref(q
->answer_search_domain
);
866 q
->answer_search_domain
= dns_search_domain_ref(c
->search_domain
);
868 r
= dns_query_synthesize_reply(q
, &state
);
872 dns_query_complete(q
, state
);
876 q
->answer_errno
= -r
;
877 dns_query_complete(q
, DNS_TRANSACTION_ERRNO
);
880 void dns_query_ready(DnsQuery
*q
) {
882 DnsQueryCandidate
*bad
= NULL
, *c
;
883 bool pending
= false;
886 assert(DNS_TRANSACTION_IS_LIVE(q
->state
));
888 /* Note that this call might invalidate the query. Callers
889 * should hence not attempt to access the query or transaction
890 * after calling this function, unless the block_ready
891 * counter was explicitly bumped before doing so. */
893 if (q
->block_ready
> 0)
896 LIST_FOREACH(candidates_by_query
, c
, q
->candidates
) {
897 DnsTransactionState state
;
899 state
= dns_query_candidate_state(c
);
902 case DNS_TRANSACTION_SUCCESS
:
903 /* One of the candidates is successful,
904 * let's use it, and copy its data out */
905 dns_query_accept(q
, c
);
908 case DNS_TRANSACTION_NULL
:
909 case DNS_TRANSACTION_PENDING
:
910 case DNS_TRANSACTION_VALIDATING
:
911 /* One of the candidates is still going on,
912 * let's maybe wait for it */
917 /* Any kind of failure */
926 dns_query_accept(q
, bad
);
929 static int dns_query_cname_redirect(DnsQuery
*q
, const DnsResourceRecord
*cname
) {
930 _cleanup_(dns_question_unrefp
) DnsQuestion
*nq_idna
= NULL
, *nq_utf8
= NULL
;
935 q
->n_cname_redirects
++;
936 if (q
->n_cname_redirects
> CNAME_MAX
)
939 r
= dns_question_cname_redirect(q
->question_idna
, cname
, &nq_idna
);
943 log_debug("Following CNAME/DNAME %s → %s.", dns_question_first_name(q
->question_idna
), dns_question_first_name(nq_idna
));
945 k
= dns_question_is_equal(q
->question_idna
, q
->question_utf8
);
949 /* Same question? Shortcut new question generation */
950 nq_utf8
= dns_question_ref(nq_idna
);
953 k
= dns_question_cname_redirect(q
->question_utf8
, cname
, &nq_utf8
);
957 log_debug("Following UTF8 CNAME/DNAME %s → %s.", dns_question_first_name(q
->question_utf8
), dns_question_first_name(nq_utf8
));
960 if (r
== 0 && k
== 0) /* No actual cname happened? */
963 if (q
->answer_protocol
== DNS_PROTOCOL_DNS
) {
964 /* Don't permit CNAME redirects from unicast DNS to LLMNR or MulticastDNS, so that global resources
965 * cannot invade the local namespace. The opposite way we permit: local names may redirect to global
968 q
->flags
&= ~(SD_RESOLVED_LLMNR
|SD_RESOLVED_MDNS
); /* mask away the local protocols */
971 /* Turn off searching for the new name */
972 q
->flags
|= SD_RESOLVED_NO_SEARCH
;
974 dns_question_unref(q
->question_idna
);
975 q
->question_idna
= nq_idna
;
978 dns_question_unref(q
->question_utf8
);
979 q
->question_utf8
= nq_utf8
;
982 dns_query_free_candidates(q
);
983 dns_query_reset_answer(q
);
985 q
->state
= DNS_TRANSACTION_NULL
;
990 int dns_query_process_cname(DnsQuery
*q
) {
991 _cleanup_(dns_resource_record_unrefp
) DnsResourceRecord
*cname
= NULL
;
992 DnsQuestion
*question
;
993 DnsResourceRecord
*rr
;
998 if (!IN_SET(q
->state
, DNS_TRANSACTION_SUCCESS
, DNS_TRANSACTION_NULL
))
999 return DNS_QUERY_NOMATCH
;
1001 question
= dns_query_question_for_protocol(q
, q
->answer_protocol
);
1003 DNS_ANSWER_FOREACH(rr
, q
->answer
) {
1004 r
= dns_question_matches_rr(question
, rr
, DNS_SEARCH_DOMAIN_NAME(q
->answer_search_domain
));
1008 return DNS_QUERY_MATCH
; /* The answer matches directly, no need to follow cnames */
1010 r
= dns_question_matches_cname_or_dname(question
, rr
, DNS_SEARCH_DOMAIN_NAME(q
->answer_search_domain
));
1013 if (r
> 0 && !cname
)
1014 cname
= dns_resource_record_ref(rr
);
1018 return DNS_QUERY_NOMATCH
; /* No match and no cname to follow */
1020 if (q
->flags
& SD_RESOLVED_NO_CNAME
)
1023 /* OK, let's actually follow the CNAME */
1024 r
= dns_query_cname_redirect(q
, cname
);
1028 /* Let's see if the answer can already answer the new
1029 * redirected question */
1030 r
= dns_query_process_cname(q
);
1031 if (r
!= DNS_QUERY_NOMATCH
)
1034 /* OK, it cannot, let's begin with the new query */
1035 r
= dns_query_go(q
);
1039 return DNS_QUERY_RESTARTED
; /* We restarted the query for a new cname */
1042 static int on_bus_track(sd_bus_track
*t
, void *userdata
) {
1043 DnsQuery
*q
= userdata
;
1048 log_debug("Client of active query vanished, aborting query.");
1049 dns_query_complete(q
, DNS_TRANSACTION_ABORTED
);
1053 int dns_query_bus_track(DnsQuery
*q
, sd_bus_message
*m
) {
1059 if (!q
->bus_track
) {
1060 r
= sd_bus_track_new(sd_bus_message_get_bus(m
), &q
->bus_track
, on_bus_track
, q
);
1065 r
= sd_bus_track_add_sender(q
->bus_track
, m
);
1072 DnsQuestion
* dns_query_question_for_protocol(DnsQuery
*q
, DnsProtocol protocol
) {
1077 case DNS_PROTOCOL_DNS
:
1078 return q
->question_idna
;
1080 case DNS_PROTOCOL_MDNS
:
1081 case DNS_PROTOCOL_LLMNR
:
1082 return q
->question_utf8
;
1089 const char *dns_query_string(DnsQuery
*q
) {
1093 /* Returns a somewhat useful human-readable lookup key string for this query */
1095 if (q
->request_address_string
)
1096 return q
->request_address_string
;
1098 if (q
->request_address_valid
) {
1099 r
= in_addr_to_string(q
->request_family
, &q
->request_address
, &q
->request_address_string
);
1101 return q
->request_address_string
;
1104 name
= dns_question_first_name(q
->question_utf8
);
1108 return dns_question_first_name(q
->question_idna
);