1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
3 #include "alloc-util.h"
4 #include "dns-domain.h"
6 #include "event-util.h"
7 #include "glyph-util.h"
8 #include "hostname-util.h"
9 #include "local-addresses.h"
10 #include "resolved-dns-query.h"
11 #include "resolved-dns-synthesize.h"
12 #include "resolved-etc-hosts.h"
13 #include "string-util.h"
15 #define QUERIES_MAX 2048
16 #define AUXILIARY_QUERIES_MAX 64
17 #define CNAME_REDIRECTS_MAX 16
19 assert_cc(AUXILIARY_QUERIES_MAX
< UINT8_MAX
);
20 assert_cc(CNAME_REDIRECTS_MAX
< UINT8_MAX
);
22 static int dns_query_candidate_new(DnsQueryCandidate
**ret
, DnsQuery
*q
, DnsScope
*s
) {
29 c
= new(DnsQueryCandidate
, 1);
33 *c
= (DnsQueryCandidate
) {
39 LIST_PREPEND(candidates_by_query
, q
->candidates
, c
);
40 LIST_PREPEND(candidates_by_scope
, s
->query_candidates
, c
);
46 static void dns_query_candidate_stop(DnsQueryCandidate
*c
) {
51 /* Detach all the DnsTransactions attached to this query */
53 while ((t
= set_steal_first(c
->transactions
))) {
54 set_remove(t
->notify_query_candidates
, c
);
55 set_remove(t
->notify_query_candidates_done
, c
);
56 dns_transaction_gc(t
);
60 static void dns_query_candidate_abandon(DnsQueryCandidate
*c
) {
65 /* Abandon all the DnsTransactions attached to this query */
67 while ((t
= set_steal_first(c
->transactions
))) {
68 t
->wait_for_answer
= true;
69 set_remove(t
->notify_query_candidates
, c
);
70 set_remove(t
->notify_query_candidates_done
, c
);
71 dns_transaction_gc(t
);
75 static DnsQueryCandidate
* dns_query_candidate_unlink(DnsQueryCandidate
*c
) {
78 /* Detach this DnsQueryCandidate from the Query and Scope objects */
81 LIST_REMOVE(candidates_by_query
, c
->query
->candidates
, c
);
86 LIST_REMOVE(candidates_by_scope
, c
->scope
->query_candidates
, c
);
93 static DnsQueryCandidate
* dns_query_candidate_free(DnsQueryCandidate
*c
) {
97 dns_query_candidate_stop(c
);
98 dns_query_candidate_unlink(c
);
100 set_free(c
->transactions
);
101 dns_search_domain_unref(c
->search_domain
);
106 DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(DnsQueryCandidate
, dns_query_candidate
, dns_query_candidate_free
);
108 static int dns_query_candidate_next_search_domain(DnsQueryCandidate
*c
) {
109 DnsSearchDomain
*next
;
113 if (c
->search_domain
&& c
->search_domain
->linked
)
114 next
= c
->search_domain
->domains_next
;
116 next
= dns_scope_get_search_domains(c
->scope
);
119 if (!next
) /* We hit the end of the list */
122 if (!next
->route_only
)
125 /* Skip over route-only domains */
126 next
= next
->domains_next
;
129 dns_search_domain_unref(c
->search_domain
);
130 c
->search_domain
= dns_search_domain_ref(next
);
135 static int dns_query_candidate_add_transaction(
136 DnsQueryCandidate
*c
,
140 _cleanup_(dns_transaction_gcp
) DnsTransaction
*t
= NULL
;
144 assert(c
->query
); /* We shan't add transactions to a candidate that has been detached already */
147 /* Regular lookup with a resource key */
150 t
= dns_scope_find_transaction(c
->scope
, key
, c
->query
->flags
);
152 r
= dns_transaction_new(&t
, c
->scope
, key
, NULL
, c
->query
->flags
);
155 } else if (set_contains(c
->transactions
, t
))
158 /* "Bypass" lookup with a query packet */
161 r
= dns_transaction_new(&t
, c
->scope
, NULL
, bypass
, c
->query
->flags
);
166 r
= set_ensure_allocated(&t
->notify_query_candidates_done
, NULL
);
170 r
= set_ensure_put(&t
->notify_query_candidates
, NULL
, c
);
174 r
= set_ensure_put(&c
->transactions
, NULL
, t
);
176 (void) set_remove(t
->notify_query_candidates
, c
);
184 static int dns_query_candidate_go(DnsQueryCandidate
*c
) {
185 _unused_
_cleanup_(dns_query_candidate_unrefp
) DnsQueryCandidate
*keep_c
= NULL
;
192 /* Let's keep a reference to the query while we're operating */
193 keep_c
= dns_query_candidate_ref(c
);
195 /* Start the transactions that are not started yet */
196 SET_FOREACH(t
, c
->transactions
) {
197 if (t
->state
!= DNS_TRANSACTION_NULL
)
200 r
= dns_transaction_go(t
);
207 /* If there was nothing to start, then let's proceed immediately */
209 dns_query_candidate_notify(c
);
214 static DnsTransactionState
dns_query_candidate_state(DnsQueryCandidate
*c
) {
215 DnsTransactionState state
= DNS_TRANSACTION_NO_SERVERS
;
220 if (c
->error_code
!= 0)
221 return DNS_TRANSACTION_ERRNO
;
223 SET_FOREACH(t
, c
->transactions
)
227 case DNS_TRANSACTION_NULL
:
228 /* If there's a NULL transaction pending, then
229 * this means not all transactions where
230 * started yet, and we were called from within
231 * the stackframe that is supposed to start
232 * remaining transactions. In this case,
233 * simply claim the candidate is pending. */
235 case DNS_TRANSACTION_PENDING
:
236 case DNS_TRANSACTION_VALIDATING
:
237 /* If there's one transaction currently in
238 * VALIDATING state, then this means there's
239 * also one in PENDING state, hence we can
240 * return PENDING immediately. */
241 return DNS_TRANSACTION_PENDING
;
243 case DNS_TRANSACTION_SUCCESS
:
248 if (state
!= DNS_TRANSACTION_SUCCESS
)
257 static int dns_query_candidate_setup_transactions(DnsQueryCandidate
*c
) {
258 DnsQuestion
*question
;
263 assert(c
->query
); /* We shan't add transactions to a candidate that has been detached already */
265 dns_query_candidate_stop(c
);
267 if (c
->query
->question_bypass
) {
268 /* If this is a bypass query, then pass the original query packet along to the transaction */
270 assert(dns_question_size(c
->query
->question_bypass
->question
) == 1);
272 if (!dns_scope_good_key(c
->scope
, dns_question_first_key(c
->query
->question_bypass
->question
)))
275 r
= dns_query_candidate_add_transaction(c
, NULL
, c
->query
->question_bypass
);
282 question
= dns_query_question_for_protocol(c
->query
, c
->scope
->protocol
);
284 /* Create one transaction per question key */
285 DNS_QUESTION_FOREACH(key
, question
) {
286 _cleanup_(dns_resource_key_unrefp
) DnsResourceKey
*new_key
= NULL
;
287 DnsResourceKey
*qkey
;
289 if (c
->search_domain
) {
290 r
= dns_resource_key_new_append_suffix(&new_key
, key
, c
->search_domain
->name
);
298 if (!dns_scope_good_key(c
->scope
, qkey
))
301 r
= dns_query_candidate_add_transaction(c
, qkey
, NULL
);
311 dns_query_candidate_stop(c
);
315 void dns_query_candidate_notify(DnsQueryCandidate
*c
) {
316 DnsTransactionState state
;
321 if (!c
->query
) /* This candidate has been abandoned, do nothing. */
324 state
= dns_query_candidate_state(c
);
326 if (DNS_TRANSACTION_IS_LIVE(state
))
329 if (state
!= DNS_TRANSACTION_SUCCESS
&& c
->search_domain
) {
331 r
= dns_query_candidate_next_search_domain(c
);
336 /* OK, there's another search domain to try, let's do so. */
338 r
= dns_query_candidate_setup_transactions(c
);
343 /* New transactions where queued. Start them and wait */
345 r
= dns_query_candidate_go(c
);
355 dns_query_ready(c
->query
);
359 c
->error_code
= log_warning_errno(r
, "Failed to follow search domains: %m");
360 dns_query_ready(c
->query
);
363 static void dns_query_stop(DnsQuery
*q
) {
366 event_source_disable(q
->timeout_event_source
);
368 LIST_FOREACH(candidates_by_query
, c
, q
->candidates
)
369 dns_query_candidate_stop(c
);
372 static void dns_query_abandon(DnsQuery
*q
) {
375 /* Thankfully transactions have their own timeouts */
376 event_source_disable(q
->timeout_event_source
);
378 LIST_FOREACH(candidates_by_query
, c
, q
->candidates
)
379 dns_query_candidate_abandon(c
);
382 static void dns_query_unlink_candidates(DnsQuery
*q
) {
385 while (q
->candidates
)
386 /* Here we drop *our* references to each of the candidates. If we had the only reference, the
387 * DnsQueryCandidate object will be freed. */
388 dns_query_candidate_unref(dns_query_candidate_unlink(q
->candidates
));
391 static void dns_query_reset_answer(DnsQuery
*q
) {
394 q
->answer
= dns_answer_unref(q
->answer
);
396 q
->answer_ede_rcode
= _DNS_EDE_RCODE_INVALID
;
397 q
->answer_ede_msg
= mfree(q
->answer_ede_msg
);
398 q
->answer_dnssec_result
= _DNSSEC_RESULT_INVALID
;
400 q
->answer_query_flags
= 0;
401 q
->answer_protocol
= _DNS_PROTOCOL_INVALID
;
402 q
->answer_family
= AF_UNSPEC
;
403 q
->answer_search_domain
= dns_search_domain_unref(q
->answer_search_domain
);
404 q
->answer_full_packet
= dns_packet_unref(q
->answer_full_packet
);
407 DnsQuery
*dns_query_free(DnsQuery
*q
) {
411 q
->timeout_event_source
= sd_event_source_disable_unref(q
->timeout_event_source
);
413 while (q
->auxiliary_queries
)
414 dns_query_free(q
->auxiliary_queries
);
416 if (q
->auxiliary_for
) {
417 assert(q
->auxiliary_for
->n_auxiliary_queries
> 0);
418 q
->auxiliary_for
->n_auxiliary_queries
--;
419 LIST_REMOVE(auxiliary_queries
, q
->auxiliary_for
->auxiliary_queries
, q
);
422 dns_query_unlink_candidates(q
);
424 dns_question_unref(q
->question_idna
);
425 dns_question_unref(q
->question_utf8
);
426 dns_packet_unref(q
->question_bypass
);
427 dns_question_unref(q
->collected_questions
);
429 dns_query_reset_answer(q
);
431 sd_bus_message_unref(q
->bus_request
);
432 sd_bus_track_unref(q
->bus_track
);
434 if (q
->varlink_request
) {
435 varlink_set_userdata(q
->varlink_request
, NULL
);
436 varlink_unref(q
->varlink_request
);
439 if (q
->request_packet
)
440 hashmap_remove_value(q
->stub_listener_extra
?
441 q
->stub_listener_extra
->queries_by_packet
:
442 q
->manager
->stub_queries_by_packet
,
446 dns_packet_unref(q
->request_packet
);
447 dns_answer_unref(q
->reply_answer
);
448 dns_answer_unref(q
->reply_authoritative
);
449 dns_answer_unref(q
->reply_additional
);
451 if (q
->request_stream
) {
452 /* Detach the stream from our query, in case something else keeps a reference to it. */
453 (void) set_remove(q
->request_stream
->queries
, q
);
454 q
->request_stream
= dns_stream_unref(q
->request_stream
);
457 free(q
->request_address_string
);
460 LIST_REMOVE(queries
, q
->manager
->dns_queries
, q
);
461 q
->manager
->n_dns_queries
--;
470 DnsQuestion
*question_utf8
,
471 DnsQuestion
*question_idna
,
472 DnsPacket
*question_bypass
,
476 _cleanup_(dns_query_freep
) DnsQuery
*q
= NULL
;
477 char key_str
[DNS_RESOURCE_KEY_STRING_MAX
];
483 if (question_bypass
) {
484 /* It's either a "bypass" query, or a regular one, but can't be both. */
485 if (question_utf8
|| question_idna
)
491 /* This (primarily) checks two things:
493 * 1. That the question is not empty
494 * 2. That all RR keys in the question objects are for the same domain
496 * Or in other words, a single DnsQuery object may be used to look up A+AAAA combination for
497 * the same domain name, or SRV+TXT (for DNS-SD services), but not for unrelated lookups. */
499 if (dns_question_size(question_utf8
) > 0) {
500 r
= dns_question_is_valid_for_query(question_utf8
);
509 /* If the IDNA and UTF8 questions are the same, merge their references */
510 r
= dns_question_is_equal(question_idna
, question_utf8
);
514 question_idna
= question_utf8
;
516 if (dns_question_size(question_idna
) > 0) {
517 r
= dns_question_is_valid_for_query(question_idna
);
527 if (!good
) /* don't allow empty queries */
531 if (m
->n_dns_queries
>= QUERIES_MAX
)
534 q
= new(DnsQuery
, 1);
539 .question_utf8
= dns_question_ref(question_utf8
),
540 .question_idna
= dns_question_ref(question_idna
),
541 .question_bypass
= dns_packet_ref(question_bypass
),
544 .answer_ede_rcode
= _DNS_EDE_RCODE_INVALID
,
545 .answer_dnssec_result
= _DNSSEC_RESULT_INVALID
,
546 .answer_protocol
= _DNS_PROTOCOL_INVALID
,
547 .answer_family
= AF_UNSPEC
,
550 if (question_bypass
) {
551 DNS_QUESTION_FOREACH(key
, question_bypass
->question
)
552 log_debug("Looking up bypass packet for %s.",
553 dns_resource_key_to_string(key
, key_str
, sizeof key_str
));
555 /* First dump UTF8 question */
556 DNS_QUESTION_FOREACH(key
, question_utf8
)
557 log_debug("Looking up RR for %s.",
558 dns_resource_key_to_string(key
, key_str
, sizeof key_str
));
560 /* And then dump the IDNA question, but only what hasn't been dumped already through the UTF8 question. */
561 DNS_QUESTION_FOREACH(key
, question_idna
) {
562 r
= dns_question_contains_key(question_utf8
, key
);
568 log_debug("Looking up IDNA RR for %s.",
569 dns_resource_key_to_string(key
, key_str
, sizeof key_str
));
573 LIST_PREPEND(queries
, m
->dns_queries
, q
);
584 int dns_query_make_auxiliary(DnsQuery
*q
, DnsQuery
*auxiliary_for
) {
586 assert(auxiliary_for
);
588 /* Ensure that the query is not auxiliary yet, and
589 * nothing else is auxiliary to it either */
590 assert(!q
->auxiliary_for
);
591 assert(!q
->auxiliary_queries
);
593 /* Ensure that the unit we shall be made auxiliary for isn't
594 * auxiliary itself */
595 assert(!auxiliary_for
->auxiliary_for
);
597 if (auxiliary_for
->n_auxiliary_queries
>= AUXILIARY_QUERIES_MAX
)
600 LIST_PREPEND(auxiliary_queries
, auxiliary_for
->auxiliary_queries
, q
);
601 q
->auxiliary_for
= auxiliary_for
;
603 auxiliary_for
->n_auxiliary_queries
++;
607 void dns_query_complete(DnsQuery
*q
, DnsTransactionState state
) {
609 assert(!DNS_TRANSACTION_IS_LIVE(state
));
610 assert(DNS_TRANSACTION_IS_LIVE(q
->state
));
612 /* Note that this call might invalidate the query. Callers should hence not attempt to access the
613 * query or transaction after calling this function. */
617 (void) manager_monitor_send(q
->manager
, q
);
619 dns_query_abandon(q
);
624 static int on_query_timeout(sd_event_source
*s
, usec_t usec
, void *userdata
) {
625 DnsQuery
*q
= ASSERT_PTR(userdata
);
629 dns_query_complete(q
, DNS_TRANSACTION_TIMEOUT
);
633 static int dns_query_add_candidate(DnsQuery
*q
, DnsScope
*s
) {
634 _cleanup_(dns_query_candidate_unrefp
) DnsQueryCandidate
*c
= NULL
;
640 r
= dns_query_candidate_new(&c
, q
, s
);
644 /* If this a single-label domain on DNS, we might append a suitable search domain first. */
645 if (!FLAGS_SET(q
->flags
, SD_RESOLVED_NO_SEARCH
) &&
646 dns_scope_name_wants_search_domain(s
, dns_question_first_name(q
->question_idna
))) {
647 /* OK, we want a search domain now. Let's find one for this scope */
649 r
= dns_query_candidate_next_search_domain(c
);
654 r
= dns_query_candidate_setup_transactions(c
);
662 static int dns_query_synthesize_reply(DnsQuery
*q
, DnsTransactionState
*state
) {
663 _cleanup_(dns_answer_unrefp
) DnsAnswer
*answer
= NULL
;
669 /* Tries to synthesize localhost RR replies (and others) where appropriate. Note that this is done *after* the
670 * the normal lookup finished. The data from the network hence takes precedence over the data we
671 * synthesize. (But note that many scopes refuse to resolve certain domain names) */
674 DNS_TRANSACTION_RCODE_FAILURE
,
675 DNS_TRANSACTION_NO_SERVERS
,
676 DNS_TRANSACTION_TIMEOUT
,
677 DNS_TRANSACTION_ATTEMPTS_MAX_REACHED
,
678 DNS_TRANSACTION_NETWORK_DOWN
,
679 DNS_TRANSACTION_NOT_FOUND
))
682 if (FLAGS_SET(q
->flags
, SD_RESOLVED_NO_SYNTHESIZE
))
685 r
= dns_synthesize_answer(
687 q
->question_bypass
? q
->question_bypass
->question
: q
->question_utf8
,
691 /* If we get ENXIO this tells us to generate NXDOMAIN unconditionally. */
693 dns_query_reset_answer(q
);
694 q
->answer_rcode
= DNS_RCODE_NXDOMAIN
;
695 q
->answer_protocol
= dns_synthesize_protocol(q
->flags
);
696 q
->answer_family
= dns_synthesize_family(q
->flags
);
697 q
->answer_query_flags
= SD_RESOLVED_AUTHENTICATED
|SD_RESOLVED_CONFIDENTIAL
|SD_RESOLVED_SYNTHETIC
;
698 *state
= DNS_TRANSACTION_RCODE_FAILURE
;
700 log_debug("Found synthetic NXDOMAIN response.");
707 dns_query_reset_answer(q
);
709 q
->answer
= TAKE_PTR(answer
);
710 q
->answer_rcode
= DNS_RCODE_SUCCESS
;
711 q
->answer_protocol
= dns_synthesize_protocol(q
->flags
);
712 q
->answer_family
= dns_synthesize_family(q
->flags
);
713 q
->answer_query_flags
= SD_RESOLVED_AUTHENTICATED
|SD_RESOLVED_CONFIDENTIAL
|SD_RESOLVED_SYNTHETIC
;
715 *state
= DNS_TRANSACTION_SUCCESS
;
717 log_debug("Found synthetic success response.");
722 static int dns_query_try_etc_hosts(DnsQuery
*q
) {
723 _cleanup_(dns_answer_unrefp
) DnsAnswer
*answer
= NULL
;
728 /* Looks in /etc/hosts for matching entries. Note that this is done *before* the normal lookup is
729 * done. The data from /etc/hosts hence takes precedence over the network. */
731 if (FLAGS_SET(q
->flags
, SD_RESOLVED_NO_SYNTHESIZE
))
734 r
= manager_etc_hosts_lookup(
736 q
->question_bypass
? q
->question_bypass
->question
: q
->question_utf8
,
741 dns_query_reset_answer(q
);
743 q
->answer
= TAKE_PTR(answer
);
744 q
->answer_rcode
= DNS_RCODE_SUCCESS
;
745 q
->answer_protocol
= dns_synthesize_protocol(q
->flags
);
746 q
->answer_family
= dns_synthesize_family(q
->flags
);
747 q
->answer_query_flags
= SD_RESOLVED_AUTHENTICATED
|SD_RESOLVED_CONFIDENTIAL
|SD_RESOLVED_SYNTHETIC
;
752 int dns_query_go(DnsQuery
*q
) {
753 DnsScopeMatch found
= DNS_SCOPE_NO
;
754 DnsScope
*first
= NULL
;
759 if (q
->state
!= DNS_TRANSACTION_NULL
)
762 r
= dns_query_try_etc_hosts(q
);
766 dns_query_complete(q
, DNS_TRANSACTION_SUCCESS
);
770 LIST_FOREACH(scopes
, s
, q
->manager
->dns_scopes
) {
773 match
= dns_scope_good_domain(s
, q
, q
->flags
);
775 if (match
> found
) { /* Does this match better? If so, remember how well it matched, and the first one
776 * that matches this well */
782 if (found
== DNS_SCOPE_NO
) {
783 DnsTransactionState state
= DNS_TRANSACTION_NO_SERVERS
;
785 r
= dns_query_synthesize_reply(q
, &state
);
789 dns_query_complete(q
, state
);
793 r
= dns_query_add_candidate(q
, first
);
797 LIST_FOREACH(scopes
, s
, first
->scopes_next
) {
800 match
= dns_scope_good_domain(s
, q
, q
->flags
);
805 r
= dns_query_add_candidate(q
, s
);
810 dns_query_reset_answer(q
);
812 r
= event_reset_time_relative(
814 &q
->timeout_event_source
,
816 SD_RESOLVED_QUERY_TIMEOUT_USEC
,
817 0, on_query_timeout
, q
,
818 0, "query-timeout", true);
822 q
->state
= DNS_TRANSACTION_PENDING
;
825 /* Start the transactions */
826 LIST_FOREACH(candidates_by_query
, c
, q
->candidates
) {
827 r
= dns_query_candidate_go(c
);
844 static void dns_query_accept(DnsQuery
*q
, DnsQueryCandidate
*c
) {
845 DnsTransactionState state
= DNS_TRANSACTION_NO_SERVERS
;
846 bool has_authenticated
= false, has_non_authenticated
= false, has_confidential
= false, has_non_confidential
= false;
847 DnssecResult dnssec_result_authenticated
= _DNSSEC_RESULT_INVALID
, dnssec_result_non_authenticated
= _DNSSEC_RESULT_INVALID
;
854 r
= dns_query_synthesize_reply(q
, &state
);
858 dns_query_complete(q
, state
);
862 if (c
->error_code
!= 0) {
863 /* If the candidate had an error condition of its own, start with that. */
864 state
= DNS_TRANSACTION_ERRNO
;
865 q
->answer
= dns_answer_unref(q
->answer
);
867 q
->answer_dnssec_result
= _DNSSEC_RESULT_INVALID
;
868 q
->answer_query_flags
= 0;
869 q
->answer_errno
= c
->error_code
;
870 q
->answer_full_packet
= dns_packet_unref(q
->answer_full_packet
);
873 SET_FOREACH(t
, c
->transactions
) {
877 case DNS_TRANSACTION_SUCCESS
: {
878 /* We found a successful reply, merge it into the answer */
880 if (state
== DNS_TRANSACTION_SUCCESS
) {
881 r
= dns_answer_extend(&q
->answer
, t
->answer
);
885 q
->answer_query_flags
|= dns_transaction_source_to_query_flags(t
->answer_source
);
887 /* Override non-successful previous answers */
888 DNS_ANSWER_REPLACE(q
->answer
, dns_answer_ref(t
->answer
));
889 q
->answer_query_flags
= dns_transaction_source_to_query_flags(t
->answer_source
);
892 q
->answer_rcode
= t
->answer_rcode
;
895 DNS_PACKET_REPLACE(q
->answer_full_packet
, dns_packet_ref(t
->received
));
897 if (FLAGS_SET(t
->answer_query_flags
, SD_RESOLVED_AUTHENTICATED
)) {
898 has_authenticated
= true;
899 dnssec_result_authenticated
= t
->answer_dnssec_result
;
901 has_non_authenticated
= true;
902 dnssec_result_non_authenticated
= t
->answer_dnssec_result
;
905 if (FLAGS_SET(t
->answer_query_flags
, SD_RESOLVED_CONFIDENTIAL
))
906 has_confidential
= true;
908 has_non_confidential
= true;
910 state
= DNS_TRANSACTION_SUCCESS
;
914 case DNS_TRANSACTION_NULL
:
915 case DNS_TRANSACTION_PENDING
:
916 case DNS_TRANSACTION_VALIDATING
:
917 case DNS_TRANSACTION_ABORTED
:
918 /* Ignore transactions that didn't complete */
922 /* Any kind of failure? Store the data away, if there's nothing stored yet. */
923 if (state
== DNS_TRANSACTION_SUCCESS
)
926 /* If there's already an authenticated negative reply stored, then prefer that over any unauthenticated one */
927 if (FLAGS_SET(q
->answer_query_flags
, SD_RESOLVED_AUTHENTICATED
) &&
928 !FLAGS_SET(t
->answer_query_flags
, SD_RESOLVED_AUTHENTICATED
))
931 DNS_ANSWER_REPLACE(q
->answer
, dns_answer_ref(t
->answer
));
932 q
->answer_rcode
= t
->answer_rcode
;
933 q
->answer_ede_rcode
= t
->answer_ede_rcode
;
934 r
= free_and_strdup_warn(&q
->answer_ede_msg
, t
->answer_ede_msg
);
937 q
->answer_dnssec_result
= t
->answer_dnssec_result
;
938 q
->answer_query_flags
= t
->answer_query_flags
| dns_transaction_source_to_query_flags(t
->answer_source
);
939 q
->answer_errno
= t
->answer_errno
;
940 DNS_PACKET_REPLACE(q
->answer_full_packet
, dns_packet_ref(t
->received
));
947 if (state
== DNS_TRANSACTION_SUCCESS
) {
948 SET_FLAG(q
->answer_query_flags
, SD_RESOLVED_AUTHENTICATED
, has_authenticated
&& !has_non_authenticated
);
949 SET_FLAG(q
->answer_query_flags
, SD_RESOLVED_CONFIDENTIAL
, has_confidential
&& !has_non_confidential
);
950 q
->answer_dnssec_result
= FLAGS_SET(q
->answer_query_flags
, SD_RESOLVED_AUTHENTICATED
) ? dnssec_result_authenticated
: dnssec_result_non_authenticated
;
953 q
->answer_protocol
= c
->scope
->protocol
;
954 q
->answer_family
= c
->scope
->family
;
956 dns_search_domain_unref(q
->answer_search_domain
);
957 q
->answer_search_domain
= dns_search_domain_ref(c
->search_domain
);
959 r
= dns_query_synthesize_reply(q
, &state
);
963 dns_query_complete(q
, state
);
967 q
->answer_errno
= -r
;
968 dns_query_complete(q
, DNS_TRANSACTION_ERRNO
);
971 void dns_query_ready(DnsQuery
*q
) {
972 DnsQueryCandidate
*bad
= NULL
;
973 bool pending
= false;
976 assert(DNS_TRANSACTION_IS_LIVE(q
->state
));
978 /* Note that this call might invalidate the query. Callers
979 * should hence not attempt to access the query or transaction
980 * after calling this function, unless the block_ready
981 * counter was explicitly bumped before doing so. */
983 if (q
->block_ready
> 0)
986 LIST_FOREACH(candidates_by_query
, c
, q
->candidates
) {
987 DnsTransactionState state
;
989 state
= dns_query_candidate_state(c
);
992 case DNS_TRANSACTION_SUCCESS
:
993 /* One of the candidates is successful,
994 * let's use it, and copy its data out */
995 dns_query_accept(q
, c
);
998 case DNS_TRANSACTION_NULL
:
999 case DNS_TRANSACTION_PENDING
:
1000 case DNS_TRANSACTION_VALIDATING
:
1001 /* One of the candidates is still going on,
1002 * let's maybe wait for it */
1007 /* Any kind of failure */
1016 dns_query_accept(q
, bad
);
1019 static int dns_query_collect_question(DnsQuery
*q
, DnsQuestion
*question
) {
1020 _cleanup_(dns_question_unrefp
) DnsQuestion
*merged
= NULL
;
1025 if (dns_question_size(question
) == 0)
1028 /* When redirecting, save the first element in the chain, for informational purposes when monitoring */
1029 r
= dns_question_merge(q
->collected_questions
, question
, &merged
);
1033 dns_question_unref(q
->collected_questions
);
1034 q
->collected_questions
= TAKE_PTR(merged
);
1039 static int dns_query_cname_redirect(DnsQuery
*q
, const DnsResourceRecord
*cname
) {
1040 _cleanup_(dns_question_unrefp
) DnsQuestion
*nq_idna
= NULL
, *nq_utf8
= NULL
;
1045 if (q
->n_cname_redirects
>= CNAME_REDIRECTS_MAX
)
1047 q
->n_cname_redirects
++;
1049 r
= dns_question_cname_redirect(q
->question_idna
, cname
, &nq_idna
);
1053 log_debug("Following CNAME/DNAME %s %s %s.",
1054 dns_question_first_name(q
->question_idna
),
1055 special_glyph(SPECIAL_GLYPH_ARROW_RIGHT
),
1056 dns_question_first_name(nq_idna
));
1058 k
= dns_question_is_equal(q
->question_idna
, q
->question_utf8
);
1062 /* Same question? Shortcut new question generation */
1063 nq_utf8
= dns_question_ref(nq_idna
);
1066 k
= dns_question_cname_redirect(q
->question_utf8
, cname
, &nq_utf8
);
1070 log_debug("Following UTF8 CNAME/DNAME %s %s %s.",
1071 dns_question_first_name(q
->question_utf8
),
1072 special_glyph(SPECIAL_GLYPH_ARROW_RIGHT
),
1073 dns_question_first_name(nq_utf8
));
1076 if (r
== 0 && k
== 0) /* No actual cname happened? */
1079 if (q
->answer_protocol
== DNS_PROTOCOL_DNS
)
1080 /* Don't permit CNAME redirects from unicast DNS to LLMNR or MulticastDNS, so that global resources
1081 * cannot invade the local namespace. The opposite way we permit: local names may redirect to global
1083 q
->flags
&= ~(SD_RESOLVED_LLMNR
|SD_RESOLVED_MDNS
); /* mask away the local protocols */
1085 /* Turn off searching for the new name */
1086 q
->flags
|= SD_RESOLVED_NO_SEARCH
;
1088 r
= dns_query_collect_question(q
, q
->question_idna
);
1091 r
= dns_query_collect_question(q
, q
->question_utf8
);
1095 /* Install the redirected question */
1096 dns_question_unref(q
->question_idna
);
1097 q
->question_idna
= TAKE_PTR(nq_idna
);
1099 dns_question_unref(q
->question_utf8
);
1100 q
->question_utf8
= TAKE_PTR(nq_utf8
);
1102 dns_query_unlink_candidates(q
);
1104 /* Note that we do *not* reset the answer here, because the answer we previously got might already
1105 * include everything we need, let's check that first */
1107 q
->state
= DNS_TRANSACTION_NULL
;
1112 int dns_query_process_cname_one(DnsQuery
*q
) {
1113 _cleanup_(dns_resource_record_unrefp
) DnsResourceRecord
*cname
= NULL
;
1114 DnsQuestion
*question
;
1115 DnsResourceRecord
*rr
;
1116 bool full_match
= true;
1122 /* Processes a CNAME redirect if there's one. Returns one of three values:
1124 * CNAME_QUERY_MATCH → direct RR match, caller should just use the RRs in this answer (and not
1125 * bother with any CNAME/DNAME stuff)
1127 * CNAME_QUERY_NOMATCH → no match at all, neither direct nor CNAME/DNAME, caller might decide to
1128 * restart query or take things as NODATA reply.
1130 * CNAME_QUERY_CNAME → no direct RR match, but a CNAME/DNAME match that we now followed for one step.
1132 * The function might also return a failure, in particular -ELOOP if we encountered too many
1133 * CNAMEs/DNAMEs in a chain or if following CNAMEs/DNAMEs was turned off.
1135 * Note that this function doesn't actually restart the query. The caller can decide to do that in
1136 * case of CNAME_QUERY_CNAME, though. */
1138 if (!IN_SET(q
->state
, DNS_TRANSACTION_SUCCESS
, DNS_TRANSACTION_NULL
))
1139 return DNS_QUERY_NOMATCH
;
1141 question
= dns_query_question_for_protocol(q
, q
->answer_protocol
);
1143 /* Small reminder: our question will consist of one or more RR keys that match in name, but not in
1144 * record type. Specifically, when we do an address lookup the question will typically consist of one
1145 * A and one AAAA key lookup for the same domain name. When we get a response from a server we need
1146 * to check if the answer answers all our questions to use it. Note that a response of CNAME/DNAME
1147 * can answer both an A and the AAAA question for us, but an A/AAAA response only the relevant
1150 * Hence we first check of the answers we collected are sufficient to answer all our questions
1151 * directly. If one question wasn't answered we go on, waiting for more replies. However, if there's
1152 * a CNAME/DNAME response we use it, and redirect to it, regardless if it was a response to the A or
1153 * the AAAA query. */
1155 DNS_QUESTION_FOREACH(k
, question
) {
1158 DNS_ANSWER_FOREACH(rr
, q
->answer
) {
1159 r
= dns_resource_key_match_rr(k
, rr
, DNS_SEARCH_DOMAIN_NAME(q
->answer_search_domain
));
1163 match
= true; /* Yay, we found an RR that matches the key we are looking for */
1169 /* Hmm. :-( there's no response for this key. This doesn't match. */
1176 return DNS_QUERY_MATCH
; /* The answer can answer our question in full, no need to follow CNAMEs/DNAMEs */
1178 /* Let's see if there is a CNAME/DNAME to match. This case is simpler: we accept the CNAME/DNAME that
1179 * matches any of our questions. */
1180 DNS_ANSWER_FOREACH(rr
, q
->answer
) {
1181 r
= dns_question_matches_cname_or_dname(question
, rr
, DNS_SEARCH_DOMAIN_NAME(q
->answer_search_domain
));
1184 if (r
> 0 && !cname
)
1185 cname
= dns_resource_record_ref(rr
);
1189 return DNS_QUERY_NOMATCH
; /* No match and no CNAME/DNAME to follow */
1191 if (q
->flags
& SD_RESOLVED_NO_CNAME
)
1194 if (!FLAGS_SET(q
->answer_query_flags
, SD_RESOLVED_AUTHENTICATED
))
1195 q
->previous_redirect_unauthenticated
= true;
1196 if (!FLAGS_SET(q
->answer_query_flags
, SD_RESOLVED_CONFIDENTIAL
))
1197 q
->previous_redirect_non_confidential
= true;
1198 if (!FLAGS_SET(q
->answer_query_flags
, SD_RESOLVED_SYNTHETIC
))
1199 q
->previous_redirect_non_synthetic
= true;
1201 /* OK, let's actually follow the CNAME */
1202 r
= dns_query_cname_redirect(q
, cname
);
1206 return DNS_QUERY_CNAME
; /* Tell caller that we did a single CNAME/DNAME redirection step */
1209 int dns_query_process_cname_many(DnsQuery
*q
) {
1214 /* Follows CNAMEs through the current packet: as long as the current packet can fulfill our
1215 * redirected CNAME queries we keep going, and restart the query once the current packet isn't good
1216 * enough anymore. It's a wrapper around dns_query_process_cname_one() and returns the same values,
1217 * but with extended semantics. Specifically:
1219 * DNS_QUERY_MATCH → as above
1221 * DNS_QUERY_CNAME → we ran into a CNAME/DNAME redirect that we could not answer from the current
1222 * message, and thus restarted the query to resolve it.
1224 * DNS_QUERY_NOMATCH → we reached the end of CNAME/DNAME chain, and there are no direct matches nor a
1225 * CNAME/DNAME match. i.e. this is a NODATA case.
1227 * Note that this function will restart the query for the caller if needed, and that's the case
1228 * DNS_QUERY_CNAME is returned.
1231 r
= dns_query_process_cname_one(q
);
1232 if (r
!= DNS_QUERY_CNAME
)
1233 return r
; /* The first redirect is special: if it doesn't answer the question that's no
1234 * reason to restart the query, we just accept this as a NODATA answer. */
1237 r
= dns_query_process_cname_one(q
);
1238 if (r
< 0 || r
== DNS_QUERY_MATCH
)
1240 if (r
== DNS_QUERY_NOMATCH
) {
1241 /* OK, so we followed one or more CNAME/DNAME RR but the existing packet can't answer
1242 * this. Let's restart the query hence, with the new question. Why the different
1243 * handling than the first chain element? Because if the server answers a direct
1244 * question with an empty answer then this is a NODATA response. But if it responds
1245 * with a CNAME chain that ultimately is incomplete (i.e. a non-empty but truncated
1246 * CNAME chain) then we better follow up ourselves and ask for the rest of the
1247 * chain. This is particular relevant since our cache will store CNAME/DNAME
1248 * redirects that we learnt about for lookups of certain DNS types, but later on we
1249 * can reuse this data even for other DNS types, but in that case need to follow up
1250 * with the final lookup of the chain ourselves with the RR type we ourselves are
1252 r
= dns_query_go(q
);
1256 return DNS_QUERY_CNAME
;
1259 /* So we found a CNAME that the existing packet already answers, again via a CNAME, let's
1260 * continue going then. */
1261 assert(r
== DNS_QUERY_CNAME
);
1265 DnsQuestion
* dns_query_question_for_protocol(DnsQuery
*q
, DnsProtocol protocol
) {
1268 if (q
->question_bypass
)
1269 return q
->question_bypass
->question
;
1273 case DNS_PROTOCOL_DNS
:
1274 return q
->question_idna
;
1276 case DNS_PROTOCOL_MDNS
:
1277 case DNS_PROTOCOL_LLMNR
:
1278 return q
->question_utf8
;
1285 const char *dns_query_string(DnsQuery
*q
) {
1289 /* Returns a somewhat useful human-readable lookup key string for this query */
1291 if (q
->question_bypass
)
1292 return dns_question_first_name(q
->question_bypass
->question
);
1294 if (q
->request_address_string
)
1295 return q
->request_address_string
;
1297 if (q
->request_address_valid
) {
1298 r
= in_addr_to_string(q
->request_family
, &q
->request_address
, &q
->request_address_string
);
1300 return q
->request_address_string
;
1303 name
= dns_question_first_name(q
->question_utf8
);
1307 return dns_question_first_name(q
->question_idna
);
1310 bool dns_query_fully_authenticated(DnsQuery
*q
) {
1313 return FLAGS_SET(q
->answer_query_flags
, SD_RESOLVED_AUTHENTICATED
) && !q
->previous_redirect_unauthenticated
;
1316 bool dns_query_fully_confidential(DnsQuery
*q
) {
1319 return FLAGS_SET(q
->answer_query_flags
, SD_RESOLVED_CONFIDENTIAL
) && !q
->previous_redirect_non_confidential
;
1322 bool dns_query_fully_authoritative(DnsQuery
*q
) {
1325 /* We are authoritative for everything synthetic (except if a previous CNAME/DNAME) wasn't
1326 * synthetic. (Note: SD_RESOLVED_SYNTHETIC is reset on each CNAME/DNAME, hence the explicit check for
1327 * previous synthetic DNAME/CNAME redirections.) */
1328 if ((q
->answer_query_flags
& SD_RESOLVED_SYNTHETIC
) && !q
->previous_redirect_non_synthetic
)
1331 /* We are also authoritative for everything coming only from the trust anchor and the local
1332 * zones. (Note: the SD_RESOLVED_FROM_xyz flags we merge on each redirect, hence no need to
1333 * explicitly check previous redirects here.) */
1334 return (q
->answer_query_flags
& SD_RESOLVED_FROM_MASK
& ~(SD_RESOLVED_FROM_TRUST_ANCHOR
| SD_RESOLVED_FROM_ZONE
)) == 0;