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"
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 (30 * 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 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 if (!next
) /* We hit the end of the list */
103 next
= dns_scope_get_search_domains(c
->scope
);
105 if (!next
) /* OK, there's nothing. */
109 dns_search_domain_unref(c
->search_domain
);
110 c
->search_domain
= dns_search_domain_ref(next
);
115 static int dns_query_candidate_add_transaction(DnsQueryCandidate
*c
, DnsResourceKey
*key
) {
122 t
= dns_scope_find_transaction(c
->scope
, key
, true);
124 r
= dns_transaction_new(&t
, c
->scope
, key
);
128 if (set_contains(c
->transactions
, t
))
132 r
= set_ensure_allocated(&c
->transactions
, NULL
);
136 r
= set_ensure_allocated(&t
->notify_query_candidates
, NULL
);
140 r
= set_put(t
->notify_query_candidates
, c
);
144 r
= set_put(c
->transactions
, t
);
146 (void) set_remove(t
->notify_query_candidates
, c
);
153 dns_transaction_gc(t
);
157 static int dns_query_candidate_go(DnsQueryCandidate
*c
) {
164 /* Start the transactions that are not started yet */
165 SET_FOREACH(t
, c
->transactions
, i
) {
166 if (t
->state
!= DNS_TRANSACTION_NULL
)
169 r
= dns_transaction_go(t
);
177 static DnsTransactionState
dns_query_candidate_state(DnsQueryCandidate
*c
) {
178 DnsTransactionState state
= DNS_TRANSACTION_NO_SERVERS
;
184 if (c
->error_code
!= 0)
185 return DNS_TRANSACTION_ERRNO
;
187 SET_FOREACH(t
, c
->transactions
, i
) {
191 case DNS_TRANSACTION_NULL
:
192 /* If there's a NULL transaction pending, then
193 * this means not all transactions where
194 * started yet, and we were called from within
195 * the stackframe that is supposed to start
196 * remaining transactions. In this case,
197 * simply claim the candidate is pending. */
199 case DNS_TRANSACTION_PENDING
:
200 case DNS_TRANSACTION_VALIDATING
:
201 /* If there's one transaction currently in
202 * VALIDATING state, then this means there's
203 * also one in PENDING state, hence we can
204 * return PENDING immediately. */
205 return DNS_TRANSACTION_PENDING
;
207 case DNS_TRANSACTION_SUCCESS
:
212 if (state
!= DNS_TRANSACTION_SUCCESS
)
222 static int dns_query_candidate_setup_transactions(DnsQueryCandidate
*c
) {
223 DnsQuestion
*question
;
229 dns_query_candidate_stop(c
);
231 question
= dns_query_question_for_protocol(c
->query
, c
->scope
->protocol
);
233 /* Create one transaction per question key */
234 DNS_QUESTION_FOREACH(key
, question
) {
235 _cleanup_(dns_resource_key_unrefp
) DnsResourceKey
*new_key
= NULL
;
237 if (c
->search_domain
) {
238 r
= dns_resource_key_new_append_suffix(&new_key
, key
, c
->search_domain
->name
);
243 r
= dns_query_candidate_add_transaction(c
, new_key
?: key
);
253 dns_query_candidate_stop(c
);
257 void dns_query_candidate_notify(DnsQueryCandidate
*c
) {
258 DnsTransactionState state
;
263 state
= dns_query_candidate_state(c
);
265 if (DNS_TRANSACTION_IS_LIVE(state
))
268 if (state
!= DNS_TRANSACTION_SUCCESS
&& c
->search_domain
) {
270 r
= dns_query_candidate_next_search_domain(c
);
275 /* OK, there's another search domain to try, let's do so. */
277 r
= dns_query_candidate_setup_transactions(c
);
282 /* New transactions where queued. Start them and wait */
284 r
= dns_query_candidate_go(c
);
294 dns_query_ready(c
->query
);
298 log_warning_errno(r
, "Failed to follow search domains: %m");
300 dns_query_ready(c
->query
);
303 static void dns_query_stop(DnsQuery
*q
) {
304 DnsQueryCandidate
*c
;
308 q
->timeout_event_source
= sd_event_source_unref(q
->timeout_event_source
);
310 LIST_FOREACH(candidates_by_query
, c
, q
->candidates
)
311 dns_query_candidate_stop(c
);
314 static void dns_query_free_candidates(DnsQuery
*q
) {
317 while (q
->candidates
)
318 dns_query_candidate_free(q
->candidates
);
321 static void dns_query_reset_answer(DnsQuery
*q
) {
324 q
->answer
= dns_answer_unref(q
->answer
);
326 q
->answer_dnssec_result
= _DNSSEC_RESULT_INVALID
;
328 q
->answer_authenticated
= false;
329 q
->answer_protocol
= _DNS_PROTOCOL_INVALID
;
330 q
->answer_family
= AF_UNSPEC
;
331 q
->answer_search_domain
= dns_search_domain_unref(q
->answer_search_domain
);
334 DnsQuery
*dns_query_free(DnsQuery
*q
) {
338 while (q
->auxiliary_queries
)
339 dns_query_free(q
->auxiliary_queries
);
341 if (q
->auxiliary_for
) {
342 assert(q
->auxiliary_for
->n_auxiliary_queries
> 0);
343 q
->auxiliary_for
->n_auxiliary_queries
--;
344 LIST_REMOVE(auxiliary_queries
, q
->auxiliary_for
->auxiliary_queries
, q
);
347 dns_query_free_candidates(q
);
349 dns_question_unref(q
->question_idna
);
350 dns_question_unref(q
->question_utf8
);
352 dns_query_reset_answer(q
);
354 sd_bus_message_unref(q
->request
);
355 sd_bus_track_unref(q
->bus_track
);
357 free(q
->request_address_string
);
360 LIST_REMOVE(queries
, q
->manager
->dns_queries
, q
);
361 q
->manager
->n_dns_queries
--;
372 DnsQuestion
*question_utf8
,
373 DnsQuestion
*question_idna
,
374 int ifindex
, uint64_t flags
) {
376 _cleanup_(dns_query_freep
) DnsQuery
*q
= NULL
;
383 if (dns_question_size(question_utf8
) > 0) {
384 r
= dns_question_is_valid_for_query(question_utf8
);
393 /* If the IDNA and UTF8 questions are the same, merge their references */
394 r
= dns_question_is_equal(question_idna
, question_utf8
);
398 question_idna
= question_utf8
;
400 if (dns_question_size(question_idna
) > 0) {
401 r
= dns_question_is_valid_for_query(question_idna
);
411 if (!good
) /* don't allow empty queries */
414 if (m
->n_dns_queries
>= QUERIES_MAX
)
417 q
= new0(DnsQuery
, 1);
421 q
->question_utf8
= dns_question_ref(question_utf8
);
422 q
->question_idna
= dns_question_ref(question_idna
);
423 q
->ifindex
= ifindex
;
425 q
->answer_dnssec_result
= _DNSSEC_RESULT_INVALID
;
426 q
->answer_protocol
= _DNS_PROTOCOL_INVALID
;
427 q
->answer_family
= AF_UNSPEC
;
429 /* First dump UTF8 question */
430 DNS_QUESTION_FOREACH(key
, question_utf8
) {
431 _cleanup_free_
char *p
= NULL
;
433 r
= dns_resource_key_to_string(key
, &p
);
437 log_debug("Looking up RR for %s.", strstrip(p
));
440 /* And then dump the IDNA question, but only what hasn't been dumped already through the UTF8 question. */
441 DNS_QUESTION_FOREACH(key
, question_idna
) {
442 _cleanup_free_
char *p
= NULL
;
444 r
= dns_question_contains(question_utf8
, key
);
450 r
= dns_resource_key_to_string(key
, &p
);
454 log_debug("Looking up IDNA RR for %s.", strstrip(p
));
457 LIST_PREPEND(queries
, m
->dns_queries
, q
);
468 int dns_query_make_auxiliary(DnsQuery
*q
, DnsQuery
*auxiliary_for
) {
470 assert(auxiliary_for
);
472 /* Ensure that that the query is not auxiliary yet, and
473 * nothing else is auxiliary to it either */
474 assert(!q
->auxiliary_for
);
475 assert(!q
->auxiliary_queries
);
477 /* Ensure that the unit we shall be made auxiliary for isn't
478 * auxiliary itself */
479 assert(!auxiliary_for
->auxiliary_for
);
481 if (auxiliary_for
->n_auxiliary_queries
>= AUXILIARY_QUERIES_MAX
)
484 LIST_PREPEND(auxiliary_queries
, auxiliary_for
->auxiliary_queries
, q
);
485 q
->auxiliary_for
= auxiliary_for
;
487 auxiliary_for
->n_auxiliary_queries
++;
491 static void dns_query_complete(DnsQuery
*q
, DnsTransactionState state
) {
493 assert(!DNS_TRANSACTION_IS_LIVE(state
));
494 assert(DNS_TRANSACTION_IS_LIVE(q
->state
));
496 /* Note that this call might invalidate the query. Callers
497 * should hence not attempt to access the query or transaction
498 * after calling this function. */
507 static int on_query_timeout(sd_event_source
*s
, usec_t usec
, void *userdata
) {
508 DnsQuery
*q
= userdata
;
513 dns_query_complete(q
, DNS_TRANSACTION_TIMEOUT
);
517 static int dns_query_add_candidate(DnsQuery
*q
, DnsScope
*s
) {
518 DnsQueryCandidate
*c
;
524 r
= dns_query_candidate_new(&c
, q
, s
);
528 /* If this a single-label domain on DNS, we might append a suitable search domain first. */
529 if ((q
->flags
& SD_RESOLVED_NO_SEARCH
) == 0) {
530 r
= dns_scope_name_needs_search_domain(s
, dns_question_first_name(q
->question_idna
));
534 /* OK, we need a search domain now. Let's find one for this scope */
536 r
= dns_query_candidate_next_search_domain(c
);
537 if (r
<= 0) /* if there's no search domain, then we won't add any transaction. */
542 r
= dns_query_candidate_setup_transactions(c
);
549 dns_query_candidate_free(c
);
553 static int dns_query_synthesize_reply(DnsQuery
*q
, DnsTransactionState
*state
) {
554 _cleanup_(dns_answer_unrefp
) DnsAnswer
*answer
= NULL
;
560 /* Tries to synthesize localhost RR replies (and others) where appropriate. Note that this is done *after* the
561 * the normal lookup finished. The data from the network hence takes precedence over the data we
562 * synthesize. (But note that many scopes refuse to resolve certain domain names) */
565 DNS_TRANSACTION_RCODE_FAILURE
,
566 DNS_TRANSACTION_NO_SERVERS
,
567 DNS_TRANSACTION_TIMEOUT
,
568 DNS_TRANSACTION_ATTEMPTS_MAX_REACHED
,
569 DNS_TRANSACTION_NETWORK_DOWN
,
570 DNS_TRANSACTION_NOT_FOUND
))
573 r
= dns_synthesize_answer(
582 dns_query_reset_answer(q
);
586 q
->answer_rcode
= DNS_RCODE_SUCCESS
;
587 q
->answer_protocol
= dns_synthesize_protocol(q
->flags
);
588 q
->answer_family
= dns_synthesize_family(q
->flags
);
589 q
->answer_authenticated
= true;
591 *state
= DNS_TRANSACTION_SUCCESS
;
596 static int dns_query_try_etc_hosts(DnsQuery
*q
) {
597 _cleanup_(dns_answer_unrefp
) DnsAnswer
*answer
= NULL
;
602 /* Looks in /etc/hosts for matching entries. Note that this is done *before* the normal lookup is done. The
603 * data from /etc/hosts hence takes precedence over the network. */
605 r
= manager_etc_hosts_lookup(
612 dns_query_reset_answer(q
);
616 q
->answer_rcode
= DNS_RCODE_SUCCESS
;
617 q
->answer_protocol
= dns_synthesize_protocol(q
->flags
);
618 q
->answer_family
= dns_synthesize_family(q
->flags
);
619 q
->answer_authenticated
= true;
624 int dns_query_go(DnsQuery
*q
) {
625 DnsScopeMatch found
= DNS_SCOPE_NO
;
626 DnsScope
*s
, *first
= NULL
;
627 DnsQueryCandidate
*c
;
632 if (q
->state
!= DNS_TRANSACTION_NULL
)
635 r
= dns_query_try_etc_hosts(q
);
639 dns_query_complete(q
, DNS_TRANSACTION_SUCCESS
);
643 LIST_FOREACH(scopes
, s
, q
->manager
->dns_scopes
) {
647 name
= dns_question_first_name(dns_query_question_for_protocol(q
, s
->protocol
));
651 match
= dns_scope_good_domain(s
, q
->ifindex
, q
->flags
, name
);
655 if (match
== DNS_SCOPE_NO
)
660 if (match
== DNS_SCOPE_YES
) {
664 assert(match
== DNS_SCOPE_MAYBE
);
671 if (found
== DNS_SCOPE_NO
) {
672 DnsTransactionState state
= DNS_TRANSACTION_NO_SERVERS
;
674 r
= dns_query_synthesize_reply(q
, &state
);
678 dns_query_complete(q
, state
);
682 r
= dns_query_add_candidate(q
, first
);
686 LIST_FOREACH(scopes
, s
, first
->scopes_next
) {
690 name
= dns_question_first_name(dns_query_question_for_protocol(q
, s
->protocol
));
694 match
= dns_scope_good_domain(s
, q
->ifindex
, q
->flags
, name
);
701 r
= dns_query_add_candidate(q
, s
);
706 dns_query_reset_answer(q
);
708 r
= sd_event_add_time(
710 &q
->timeout_event_source
,
711 clock_boottime_or_monotonic(),
712 now(clock_boottime_or_monotonic()) + QUERY_TIMEOUT_USEC
, 0,
713 on_query_timeout
, q
);
717 (void) sd_event_source_set_description(q
->timeout_event_source
, "query-timeout");
719 q
->state
= DNS_TRANSACTION_PENDING
;
722 /* Start the transactions */
723 LIST_FOREACH(candidates_by_query
, c
, q
->candidates
) {
724 r
= dns_query_candidate_go(c
);
741 static void dns_query_accept(DnsQuery
*q
, DnsQueryCandidate
*c
) {
742 DnsTransactionState state
= DNS_TRANSACTION_NO_SERVERS
;
743 bool has_authenticated
= false, has_non_authenticated
= false;
744 DnssecResult dnssec_result_authenticated
= _DNSSEC_RESULT_INVALID
, dnssec_result_non_authenticated
= _DNSSEC_RESULT_INVALID
;
752 r
= dns_query_synthesize_reply(q
, &state
);
756 dns_query_complete(q
, state
);
760 if (c
->error_code
!= 0) {
761 /* If the candidate had an error condition of its own, start with that. */
762 state
= DNS_TRANSACTION_ERRNO
;
763 q
->answer
= dns_answer_unref(q
->answer
);
765 q
->answer_dnssec_result
= _DNSSEC_RESULT_INVALID
;
766 q
->answer_errno
= c
->error_code
;
769 SET_FOREACH(t
, c
->transactions
, i
) {
773 case DNS_TRANSACTION_SUCCESS
: {
774 /* We found a successfuly reply, merge it into the answer */
775 r
= dns_answer_extend(&q
->answer
, t
->answer
);
779 q
->answer_rcode
= t
->answer_rcode
;
782 if (t
->answer_authenticated
) {
783 has_authenticated
= true;
784 dnssec_result_authenticated
= t
->answer_dnssec_result
;
786 has_non_authenticated
= true;
787 dnssec_result_non_authenticated
= t
->answer_dnssec_result
;
790 state
= DNS_TRANSACTION_SUCCESS
;
794 case DNS_TRANSACTION_NULL
:
795 case DNS_TRANSACTION_PENDING
:
796 case DNS_TRANSACTION_VALIDATING
:
797 case DNS_TRANSACTION_ABORTED
:
798 /* Ignore transactions that didn't complete */
802 /* Any kind of failure? Store the data away,
803 * if there's nothing stored yet. */
805 if (state
== DNS_TRANSACTION_SUCCESS
)
808 q
->answer
= dns_answer_unref(q
->answer
);
809 q
->answer_rcode
= t
->answer_rcode
;
810 q
->answer_dnssec_result
= t
->answer_dnssec_result
;
811 q
->answer_errno
= t
->answer_errno
;
818 if (state
== DNS_TRANSACTION_SUCCESS
) {
819 q
->answer_authenticated
= has_authenticated
&& !has_non_authenticated
;
820 q
->answer_dnssec_result
= q
->answer_authenticated
? dnssec_result_authenticated
: dnssec_result_non_authenticated
;
823 q
->answer_protocol
= c
->scope
->protocol
;
824 q
->answer_family
= c
->scope
->family
;
826 dns_search_domain_unref(q
->answer_search_domain
);
827 q
->answer_search_domain
= dns_search_domain_ref(c
->search_domain
);
829 r
= dns_query_synthesize_reply(q
, &state
);
833 dns_query_complete(q
, state
);
837 q
->answer_errno
= -r
;
838 dns_query_complete(q
, DNS_TRANSACTION_ERRNO
);
841 void dns_query_ready(DnsQuery
*q
) {
843 DnsQueryCandidate
*bad
= NULL
, *c
;
844 bool pending
= false;
847 assert(DNS_TRANSACTION_IS_LIVE(q
->state
));
849 /* Note that this call might invalidate the query. Callers
850 * should hence not attempt to access the query or transaction
851 * after calling this function, unless the block_ready
852 * counter was explicitly bumped before doing so. */
854 if (q
->block_ready
> 0)
857 LIST_FOREACH(candidates_by_query
, c
, q
->candidates
) {
858 DnsTransactionState state
;
860 state
= dns_query_candidate_state(c
);
863 case DNS_TRANSACTION_SUCCESS
:
864 /* One of the candidates is successful,
865 * let's use it, and copy its data out */
866 dns_query_accept(q
, c
);
869 case DNS_TRANSACTION_NULL
:
870 case DNS_TRANSACTION_PENDING
:
871 case DNS_TRANSACTION_VALIDATING
:
872 /* One of the candidates is still going on,
873 * let's maybe wait for it */
878 /* Any kind of failure */
887 dns_query_accept(q
, bad
);
890 static int dns_query_cname_redirect(DnsQuery
*q
, const DnsResourceRecord
*cname
) {
891 _cleanup_(dns_question_unrefp
) DnsQuestion
*nq_idna
= NULL
, *nq_utf8
= NULL
;
896 q
->n_cname_redirects
++;
897 if (q
->n_cname_redirects
> CNAME_MAX
)
900 r
= dns_question_cname_redirect(q
->question_idna
, cname
, &nq_idna
);
904 log_debug("Following CNAME/DNAME %s → %s.", dns_question_first_name(q
->question_idna
), dns_question_first_name(nq_idna
));
906 k
= dns_question_is_equal(q
->question_idna
, q
->question_utf8
);
910 /* Same question? Shortcut new question generation */
911 nq_utf8
= dns_question_ref(nq_idna
);
914 k
= dns_question_cname_redirect(q
->question_utf8
, cname
, &nq_utf8
);
918 log_debug("Following UTF8 CNAME/DNAME %s → %s.", dns_question_first_name(q
->question_utf8
), dns_question_first_name(nq_utf8
));
921 if (r
== 0 && k
== 0) /* No actual cname happened? */
924 dns_question_unref(q
->question_idna
);
925 q
->question_idna
= nq_idna
;
928 dns_question_unref(q
->question_utf8
);
929 q
->question_utf8
= nq_utf8
;
932 dns_query_free_candidates(q
);
933 dns_query_reset_answer(q
);
934 q
->state
= DNS_TRANSACTION_NULL
;
936 /* Turn off searching for the new name */
937 q
->flags
|= SD_RESOLVED_NO_SEARCH
;
942 int dns_query_process_cname(DnsQuery
*q
) {
943 _cleanup_(dns_resource_record_unrefp
) DnsResourceRecord
*cname
= NULL
;
944 DnsQuestion
*question
;
945 DnsResourceRecord
*rr
;
950 if (!IN_SET(q
->state
, DNS_TRANSACTION_SUCCESS
, DNS_TRANSACTION_NULL
))
951 return DNS_QUERY_NOMATCH
;
953 question
= dns_query_question_for_protocol(q
, q
->answer_protocol
);
955 DNS_ANSWER_FOREACH(rr
, q
->answer
) {
956 r
= dns_question_matches_rr(question
, rr
, DNS_SEARCH_DOMAIN_NAME(q
->answer_search_domain
));
960 return DNS_QUERY_MATCH
; /* The answer matches directly, no need to follow cnames */
962 r
= dns_question_matches_cname_or_dname(question
, rr
, DNS_SEARCH_DOMAIN_NAME(q
->answer_search_domain
));
966 cname
= dns_resource_record_ref(rr
);
970 return DNS_QUERY_NOMATCH
; /* No match and no cname to follow */
972 if (q
->flags
& SD_RESOLVED_NO_CNAME
)
975 /* OK, let's actually follow the CNAME */
976 r
= dns_query_cname_redirect(q
, cname
);
980 /* Let's see if the answer can already answer the new
981 * redirected question */
982 r
= dns_query_process_cname(q
);
983 if (r
!= DNS_QUERY_NOMATCH
)
986 /* OK, it cannot, let's begin with the new query */
991 return DNS_QUERY_RESTARTED
; /* We restarted the query for a new cname */
994 static int on_bus_track(sd_bus_track
*t
, void *userdata
) {
995 DnsQuery
*q
= userdata
;
1000 log_debug("Client of active query vanished, aborting query.");
1001 dns_query_complete(q
, DNS_TRANSACTION_ABORTED
);
1005 int dns_query_bus_track(DnsQuery
*q
, sd_bus_message
*m
) {
1011 if (!q
->bus_track
) {
1012 r
= sd_bus_track_new(sd_bus_message_get_bus(m
), &q
->bus_track
, on_bus_track
, q
);
1017 r
= sd_bus_track_add_sender(q
->bus_track
, m
);
1024 DnsQuestion
* dns_query_question_for_protocol(DnsQuery
*q
, DnsProtocol protocol
) {
1029 case DNS_PROTOCOL_DNS
:
1030 return q
->question_idna
;
1032 case DNS_PROTOCOL_MDNS
:
1033 case DNS_PROTOCOL_LLMNR
:
1034 return q
->question_utf8
;
1041 const char *dns_query_string(DnsQuery
*q
) {
1045 /* Returns a somewhat useful human-readable lookup key string for this query */
1047 if (q
->request_address_string
)
1048 return q
->request_address_string
;
1050 if (q
->request_address_valid
) {
1051 r
= in_addr_to_string(q
->request_family
, &q
->request_address
, &q
->request_address_string
);
1053 return q
->request_address_string
;
1056 name
= dns_question_first_name(q
->question_utf8
);
1060 return dns_question_first_name(q
->question_idna
);