1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2014 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
22 #include "alloc-util.h"
23 #include "dns-domain.h"
25 #include "hostname-util.h"
26 #include "local-addresses.h"
27 #include "resolved-dns-query.h"
28 #include "resolved-dns-synthesize.h"
29 #include "resolved-etc-hosts.h"
30 #include "string-util.h"
32 /* How long to wait for the query in total */
33 #define QUERY_TIMEOUT_USEC (30 * USEC_PER_SEC)
36 #define QUERIES_MAX 2048
37 #define AUXILIARY_QUERIES_MAX 64
39 static int dns_query_candidate_new(DnsQueryCandidate
**ret
, DnsQuery
*q
, DnsScope
*s
) {
46 c
= new0(DnsQueryCandidate
, 1);
53 LIST_PREPEND(candidates_by_query
, q
->candidates
, c
);
54 LIST_PREPEND(candidates_by_scope
, s
->query_candidates
, c
);
60 static void dns_query_candidate_stop(DnsQueryCandidate
*c
) {
65 while ((t
= set_steal_first(c
->transactions
))) {
66 set_remove(t
->notify_query_candidates
, 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
);
92 static int dns_query_candidate_next_search_domain(DnsQueryCandidate
*c
) {
93 DnsSearchDomain
*next
= NULL
;
97 if (c
->search_domain
&& c
->search_domain
->linked
)
98 next
= c
->search_domain
->domains_next
;
100 next
= dns_scope_get_search_domains(c
->scope
);
103 if (!next
) /* We hit the end of the list */
106 if (!next
->route_only
)
109 /* Skip over route-only domains */
110 next
= next
->domains_next
;
113 dns_search_domain_unref(c
->search_domain
);
114 c
->search_domain
= dns_search_domain_ref(next
);
119 static int dns_query_candidate_add_transaction(DnsQueryCandidate
*c
, DnsResourceKey
*key
) {
126 t
= dns_scope_find_transaction(c
->scope
, key
, true);
128 r
= dns_transaction_new(&t
, c
->scope
, key
);
132 if (set_contains(c
->transactions
, t
))
136 r
= set_ensure_allocated(&c
->transactions
, NULL
);
140 r
= set_ensure_allocated(&t
->notify_query_candidates
, NULL
);
144 r
= set_put(t
->notify_query_candidates
, c
);
148 r
= set_put(c
->transactions
, t
);
150 (void) set_remove(t
->notify_query_candidates
, c
);
157 dns_transaction_gc(t
);
161 static int dns_query_candidate_go(DnsQueryCandidate
*c
) {
169 /* Start the transactions that are not started yet */
170 SET_FOREACH(t
, c
->transactions
, i
) {
171 if (t
->state
!= DNS_TRANSACTION_NULL
)
174 r
= dns_transaction_go(t
);
181 /* If there was nothing to start, then let's proceed immediately */
183 dns_query_candidate_notify(c
);
188 static DnsTransactionState
dns_query_candidate_state(DnsQueryCandidate
*c
) {
189 DnsTransactionState state
= DNS_TRANSACTION_NO_SERVERS
;
195 if (c
->error_code
!= 0)
196 return DNS_TRANSACTION_ERRNO
;
198 SET_FOREACH(t
, c
->transactions
, i
) {
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. */
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
;
218 case DNS_TRANSACTION_SUCCESS
:
223 if (state
!= DNS_TRANSACTION_SUCCESS
)
233 static bool dns_query_candidate_is_routable(DnsQueryCandidate
*c
, uint16_t type
) {
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. */
242 if (!c
->query
->suppress_unroutable_family
)
245 if (c
->scope
->protocol
!= DNS_PROTOCOL_DNS
)
248 family
= dns_type_to_af(type
);
253 return link_relevant(c
->scope
->link
, family
, false);
255 return manager_routable(c
->scope
->manager
, family
);
258 static int dns_query_candidate_setup_transactions(DnsQueryCandidate
*c
) {
259 DnsQuestion
*question
;
265 dns_query_candidate_stop(c
);
267 question
= dns_query_question_for_protocol(c
->query
, c
->scope
->protocol
);
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
;
274 if (!dns_query_candidate_is_routable(c
, key
->type
))
277 if (c
->search_domain
) {
278 r
= dns_resource_key_new_append_suffix(&new_key
, key
, c
->search_domain
->name
);
286 if (!dns_scope_good_key(c
->scope
, qkey
))
289 r
= dns_query_candidate_add_transaction(c
, qkey
);
299 dns_query_candidate_stop(c
);
303 void dns_query_candidate_notify(DnsQueryCandidate
*c
) {
304 DnsTransactionState state
;
309 state
= dns_query_candidate_state(c
);
311 if (DNS_TRANSACTION_IS_LIVE(state
))
314 if (state
!= DNS_TRANSACTION_SUCCESS
&& c
->search_domain
) {
316 r
= dns_query_candidate_next_search_domain(c
);
321 /* OK, there's another search domain to try, let's do so. */
323 r
= dns_query_candidate_setup_transactions(c
);
328 /* New transactions where queued. Start them and wait */
330 r
= dns_query_candidate_go(c
);
340 dns_query_ready(c
->query
);
344 log_warning_errno(r
, "Failed to follow search domains: %m");
346 dns_query_ready(c
->query
);
349 static void dns_query_stop(DnsQuery
*q
) {
350 DnsQueryCandidate
*c
;
354 q
->timeout_event_source
= sd_event_source_unref(q
->timeout_event_source
);
356 LIST_FOREACH(candidates_by_query
, c
, q
->candidates
)
357 dns_query_candidate_stop(c
);
360 static void dns_query_free_candidates(DnsQuery
*q
) {
363 while (q
->candidates
)
364 dns_query_candidate_free(q
->candidates
);
367 static void dns_query_reset_answer(DnsQuery
*q
) {
370 q
->answer
= dns_answer_unref(q
->answer
);
372 q
->answer_dnssec_result
= _DNSSEC_RESULT_INVALID
;
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
);
380 DnsQuery
*dns_query_free(DnsQuery
*q
) {
384 while (q
->auxiliary_queries
)
385 dns_query_free(q
->auxiliary_queries
);
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
);
393 dns_query_free_candidates(q
);
395 dns_question_unref(q
->question_idna
);
396 dns_question_unref(q
->question_utf8
);
398 dns_query_reset_answer(q
);
400 sd_bus_message_unref(q
->request
);
401 sd_bus_track_unref(q
->bus_track
);
403 free(q
->request_address_string
);
406 LIST_REMOVE(queries
, q
->manager
->dns_queries
, q
);
407 q
->manager
->n_dns_queries
--;
418 DnsQuestion
*question_utf8
,
419 DnsQuestion
*question_idna
,
420 int ifindex
, uint64_t flags
) {
422 _cleanup_(dns_query_freep
) DnsQuery
*q
= NULL
;
429 if (dns_question_size(question_utf8
) > 0) {
430 r
= dns_question_is_valid_for_query(question_utf8
);
439 /* If the IDNA and UTF8 questions are the same, merge their references */
440 r
= dns_question_is_equal(question_idna
, question_utf8
);
444 question_idna
= question_utf8
;
446 if (dns_question_size(question_idna
) > 0) {
447 r
= dns_question_is_valid_for_query(question_idna
);
457 if (!good
) /* don't allow empty queries */
460 if (m
->n_dns_queries
>= QUERIES_MAX
)
463 q
= new0(DnsQuery
, 1);
467 q
->question_utf8
= dns_question_ref(question_utf8
);
468 q
->question_idna
= dns_question_ref(question_idna
);
469 q
->ifindex
= ifindex
;
471 q
->answer_dnssec_result
= _DNSSEC_RESULT_INVALID
;
472 q
->answer_protocol
= _DNS_PROTOCOL_INVALID
;
473 q
->answer_family
= AF_UNSPEC
;
475 /* First dump UTF8 question */
476 DNS_QUESTION_FOREACH(key
, question_utf8
) {
477 _cleanup_free_
char *p
= NULL
;
479 r
= dns_resource_key_to_string(key
, &p
);
483 log_debug("Looking up RR for %s.", strstrip(p
));
486 /* And then dump the IDNA question, but only what hasn't been dumped already through the UTF8 question. */
487 DNS_QUESTION_FOREACH(key
, question_idna
) {
488 _cleanup_free_
char *p
= NULL
;
490 r
= dns_question_contains(question_utf8
, key
);
496 r
= dns_resource_key_to_string(key
, &p
);
500 log_debug("Looking up IDNA RR for %s.", strstrip(p
));
503 LIST_PREPEND(queries
, m
->dns_queries
, q
);
514 int dns_query_make_auxiliary(DnsQuery
*q
, DnsQuery
*auxiliary_for
) {
516 assert(auxiliary_for
);
518 /* Ensure that 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
);
523 /* Ensure that the unit we shall be made auxiliary for isn't
524 * auxiliary itself */
525 assert(!auxiliary_for
->auxiliary_for
);
527 if (auxiliary_for
->n_auxiliary_queries
>= AUXILIARY_QUERIES_MAX
)
530 LIST_PREPEND(auxiliary_queries
, auxiliary_for
->auxiliary_queries
, q
);
531 q
->auxiliary_for
= auxiliary_for
;
533 auxiliary_for
->n_auxiliary_queries
++;
537 static void dns_query_complete(DnsQuery
*q
, DnsTransactionState state
) {
539 assert(!DNS_TRANSACTION_IS_LIVE(state
));
540 assert(DNS_TRANSACTION_IS_LIVE(q
->state
));
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. */
553 static int on_query_timeout(sd_event_source
*s
, usec_t usec
, void *userdata
) {
554 DnsQuery
*q
= userdata
;
559 dns_query_complete(q
, DNS_TRANSACTION_TIMEOUT
);
563 static int dns_query_add_candidate(DnsQuery
*q
, DnsScope
*s
) {
564 DnsQueryCandidate
*c
;
570 r
= dns_query_candidate_new(&c
, q
, s
);
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
));
580 /* OK, we need a search domain now. Let's find one for this scope */
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. */
588 r
= dns_query_candidate_setup_transactions(c
);
595 dns_query_candidate_free(c
);
599 static int dns_query_synthesize_reply(DnsQuery
*q
, DnsTransactionState
*state
) {
600 _cleanup_(dns_answer_unrefp
) DnsAnswer
*answer
= NULL
;
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) */
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
))
619 r
= dns_synthesize_answer(
628 dns_query_reset_answer(q
);
632 q
->answer_rcode
= DNS_RCODE_SUCCESS
;
633 q
->answer_protocol
= dns_synthesize_protocol(q
->flags
);
634 q
->answer_family
= dns_synthesize_family(q
->flags
);
635 q
->answer_authenticated
= true;
637 *state
= DNS_TRANSACTION_SUCCESS
;
642 static int dns_query_try_etc_hosts(DnsQuery
*q
) {
643 _cleanup_(dns_answer_unrefp
) DnsAnswer
*answer
= NULL
;
648 /* Looks in /etc/hosts for matching entries. Note that this is done *before* the normal lookup is done. The
649 * data from /etc/hosts hence takes precedence over the network. */
651 r
= manager_etc_hosts_lookup(
658 dns_query_reset_answer(q
);
662 q
->answer_rcode
= DNS_RCODE_SUCCESS
;
663 q
->answer_protocol
= dns_synthesize_protocol(q
->flags
);
664 q
->answer_family
= dns_synthesize_family(q
->flags
);
665 q
->answer_authenticated
= true;
670 int dns_query_go(DnsQuery
*q
) {
671 DnsScopeMatch found
= DNS_SCOPE_NO
;
672 DnsScope
*s
, *first
= NULL
;
673 DnsQueryCandidate
*c
;
678 if (q
->state
!= DNS_TRANSACTION_NULL
)
681 r
= dns_query_try_etc_hosts(q
);
685 dns_query_complete(q
, DNS_TRANSACTION_SUCCESS
);
689 LIST_FOREACH(scopes
, s
, q
->manager
->dns_scopes
) {
693 name
= dns_question_first_name(dns_query_question_for_protocol(q
, s
->protocol
));
697 match
= dns_scope_good_domain(s
, q
->ifindex
, q
->flags
, name
);
701 if (match
== DNS_SCOPE_NO
)
706 if (match
== DNS_SCOPE_YES
) {
710 assert(match
== DNS_SCOPE_MAYBE
);
717 if (found
== DNS_SCOPE_NO
) {
718 DnsTransactionState state
= DNS_TRANSACTION_NO_SERVERS
;
720 r
= dns_query_synthesize_reply(q
, &state
);
724 dns_query_complete(q
, state
);
728 r
= dns_query_add_candidate(q
, first
);
732 LIST_FOREACH(scopes
, s
, first
->scopes_next
) {
736 name
= dns_question_first_name(dns_query_question_for_protocol(q
, s
->protocol
));
740 match
= dns_scope_good_domain(s
, q
->ifindex
, q
->flags
, name
);
747 r
= dns_query_add_candidate(q
, s
);
752 dns_query_reset_answer(q
);
754 r
= sd_event_add_time(
756 &q
->timeout_event_source
,
757 clock_boottime_or_monotonic(),
758 now(clock_boottime_or_monotonic()) + QUERY_TIMEOUT_USEC
, 0,
759 on_query_timeout
, q
);
763 (void) sd_event_source_set_description(q
->timeout_event_source
, "query-timeout");
765 q
->state
= DNS_TRANSACTION_PENDING
;
768 /* Start the transactions */
769 LIST_FOREACH(candidates_by_query
, c
, q
->candidates
) {
770 r
= dns_query_candidate_go(c
);
787 static void dns_query_accept(DnsQuery
*q
, DnsQueryCandidate
*c
) {
788 DnsTransactionState state
= DNS_TRANSACTION_NO_SERVERS
;
789 bool has_authenticated
= false, has_non_authenticated
= false;
790 DnssecResult dnssec_result_authenticated
= _DNSSEC_RESULT_INVALID
, dnssec_result_non_authenticated
= _DNSSEC_RESULT_INVALID
;
798 r
= dns_query_synthesize_reply(q
, &state
);
802 dns_query_complete(q
, state
);
806 if (c
->error_code
!= 0) {
807 /* If the candidate had an error condition of its own, start with that. */
808 state
= DNS_TRANSACTION_ERRNO
;
809 q
->answer
= dns_answer_unref(q
->answer
);
811 q
->answer_dnssec_result
= _DNSSEC_RESULT_INVALID
;
812 q
->answer_errno
= c
->error_code
;
815 SET_FOREACH(t
, c
->transactions
, i
) {
819 case DNS_TRANSACTION_SUCCESS
: {
820 /* We found a successfuly reply, merge it into the answer */
821 r
= dns_answer_extend(&q
->answer
, t
->answer
);
825 q
->answer_rcode
= t
->answer_rcode
;
828 if (t
->answer_authenticated
) {
829 has_authenticated
= true;
830 dnssec_result_authenticated
= t
->answer_dnssec_result
;
832 has_non_authenticated
= true;
833 dnssec_result_non_authenticated
= t
->answer_dnssec_result
;
836 state
= DNS_TRANSACTION_SUCCESS
;
840 case DNS_TRANSACTION_NULL
:
841 case DNS_TRANSACTION_PENDING
:
842 case DNS_TRANSACTION_VALIDATING
:
843 case DNS_TRANSACTION_ABORTED
:
844 /* Ignore transactions that didn't complete */
848 /* Any kind of failure? Store the data away,
849 * if there's nothing stored yet. */
851 if (state
== DNS_TRANSACTION_SUCCESS
)
854 q
->answer
= dns_answer_unref(q
->answer
);
855 q
->answer_rcode
= t
->answer_rcode
;
856 q
->answer_dnssec_result
= t
->answer_dnssec_result
;
857 q
->answer_errno
= t
->answer_errno
;
864 if (state
== DNS_TRANSACTION_SUCCESS
) {
865 q
->answer_authenticated
= has_authenticated
&& !has_non_authenticated
;
866 q
->answer_dnssec_result
= q
->answer_authenticated
? dnssec_result_authenticated
: dnssec_result_non_authenticated
;
869 q
->answer_protocol
= c
->scope
->protocol
;
870 q
->answer_family
= c
->scope
->family
;
872 dns_search_domain_unref(q
->answer_search_domain
);
873 q
->answer_search_domain
= dns_search_domain_ref(c
->search_domain
);
875 r
= dns_query_synthesize_reply(q
, &state
);
879 dns_query_complete(q
, state
);
883 q
->answer_errno
= -r
;
884 dns_query_complete(q
, DNS_TRANSACTION_ERRNO
);
887 void dns_query_ready(DnsQuery
*q
) {
889 DnsQueryCandidate
*bad
= NULL
, *c
;
890 bool pending
= false;
893 assert(DNS_TRANSACTION_IS_LIVE(q
->state
));
895 /* Note that this call might invalidate the query. Callers
896 * should hence not attempt to access the query or transaction
897 * after calling this function, unless the block_ready
898 * counter was explicitly bumped before doing so. */
900 if (q
->block_ready
> 0)
903 LIST_FOREACH(candidates_by_query
, c
, q
->candidates
) {
904 DnsTransactionState state
;
906 state
= dns_query_candidate_state(c
);
909 case DNS_TRANSACTION_SUCCESS
:
910 /* One of the candidates is successful,
911 * let's use it, and copy its data out */
912 dns_query_accept(q
, c
);
915 case DNS_TRANSACTION_NULL
:
916 case DNS_TRANSACTION_PENDING
:
917 case DNS_TRANSACTION_VALIDATING
:
918 /* One of the candidates is still going on,
919 * let's maybe wait for it */
924 /* Any kind of failure */
933 dns_query_accept(q
, bad
);
936 static int dns_query_cname_redirect(DnsQuery
*q
, const DnsResourceRecord
*cname
) {
937 _cleanup_(dns_question_unrefp
) DnsQuestion
*nq_idna
= NULL
, *nq_utf8
= NULL
;
942 q
->n_cname_redirects
++;
943 if (q
->n_cname_redirects
> CNAME_MAX
)
946 r
= dns_question_cname_redirect(q
->question_idna
, cname
, &nq_idna
);
950 log_debug("Following CNAME/DNAME %s → %s.", dns_question_first_name(q
->question_idna
), dns_question_first_name(nq_idna
));
952 k
= dns_question_is_equal(q
->question_idna
, q
->question_utf8
);
956 /* Same question? Shortcut new question generation */
957 nq_utf8
= dns_question_ref(nq_idna
);
960 k
= dns_question_cname_redirect(q
->question_utf8
, cname
, &nq_utf8
);
964 log_debug("Following UTF8 CNAME/DNAME %s → %s.", dns_question_first_name(q
->question_utf8
), dns_question_first_name(nq_utf8
));
967 if (r
== 0 && k
== 0) /* No actual cname happened? */
970 dns_question_unref(q
->question_idna
);
971 q
->question_idna
= nq_idna
;
974 dns_question_unref(q
->question_utf8
);
975 q
->question_utf8
= nq_utf8
;
978 dns_query_free_candidates(q
);
979 dns_query_reset_answer(q
);
980 q
->state
= DNS_TRANSACTION_NULL
;
982 /* Turn off searching for the new name */
983 q
->flags
|= SD_RESOLVED_NO_SEARCH
;
988 int dns_query_process_cname(DnsQuery
*q
) {
989 _cleanup_(dns_resource_record_unrefp
) DnsResourceRecord
*cname
= NULL
;
990 DnsQuestion
*question
;
991 DnsResourceRecord
*rr
;
996 if (!IN_SET(q
->state
, DNS_TRANSACTION_SUCCESS
, DNS_TRANSACTION_NULL
))
997 return DNS_QUERY_NOMATCH
;
999 question
= dns_query_question_for_protocol(q
, q
->answer_protocol
);
1001 DNS_ANSWER_FOREACH(rr
, q
->answer
) {
1002 r
= dns_question_matches_rr(question
, rr
, DNS_SEARCH_DOMAIN_NAME(q
->answer_search_domain
));
1006 return DNS_QUERY_MATCH
; /* The answer matches directly, no need to follow cnames */
1008 r
= dns_question_matches_cname_or_dname(question
, rr
, DNS_SEARCH_DOMAIN_NAME(q
->answer_search_domain
));
1011 if (r
> 0 && !cname
)
1012 cname
= dns_resource_record_ref(rr
);
1016 return DNS_QUERY_NOMATCH
; /* No match and no cname to follow */
1018 if (q
->flags
& SD_RESOLVED_NO_CNAME
)
1021 /* OK, let's actually follow the CNAME */
1022 r
= dns_query_cname_redirect(q
, cname
);
1026 /* Let's see if the answer can already answer the new
1027 * redirected question */
1028 r
= dns_query_process_cname(q
);
1029 if (r
!= DNS_QUERY_NOMATCH
)
1032 /* OK, it cannot, let's begin with the new query */
1033 r
= dns_query_go(q
);
1037 return DNS_QUERY_RESTARTED
; /* We restarted the query for a new cname */
1040 static int on_bus_track(sd_bus_track
*t
, void *userdata
) {
1041 DnsQuery
*q
= userdata
;
1046 log_debug("Client of active query vanished, aborting query.");
1047 dns_query_complete(q
, DNS_TRANSACTION_ABORTED
);
1051 int dns_query_bus_track(DnsQuery
*q
, sd_bus_message
*m
) {
1057 if (!q
->bus_track
) {
1058 r
= sd_bus_track_new(sd_bus_message_get_bus(m
), &q
->bus_track
, on_bus_track
, q
);
1063 r
= sd_bus_track_add_sender(q
->bus_track
, m
);
1070 DnsQuestion
* dns_query_question_for_protocol(DnsQuery
*q
, DnsProtocol protocol
) {
1075 case DNS_PROTOCOL_DNS
:
1076 return q
->question_idna
;
1078 case DNS_PROTOCOL_MDNS
:
1079 case DNS_PROTOCOL_LLMNR
:
1080 return q
->question_utf8
;
1087 const char *dns_query_string(DnsQuery
*q
) {
1091 /* Returns a somewhat useful human-readable lookup key string for this query */
1093 if (q
->request_address_string
)
1094 return q
->request_address_string
;
1096 if (q
->request_address_valid
) {
1097 r
= in_addr_to_string(q
->request_family
, &q
->request_address
, &q
->request_address_string
);
1099 return q
->request_address_string
;
1102 name
= dns_question_first_name(q
->question_utf8
);
1106 return dns_question_first_name(q
->question_idna
);