1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 #include "alloc-util.h"
4 #include "dns-domain.h"
6 #include "hostname-util.h"
7 #include "local-addresses.h"
8 #include "resolved-dns-query.h"
9 #include "resolved-dns-synthesize.h"
10 #include "resolved-etc-hosts.h"
11 #include "string-util.h"
14 #define QUERIES_MAX 2048
15 #define AUXILIARY_QUERIES_MAX 64
17 static int dns_query_candidate_new(DnsQueryCandidate
**ret
, DnsQuery
*q
, DnsScope
*s
) {
24 c
= new0(DnsQueryCandidate
, 1);
31 LIST_PREPEND(candidates_by_query
, q
->candidates
, c
);
32 LIST_PREPEND(candidates_by_scope
, s
->query_candidates
, c
);
38 static void dns_query_candidate_stop(DnsQueryCandidate
*c
) {
43 while ((t
= set_steal_first(c
->transactions
))) {
44 set_remove(t
->notify_query_candidates
, c
);
45 set_remove(t
->notify_query_candidates_done
, c
);
46 dns_transaction_gc(t
);
50 DnsQueryCandidate
* dns_query_candidate_free(DnsQueryCandidate
*c
) {
55 dns_query_candidate_stop(c
);
57 set_free(c
->transactions
);
58 dns_search_domain_unref(c
->search_domain
);
61 LIST_REMOVE(candidates_by_query
, c
->query
->candidates
, c
);
64 LIST_REMOVE(candidates_by_scope
, c
->scope
->query_candidates
, c
);
69 static int dns_query_candidate_next_search_domain(DnsQueryCandidate
*c
) {
70 DnsSearchDomain
*next
= NULL
;
74 if (c
->search_domain
&& c
->search_domain
->linked
)
75 next
= c
->search_domain
->domains_next
;
77 next
= dns_scope_get_search_domains(c
->scope
);
80 if (!next
) /* We hit the end of the list */
83 if (!next
->route_only
)
86 /* Skip over route-only domains */
87 next
= next
->domains_next
;
90 dns_search_domain_unref(c
->search_domain
);
91 c
->search_domain
= dns_search_domain_ref(next
);
96 static int dns_query_candidate_add_transaction(DnsQueryCandidate
*c
, DnsResourceKey
*key
) {
97 _cleanup_(dns_transaction_gcp
) DnsTransaction
*t
= NULL
;
103 t
= dns_scope_find_transaction(c
->scope
, key
, true);
105 r
= dns_transaction_new(&t
, c
->scope
, key
);
108 } else if (set_contains(c
->transactions
, t
))
111 r
= set_ensure_allocated(&t
->notify_query_candidates_done
, NULL
);
115 r
= set_ensure_put(&t
->notify_query_candidates
, NULL
, c
);
119 r
= set_ensure_put(&c
->transactions
, NULL
, t
);
121 (void) set_remove(t
->notify_query_candidates
, c
);
125 t
->clamp_ttl
= c
->query
->clamp_ttl
;
130 static int dns_query_candidate_go(DnsQueryCandidate
*c
) {
137 /* Start the transactions that are not started yet */
138 SET_FOREACH(t
, c
->transactions
) {
139 if (t
->state
!= DNS_TRANSACTION_NULL
)
142 r
= dns_transaction_go(t
);
149 /* If there was nothing to start, then let's proceed immediately */
151 dns_query_candidate_notify(c
);
156 static DnsTransactionState
dns_query_candidate_state(DnsQueryCandidate
*c
) {
157 DnsTransactionState state
= DNS_TRANSACTION_NO_SERVERS
;
162 if (c
->error_code
!= 0)
163 return DNS_TRANSACTION_ERRNO
;
165 SET_FOREACH(t
, c
->transactions
) {
169 case DNS_TRANSACTION_NULL
:
170 /* If there's a NULL transaction pending, then
171 * this means not all transactions where
172 * started yet, and we were called from within
173 * the stackframe that is supposed to start
174 * remaining transactions. In this case,
175 * simply claim the candidate is pending. */
177 case DNS_TRANSACTION_PENDING
:
178 case DNS_TRANSACTION_VALIDATING
:
179 /* If there's one transaction currently in
180 * VALIDATING state, then this means there's
181 * also one in PENDING state, hence we can
182 * return PENDING immediately. */
183 return DNS_TRANSACTION_PENDING
;
185 case DNS_TRANSACTION_SUCCESS
:
190 if (state
!= DNS_TRANSACTION_SUCCESS
)
200 static int dns_query_candidate_setup_transactions(DnsQueryCandidate
*c
) {
201 DnsQuestion
*question
;
207 dns_query_candidate_stop(c
);
209 question
= dns_query_question_for_protocol(c
->query
, c
->scope
->protocol
);
211 /* Create one transaction per question key */
212 DNS_QUESTION_FOREACH(key
, question
) {
213 _cleanup_(dns_resource_key_unrefp
) DnsResourceKey
*new_key
= NULL
;
214 DnsResourceKey
*qkey
;
216 if (c
->search_domain
) {
217 r
= dns_resource_key_new_append_suffix(&new_key
, key
, c
->search_domain
->name
);
225 if (!dns_scope_good_key(c
->scope
, qkey
))
228 r
= dns_query_candidate_add_transaction(c
, qkey
);
238 dns_query_candidate_stop(c
);
242 void dns_query_candidate_notify(DnsQueryCandidate
*c
) {
243 DnsTransactionState state
;
248 state
= dns_query_candidate_state(c
);
250 if (DNS_TRANSACTION_IS_LIVE(state
))
253 if (state
!= DNS_TRANSACTION_SUCCESS
&& c
->search_domain
) {
255 r
= dns_query_candidate_next_search_domain(c
);
260 /* OK, there's another search domain to try, let's do so. */
262 r
= dns_query_candidate_setup_transactions(c
);
267 /* New transactions where queued. Start them and wait */
269 r
= dns_query_candidate_go(c
);
279 dns_query_ready(c
->query
);
283 log_warning_errno(r
, "Failed to follow search domains: %m");
285 dns_query_ready(c
->query
);
288 static void dns_query_stop(DnsQuery
*q
) {
289 DnsQueryCandidate
*c
;
293 q
->timeout_event_source
= sd_event_source_unref(q
->timeout_event_source
);
295 LIST_FOREACH(candidates_by_query
, c
, q
->candidates
)
296 dns_query_candidate_stop(c
);
299 static void dns_query_free_candidates(DnsQuery
*q
) {
302 while (q
->candidates
)
303 dns_query_candidate_free(q
->candidates
);
306 static void dns_query_reset_answer(DnsQuery
*q
) {
309 q
->answer
= dns_answer_unref(q
->answer
);
311 q
->answer_dnssec_result
= _DNSSEC_RESULT_INVALID
;
313 q
->answer_authenticated
= false;
314 q
->answer_protocol
= _DNS_PROTOCOL_INVALID
;
315 q
->answer_family
= AF_UNSPEC
;
316 q
->answer_search_domain
= dns_search_domain_unref(q
->answer_search_domain
);
319 DnsQuery
*dns_query_free(DnsQuery
*q
) {
323 while (q
->auxiliary_queries
)
324 dns_query_free(q
->auxiliary_queries
);
326 if (q
->auxiliary_for
) {
327 assert(q
->auxiliary_for
->n_auxiliary_queries
> 0);
328 q
->auxiliary_for
->n_auxiliary_queries
--;
329 LIST_REMOVE(auxiliary_queries
, q
->auxiliary_for
->auxiliary_queries
, q
);
332 dns_query_free_candidates(q
);
334 dns_question_unref(q
->question_idna
);
335 dns_question_unref(q
->question_utf8
);
337 dns_query_reset_answer(q
);
339 sd_bus_message_unref(q
->bus_request
);
340 sd_bus_track_unref(q
->bus_track
);
342 if (q
->varlink_request
) {
343 varlink_set_userdata(q
->varlink_request
, NULL
);
344 varlink_unref(q
->varlink_request
);
347 dns_packet_unref(q
->request_dns_packet
);
348 dns_packet_unref(q
->reply_dns_packet
);
350 if (q
->request_dns_stream
) {
351 /* Detach the stream from our query, in case something else keeps a reference to it. */
352 (void) set_remove(q
->request_dns_stream
->queries
, q
);
353 q
->request_dns_stream
= dns_stream_unref(q
->request_dns_stream
);
356 free(q
->request_address_string
);
359 LIST_REMOVE(queries
, q
->manager
->dns_queries
, q
);
360 q
->manager
->n_dns_queries
--;
369 DnsQuestion
*question_utf8
,
370 DnsQuestion
*question_idna
,
374 _cleanup_(dns_query_freep
) DnsQuery
*q
= NULL
;
378 char key_str
[DNS_RESOURCE_KEY_STRING_MAX
];
382 if (dns_question_size(question_utf8
) > 0) {
383 r
= dns_question_is_valid_for_query(question_utf8
);
392 /* If the IDNA and UTF8 questions are the same, merge their references */
393 r
= dns_question_is_equal(question_idna
, question_utf8
);
397 question_idna
= question_utf8
;
399 if (dns_question_size(question_idna
) > 0) {
400 r
= dns_question_is_valid_for_query(question_idna
);
410 if (!good
) /* don't allow empty queries */
413 if (m
->n_dns_queries
>= QUERIES_MAX
)
416 q
= new0(DnsQuery
, 1);
420 q
->question_utf8
= dns_question_ref(question_utf8
);
421 q
->question_idna
= dns_question_ref(question_idna
);
422 q
->ifindex
= ifindex
;
424 q
->answer_dnssec_result
= _DNSSEC_RESULT_INVALID
;
425 q
->answer_protocol
= _DNS_PROTOCOL_INVALID
;
426 q
->answer_family
= AF_UNSPEC
;
428 /* First dump UTF8 question */
429 DNS_QUESTION_FOREACH(key
, question_utf8
)
430 log_debug("Looking up RR for %s.",
431 dns_resource_key_to_string(key
, key_str
, sizeof key_str
));
433 /* And then dump the IDNA question, but only what hasn't been dumped already through the UTF8 question. */
434 DNS_QUESTION_FOREACH(key
, question_idna
) {
435 r
= dns_question_contains(question_utf8
, key
);
441 log_debug("Looking up IDNA RR for %s.",
442 dns_resource_key_to_string(key
, key_str
, sizeof key_str
));
445 LIST_PREPEND(queries
, m
->dns_queries
, q
);
456 int dns_query_make_auxiliary(DnsQuery
*q
, DnsQuery
*auxiliary_for
) {
458 assert(auxiliary_for
);
460 /* Ensure that the query is not auxiliary yet, and
461 * nothing else is auxiliary to it either */
462 assert(!q
->auxiliary_for
);
463 assert(!q
->auxiliary_queries
);
465 /* Ensure that the unit we shall be made auxiliary for isn't
466 * auxiliary itself */
467 assert(!auxiliary_for
->auxiliary_for
);
469 if (auxiliary_for
->n_auxiliary_queries
>= AUXILIARY_QUERIES_MAX
)
472 LIST_PREPEND(auxiliary_queries
, auxiliary_for
->auxiliary_queries
, q
);
473 q
->auxiliary_for
= auxiliary_for
;
475 auxiliary_for
->n_auxiliary_queries
++;
479 void dns_query_complete(DnsQuery
*q
, DnsTransactionState state
) {
481 assert(!DNS_TRANSACTION_IS_LIVE(state
));
482 assert(DNS_TRANSACTION_IS_LIVE(q
->state
));
484 /* Note that this call might invalidate the query. Callers should hence not attempt to access the
485 * query or transaction after calling this function. */
494 static int on_query_timeout(sd_event_source
*s
, usec_t usec
, void *userdata
) {
495 DnsQuery
*q
= userdata
;
500 dns_query_complete(q
, DNS_TRANSACTION_TIMEOUT
);
504 static int dns_query_add_candidate(DnsQuery
*q
, DnsScope
*s
) {
505 _cleanup_(dns_query_candidate_freep
) DnsQueryCandidate
*c
= NULL
;
511 r
= dns_query_candidate_new(&c
, q
, s
);
515 /* If this a single-label domain on DNS, we might append a suitable search domain first. */
516 if (!FLAGS_SET(q
->flags
, SD_RESOLVED_NO_SEARCH
) &&
517 dns_scope_name_wants_search_domain(s
, dns_question_first_name(q
->question_idna
))) {
518 /* OK, we want a search domain now. Let's find one for this scope */
520 r
= dns_query_candidate_next_search_domain(c
);
525 r
= dns_query_candidate_setup_transactions(c
);
533 static int dns_query_synthesize_reply(DnsQuery
*q
, DnsTransactionState
*state
) {
534 _cleanup_(dns_answer_unrefp
) DnsAnswer
*answer
= NULL
;
540 /* Tries to synthesize localhost RR replies (and others) where appropriate. Note that this is done *after* the
541 * the normal lookup finished. The data from the network hence takes precedence over the data we
542 * synthesize. (But note that many scopes refuse to resolve certain domain names) */
545 DNS_TRANSACTION_RCODE_FAILURE
,
546 DNS_TRANSACTION_NO_SERVERS
,
547 DNS_TRANSACTION_TIMEOUT
,
548 DNS_TRANSACTION_ATTEMPTS_MAX_REACHED
,
549 DNS_TRANSACTION_NETWORK_DOWN
,
550 DNS_TRANSACTION_NOT_FOUND
))
553 r
= dns_synthesize_answer(
559 /* If we get ENXIO this tells us to generate NXDOMAIN unconditionally. */
561 dns_query_reset_answer(q
);
562 q
->answer_rcode
= DNS_RCODE_NXDOMAIN
;
563 q
->answer_protocol
= dns_synthesize_protocol(q
->flags
);
564 q
->answer_family
= dns_synthesize_family(q
->flags
);
565 q
->answer_authenticated
= true;
566 *state
= DNS_TRANSACTION_RCODE_FAILURE
;
573 dns_query_reset_answer(q
);
575 q
->answer
= TAKE_PTR(answer
);
576 q
->answer_rcode
= DNS_RCODE_SUCCESS
;
577 q
->answer_protocol
= dns_synthesize_protocol(q
->flags
);
578 q
->answer_family
= dns_synthesize_family(q
->flags
);
579 q
->answer_authenticated
= true;
581 *state
= DNS_TRANSACTION_SUCCESS
;
586 static int dns_query_try_etc_hosts(DnsQuery
*q
) {
587 _cleanup_(dns_answer_unrefp
) DnsAnswer
*answer
= NULL
;
592 /* Looks in /etc/hosts for matching entries. Note that this is done *before* the normal lookup is done. The
593 * data from /etc/hosts hence takes precedence over the network. */
595 r
= manager_etc_hosts_lookup(
602 dns_query_reset_answer(q
);
604 q
->answer
= TAKE_PTR(answer
);
605 q
->answer_rcode
= DNS_RCODE_SUCCESS
;
606 q
->answer_protocol
= dns_synthesize_protocol(q
->flags
);
607 q
->answer_family
= dns_synthesize_family(q
->flags
);
608 q
->answer_authenticated
= true;
613 int dns_query_go(DnsQuery
*q
) {
614 DnsScopeMatch found
= DNS_SCOPE_NO
;
615 DnsScope
*s
, *first
= NULL
;
616 DnsQueryCandidate
*c
;
621 if (q
->state
!= DNS_TRANSACTION_NULL
)
624 r
= dns_query_try_etc_hosts(q
);
628 dns_query_complete(q
, DNS_TRANSACTION_SUCCESS
);
632 LIST_FOREACH(scopes
, s
, q
->manager
->dns_scopes
) {
636 name
= dns_question_first_name(dns_query_question_for_protocol(q
, s
->protocol
));
640 match
= dns_scope_good_domain(s
, q
->ifindex
, q
->flags
, name
);
642 log_debug("Couldn't check if '%s' matches against scope, ignoring.", name
);
646 if (match
> found
) { /* Does this match better? If so, remember how well it matched, and the first one
647 * that matches this well */
653 if (found
== DNS_SCOPE_NO
) {
654 DnsTransactionState state
= DNS_TRANSACTION_NO_SERVERS
;
656 r
= dns_query_synthesize_reply(q
, &state
);
660 dns_query_complete(q
, state
);
664 r
= dns_query_add_candidate(q
, first
);
668 LIST_FOREACH(scopes
, s
, first
->scopes_next
) {
672 name
= dns_question_first_name(dns_query_question_for_protocol(q
, s
->protocol
));
676 match
= dns_scope_good_domain(s
, q
->ifindex
, q
->flags
, name
);
678 log_debug("Couldn't check if '%s' matches against scope, ignoring.", name
);
685 r
= dns_query_add_candidate(q
, s
);
690 dns_query_reset_answer(q
);
692 r
= sd_event_add_time_relative(
694 &q
->timeout_event_source
,
695 clock_boottime_or_monotonic(),
696 SD_RESOLVED_QUERY_TIMEOUT_USEC
,
697 0, on_query_timeout
, q
);
701 (void) sd_event_source_set_description(q
->timeout_event_source
, "query-timeout");
703 q
->state
= DNS_TRANSACTION_PENDING
;
706 /* Start the transactions */
707 LIST_FOREACH(candidates_by_query
, c
, q
->candidates
) {
708 r
= dns_query_candidate_go(c
);
725 static void dns_query_accept(DnsQuery
*q
, DnsQueryCandidate
*c
) {
726 DnsTransactionState state
= DNS_TRANSACTION_NO_SERVERS
;
727 bool has_authenticated
= false, has_non_authenticated
= false;
728 DnssecResult dnssec_result_authenticated
= _DNSSEC_RESULT_INVALID
, dnssec_result_non_authenticated
= _DNSSEC_RESULT_INVALID
;
735 r
= dns_query_synthesize_reply(q
, &state
);
739 dns_query_complete(q
, state
);
743 if (c
->error_code
!= 0) {
744 /* If the candidate had an error condition of its own, start with that. */
745 state
= DNS_TRANSACTION_ERRNO
;
746 q
->answer
= dns_answer_unref(q
->answer
);
748 q
->answer_dnssec_result
= _DNSSEC_RESULT_INVALID
;
749 q
->answer_authenticated
= false;
750 q
->answer_errno
= c
->error_code
;
753 SET_FOREACH(t
, c
->transactions
) {
757 case DNS_TRANSACTION_SUCCESS
: {
758 /* We found a successfully reply, merge it into the answer */
759 r
= dns_answer_extend(&q
->answer
, t
->answer
);
763 q
->answer_rcode
= t
->answer_rcode
;
766 if (t
->answer_authenticated
) {
767 has_authenticated
= true;
768 dnssec_result_authenticated
= t
->answer_dnssec_result
;
770 has_non_authenticated
= true;
771 dnssec_result_non_authenticated
= t
->answer_dnssec_result
;
774 state
= DNS_TRANSACTION_SUCCESS
;
778 case DNS_TRANSACTION_NULL
:
779 case DNS_TRANSACTION_PENDING
:
780 case DNS_TRANSACTION_VALIDATING
:
781 case DNS_TRANSACTION_ABORTED
:
782 /* Ignore transactions that didn't complete */
786 /* Any kind of failure? Store the data away, if there's nothing stored yet. */
787 if (state
== DNS_TRANSACTION_SUCCESS
)
790 /* If there's already an authenticated negative reply stored, then prefer that over any unauthenticated one */
791 if (q
->answer_authenticated
&& !t
->answer_authenticated
)
794 q
->answer
= dns_answer_unref(q
->answer
);
795 q
->answer_rcode
= t
->answer_rcode
;
796 q
->answer_dnssec_result
= t
->answer_dnssec_result
;
797 q
->answer_authenticated
= t
->answer_authenticated
;
798 q
->answer_errno
= t
->answer_errno
;
805 if (state
== DNS_TRANSACTION_SUCCESS
) {
806 q
->answer_authenticated
= has_authenticated
&& !has_non_authenticated
;
807 q
->answer_dnssec_result
= q
->answer_authenticated
? dnssec_result_authenticated
: dnssec_result_non_authenticated
;
810 q
->answer_protocol
= c
->scope
->protocol
;
811 q
->answer_family
= c
->scope
->family
;
813 dns_search_domain_unref(q
->answer_search_domain
);
814 q
->answer_search_domain
= dns_search_domain_ref(c
->search_domain
);
816 r
= dns_query_synthesize_reply(q
, &state
);
820 dns_query_complete(q
, state
);
824 q
->answer_errno
= -r
;
825 dns_query_complete(q
, DNS_TRANSACTION_ERRNO
);
828 void dns_query_ready(DnsQuery
*q
) {
830 DnsQueryCandidate
*bad
= NULL
, *c
;
831 bool pending
= false;
834 assert(DNS_TRANSACTION_IS_LIVE(q
->state
));
836 /* Note that this call might invalidate the query. Callers
837 * should hence not attempt to access the query or transaction
838 * after calling this function, unless the block_ready
839 * counter was explicitly bumped before doing so. */
841 if (q
->block_ready
> 0)
844 LIST_FOREACH(candidates_by_query
, c
, q
->candidates
) {
845 DnsTransactionState state
;
847 state
= dns_query_candidate_state(c
);
850 case DNS_TRANSACTION_SUCCESS
:
851 /* One of the candidates is successful,
852 * let's use it, and copy its data out */
853 dns_query_accept(q
, c
);
856 case DNS_TRANSACTION_NULL
:
857 case DNS_TRANSACTION_PENDING
:
858 case DNS_TRANSACTION_VALIDATING
:
859 /* One of the candidates is still going on,
860 * let's maybe wait for it */
865 /* Any kind of failure */
874 dns_query_accept(q
, bad
);
877 static int dns_query_cname_redirect(DnsQuery
*q
, const DnsResourceRecord
*cname
) {
878 _cleanup_(dns_question_unrefp
) DnsQuestion
*nq_idna
= NULL
, *nq_utf8
= NULL
;
883 q
->n_cname_redirects
++;
884 if (q
->n_cname_redirects
> CNAME_MAX
)
887 r
= dns_question_cname_redirect(q
->question_idna
, cname
, &nq_idna
);
891 log_debug("Following CNAME/DNAME %s → %s.", dns_question_first_name(q
->question_idna
), dns_question_first_name(nq_idna
));
893 k
= dns_question_is_equal(q
->question_idna
, q
->question_utf8
);
897 /* Same question? Shortcut new question generation */
898 nq_utf8
= dns_question_ref(nq_idna
);
901 k
= dns_question_cname_redirect(q
->question_utf8
, cname
, &nq_utf8
);
905 log_debug("Following UTF8 CNAME/DNAME %s → %s.", dns_question_first_name(q
->question_utf8
), dns_question_first_name(nq_utf8
));
908 if (r
== 0 && k
== 0) /* No actual cname happened? */
911 if (q
->answer_protocol
== DNS_PROTOCOL_DNS
) {
912 /* Don't permit CNAME redirects from unicast DNS to LLMNR or MulticastDNS, so that global resources
913 * cannot invade the local namespace. The opposite way we permit: local names may redirect to global
916 q
->flags
&= ~(SD_RESOLVED_LLMNR
|SD_RESOLVED_MDNS
); /* mask away the local protocols */
919 /* Turn off searching for the new name */
920 q
->flags
|= SD_RESOLVED_NO_SEARCH
;
922 dns_question_unref(q
->question_idna
);
923 q
->question_idna
= TAKE_PTR(nq_idna
);
925 dns_question_unref(q
->question_utf8
);
926 q
->question_utf8
= TAKE_PTR(nq_utf8
);
928 dns_query_free_candidates(q
);
929 dns_query_reset_answer(q
);
931 q
->state
= DNS_TRANSACTION_NULL
;
936 int dns_query_process_cname(DnsQuery
*q
) {
937 _cleanup_(dns_resource_record_unrefp
) DnsResourceRecord
*cname
= NULL
;
938 DnsQuestion
*question
;
939 DnsResourceRecord
*rr
;
944 if (!IN_SET(q
->state
, DNS_TRANSACTION_SUCCESS
, DNS_TRANSACTION_NULL
))
945 return DNS_QUERY_NOMATCH
;
947 question
= dns_query_question_for_protocol(q
, q
->answer_protocol
);
949 DNS_ANSWER_FOREACH(rr
, q
->answer
) {
950 r
= dns_question_matches_rr(question
, rr
, DNS_SEARCH_DOMAIN_NAME(q
->answer_search_domain
));
954 return DNS_QUERY_MATCH
; /* The answer matches directly, no need to follow cnames */
956 r
= dns_question_matches_cname_or_dname(question
, rr
, DNS_SEARCH_DOMAIN_NAME(q
->answer_search_domain
));
960 cname
= dns_resource_record_ref(rr
);
964 return DNS_QUERY_NOMATCH
; /* No match and no cname to follow */
966 if (q
->flags
& SD_RESOLVED_NO_CNAME
)
969 if (!q
->answer_authenticated
)
970 q
->previous_redirect_unauthenticated
= true;
972 /* OK, let's actually follow the CNAME */
973 r
= dns_query_cname_redirect(q
, cname
);
977 /* Let's see if the answer can already answer the new
978 * redirected question */
979 r
= dns_query_process_cname(q
);
980 if (r
!= DNS_QUERY_NOMATCH
)
983 /* OK, it cannot, let's begin with the new query */
988 return DNS_QUERY_RESTARTED
; /* We restarted the query for a new cname */
991 DnsQuestion
* dns_query_question_for_protocol(DnsQuery
*q
, DnsProtocol protocol
) {
996 case DNS_PROTOCOL_DNS
:
997 return q
->question_idna
;
999 case DNS_PROTOCOL_MDNS
:
1000 case DNS_PROTOCOL_LLMNR
:
1001 return q
->question_utf8
;
1008 const char *dns_query_string(DnsQuery
*q
) {
1012 /* Returns a somewhat useful human-readable lookup key string for this query */
1014 if (q
->request_address_string
)
1015 return q
->request_address_string
;
1017 if (q
->request_address_valid
) {
1018 r
= in_addr_to_string(q
->request_family
, &q
->request_address
, &q
->request_address_string
);
1020 return q
->request_address_string
;
1023 name
= dns_question_first_name(q
->question_utf8
);
1027 return dns_question_first_name(q
->question_idna
);
1030 bool dns_query_fully_authenticated(DnsQuery
*q
) {
1033 return q
->answer_authenticated
&& !q
->previous_redirect_unauthenticated
;