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 "string-util.h"
29 /* How long to wait for the query in total */
30 #define QUERY_TIMEOUT_USEC (30 * USEC_PER_SEC)
33 #define QUERIES_MAX 2048
34 #define AUXILIARY_QUERIES_MAX 64
36 static int dns_query_candidate_new(DnsQueryCandidate
**ret
, DnsQuery
*q
, DnsScope
*s
) {
43 c
= new0(DnsQueryCandidate
, 1);
50 LIST_PREPEND(candidates_by_query
, q
->candidates
, c
);
51 LIST_PREPEND(candidates_by_scope
, s
->query_candidates
, c
);
57 static void dns_query_candidate_stop(DnsQueryCandidate
*c
) {
62 while ((t
= set_steal_first(c
->transactions
))) {
63 set_remove(t
->notify_query_candidates
, c
);
64 dns_transaction_gc(t
);
68 DnsQueryCandidate
* dns_query_candidate_free(DnsQueryCandidate
*c
) {
73 dns_query_candidate_stop(c
);
75 set_free(c
->transactions
);
76 dns_search_domain_unref(c
->search_domain
);
79 LIST_REMOVE(candidates_by_query
, c
->query
->candidates
, c
);
82 LIST_REMOVE(candidates_by_scope
, c
->scope
->query_candidates
, c
);
89 static int dns_query_candidate_next_search_domain(DnsQueryCandidate
*c
) {
90 DnsSearchDomain
*next
= NULL
;
94 if (c
->search_domain
&& c
->search_domain
->linked
) {
95 next
= c
->search_domain
->domains_next
;
97 if (!next
) /* We hit the end of the list */
101 next
= dns_scope_get_search_domains(c
->scope
);
103 if (!next
) /* OK, there's nothing. */
107 dns_search_domain_unref(c
->search_domain
);
108 c
->search_domain
= dns_search_domain_ref(next
);
113 static int dns_query_candidate_add_transaction(DnsQueryCandidate
*c
, DnsResourceKey
*key
) {
120 t
= dns_scope_find_transaction(c
->scope
, key
, true);
122 r
= dns_transaction_new(&t
, c
->scope
, key
);
126 if (set_contains(c
->transactions
, t
))
130 r
= set_ensure_allocated(&c
->transactions
, NULL
);
134 r
= set_ensure_allocated(&t
->notify_query_candidates
, NULL
);
138 r
= set_put(t
->notify_query_candidates
, c
);
142 r
= set_put(c
->transactions
, t
);
144 (void) set_remove(t
->notify_query_candidates
, c
);
151 dns_transaction_gc(t
);
155 static int dns_query_candidate_go(DnsQueryCandidate
*c
) {
162 /* Start the transactions that are not started yet */
163 SET_FOREACH(t
, c
->transactions
, i
) {
164 if (t
->state
!= DNS_TRANSACTION_NULL
)
167 r
= dns_transaction_go(t
);
175 static DnsTransactionState
dns_query_candidate_state(DnsQueryCandidate
*c
) {
176 DnsTransactionState state
= DNS_TRANSACTION_NO_SERVERS
;
182 if (c
->error_code
!= 0)
183 return DNS_TRANSACTION_RESOURCES
;
185 SET_FOREACH(t
, c
->transactions
, i
) {
189 case DNS_TRANSACTION_NULL
:
190 /* If there's a NULL transaction pending, then
191 * this means not all transactions where
192 * started yet, and we were called from within
193 * the stackframe that is supposed to start
194 * remaining transactions. In this case,
195 * simply claim the candidate is pending. */
197 case DNS_TRANSACTION_PENDING
:
198 case DNS_TRANSACTION_VALIDATING
:
199 /* If there's one transaction currently in
200 * VALIDATING state, then this means there's
201 * also one in PENDING state, hence we can
202 * return PENDING immediately. */
203 return DNS_TRANSACTION_PENDING
;
205 case DNS_TRANSACTION_SUCCESS
:
210 if (state
!= DNS_TRANSACTION_SUCCESS
)
220 static int dns_query_candidate_setup_transactions(DnsQueryCandidate
*c
) {
221 DnsQuestion
*question
;
227 dns_query_candidate_stop(c
);
229 question
= dns_query_question_for_protocol(c
->query
, c
->scope
->protocol
);
231 /* Create one transaction per question key */
232 DNS_QUESTION_FOREACH(key
, question
) {
233 _cleanup_(dns_resource_key_unrefp
) DnsResourceKey
*new_key
= NULL
;
235 if (c
->search_domain
) {
236 r
= dns_resource_key_new_append_suffix(&new_key
, key
, c
->search_domain
->name
);
241 r
= dns_query_candidate_add_transaction(c
, new_key
?: key
);
251 dns_query_candidate_stop(c
);
255 void dns_query_candidate_notify(DnsQueryCandidate
*c
) {
256 DnsTransactionState state
;
261 state
= dns_query_candidate_state(c
);
263 if (DNS_TRANSACTION_IS_LIVE(state
))
266 if (state
!= DNS_TRANSACTION_SUCCESS
&& c
->search_domain
) {
268 r
= dns_query_candidate_next_search_domain(c
);
273 /* OK, there's another search domain to try, let's do so. */
275 r
= dns_query_candidate_setup_transactions(c
);
280 /* New transactions where queued. Start them and wait */
282 r
= dns_query_candidate_go(c
);
292 dns_query_ready(c
->query
);
296 log_warning_errno(r
, "Failed to follow search domains: %m");
298 dns_query_ready(c
->query
);
301 static void dns_query_stop(DnsQuery
*q
) {
302 DnsQueryCandidate
*c
;
306 q
->timeout_event_source
= sd_event_source_unref(q
->timeout_event_source
);
308 LIST_FOREACH(candidates_by_query
, c
, q
->candidates
)
309 dns_query_candidate_stop(c
);
312 DnsQuery
*dns_query_free(DnsQuery
*q
) {
316 while (q
->auxiliary_queries
)
317 dns_query_free(q
->auxiliary_queries
);
319 if (q
->auxiliary_for
) {
320 assert(q
->auxiliary_for
->n_auxiliary_queries
> 0);
321 q
->auxiliary_for
->n_auxiliary_queries
--;
322 LIST_REMOVE(auxiliary_queries
, q
->auxiliary_for
->auxiliary_queries
, q
);
325 while (q
->candidates
)
326 dns_query_candidate_free(q
->candidates
);
328 dns_question_unref(q
->question_idna
);
329 dns_question_unref(q
->question_utf8
);
330 dns_answer_unref(q
->answer
);
331 dns_search_domain_unref(q
->answer_search_domain
);
333 sd_bus_message_unref(q
->request
);
334 sd_bus_track_unref(q
->bus_track
);
336 free(q
->request_address_string
);
339 LIST_REMOVE(queries
, q
->manager
->dns_queries
, q
);
340 q
->manager
->n_dns_queries
--;
351 DnsQuestion
*question_utf8
,
352 DnsQuestion
*question_idna
,
353 int ifindex
, uint64_t flags
) {
355 _cleanup_(dns_query_freep
) DnsQuery
*q
= NULL
;
362 if (dns_question_size(question_utf8
) > 0) {
363 r
= dns_question_is_valid_for_query(question_utf8
);
372 /* If the IDNA and UTF8 questions are the same, merge their references */
373 r
= dns_question_is_equal(question_idna
, question_utf8
);
377 question_idna
= question_utf8
;
379 if (dns_question_size(question_idna
) > 0) {
380 r
= dns_question_is_valid_for_query(question_idna
);
390 if (!good
) /* don't allow empty queries */
393 if (m
->n_dns_queries
>= QUERIES_MAX
)
396 q
= new0(DnsQuery
, 1);
400 q
->question_utf8
= dns_question_ref(question_utf8
);
401 q
->question_idna
= dns_question_ref(question_idna
);
402 q
->ifindex
= ifindex
;
404 q
->answer_family
= AF_UNSPEC
;
405 q
->answer_protocol
= _DNS_PROTOCOL_INVALID
;
407 /* First dump UTF8 question */
408 DNS_QUESTION_FOREACH(key
, question_utf8
) {
409 _cleanup_free_
char *p
= NULL
;
411 r
= dns_resource_key_to_string(key
, &p
);
415 log_debug("Looking up RR for %s.", strstrip(p
));
418 /* And then dump the IDNA question, but only what hasn't been dumped already through the UTF8 question. */
419 DNS_QUESTION_FOREACH(key
, question_idna
) {
420 _cleanup_free_
char *p
= NULL
;
422 r
= dns_question_contains(question_utf8
, key
);
428 r
= dns_resource_key_to_string(key
, &p
);
432 log_debug("Looking up IDNA RR for %s.", strstrip(p
));
435 LIST_PREPEND(queries
, m
->dns_queries
, q
);
446 int dns_query_make_auxiliary(DnsQuery
*q
, DnsQuery
*auxiliary_for
) {
448 assert(auxiliary_for
);
450 /* Ensure that that the query is not auxiliary yet, and
451 * nothing else is auxiliary to it either */
452 assert(!q
->auxiliary_for
);
453 assert(!q
->auxiliary_queries
);
455 /* Ensure that the unit we shall be made auxiliary for isn't
456 * auxiliary itself */
457 assert(!auxiliary_for
->auxiliary_for
);
459 if (auxiliary_for
->n_auxiliary_queries
>= AUXILIARY_QUERIES_MAX
)
462 LIST_PREPEND(auxiliary_queries
, auxiliary_for
->auxiliary_queries
, q
);
463 q
->auxiliary_for
= auxiliary_for
;
465 auxiliary_for
->n_auxiliary_queries
++;
469 static void dns_query_complete(DnsQuery
*q
, DnsTransactionState state
) {
471 assert(!DNS_TRANSACTION_IS_LIVE(state
));
472 assert(DNS_TRANSACTION_IS_LIVE(q
->state
));
474 /* Note that this call might invalidate the query. Callers
475 * should hence not attempt to access the query or transaction
476 * after calling this function. */
485 static int on_query_timeout(sd_event_source
*s
, usec_t usec
, void *userdata
) {
486 DnsQuery
*q
= userdata
;
491 dns_query_complete(q
, DNS_TRANSACTION_TIMEOUT
);
495 static int dns_query_add_candidate(DnsQuery
*q
, DnsScope
*s
) {
496 DnsQueryCandidate
*c
;
502 r
= dns_query_candidate_new(&c
, q
, s
);
506 /* If this a single-label domain on DNS, we might append a suitable search domain first. */
507 if ((q
->flags
& SD_RESOLVED_NO_SEARCH
) == 0) {
508 r
= dns_scope_name_needs_search_domain(s
, dns_question_first_name(q
->question_idna
));
512 /* OK, we need a search domain now. Let's find one for this scope */
514 r
= dns_query_candidate_next_search_domain(c
);
515 if (r
<= 0) /* if there's no search domain, then we won't add any transaction. */
520 r
= dns_query_candidate_setup_transactions(c
);
527 dns_query_candidate_free(c
);
531 static int SYNTHESIZE_IFINDEX(int ifindex
) {
533 /* When the caller asked for resolving on a specific
534 * interface, we synthesize the answer for that
535 * interface. However, if nothing specific was claimed and we
536 * only return localhost RRs, we synthesize the answer for
542 return LOOPBACK_IFINDEX
;
545 static int SYNTHESIZE_FAMILY(uint64_t flags
) {
547 /* Picks an address family depending on set flags. This is
548 * purely for synthesized answers, where the family we return
549 * for the reply should match what was requested in the
550 * question, even though we are synthesizing the answer
553 if (!(flags
& SD_RESOLVED_DNS
)) {
554 if (flags
& SD_RESOLVED_LLMNR_IPV4
)
556 if (flags
& SD_RESOLVED_LLMNR_IPV6
)
563 static DnsProtocol
SYNTHESIZE_PROTOCOL(uint64_t flags
) {
565 /* Similar as SYNTHESIZE_FAMILY() but does this for the
566 * protocol. If resolving via DNS was requested, we claim it
567 * was DNS. Similar, if nothing specific was
568 * requested. However, if only resolving via LLMNR was
569 * requested we return that. */
571 if (flags
& SD_RESOLVED_DNS
)
572 return DNS_PROTOCOL_DNS
;
573 if (flags
& SD_RESOLVED_LLMNR
)
574 return DNS_PROTOCOL_LLMNR
;
576 return DNS_PROTOCOL_DNS
;
579 static int dns_type_to_af(uint16_t t
) {
596 static int synthesize_localhost_rr(DnsQuery
*q
, const DnsResourceKey
*key
, DnsAnswer
**answer
) {
603 r
= dns_answer_reserve(answer
, 2);
607 if (IN_SET(key
->type
, DNS_TYPE_A
, DNS_TYPE_ANY
)) {
608 _cleanup_(dns_resource_record_unrefp
) DnsResourceRecord
*rr
= NULL
;
610 rr
= dns_resource_record_new_full(DNS_CLASS_IN
, DNS_TYPE_A
, DNS_RESOURCE_KEY_NAME(key
));
614 rr
->a
.in_addr
.s_addr
= htobe32(INADDR_LOOPBACK
);
616 r
= dns_answer_add(*answer
, rr
, SYNTHESIZE_IFINDEX(q
->ifindex
), DNS_ANSWER_AUTHENTICATED
);
621 if (IN_SET(key
->type
, DNS_TYPE_AAAA
, DNS_TYPE_ANY
)) {
622 _cleanup_(dns_resource_record_unrefp
) DnsResourceRecord
*rr
= NULL
;
624 rr
= dns_resource_record_new_full(DNS_CLASS_IN
, DNS_TYPE_AAAA
, DNS_RESOURCE_KEY_NAME(key
));
628 rr
->aaaa
.in6_addr
= in6addr_loopback
;
630 r
= dns_answer_add(*answer
, rr
, SYNTHESIZE_IFINDEX(q
->ifindex
), DNS_ANSWER_AUTHENTICATED
);
638 static int answer_add_ptr(DnsAnswer
**answer
, const char *from
, const char *to
, int ifindex
, DnsAnswerFlags flags
) {
639 _cleanup_(dns_resource_record_unrefp
) DnsResourceRecord
*rr
= NULL
;
641 rr
= dns_resource_record_new_full(DNS_CLASS_IN
, DNS_TYPE_PTR
, from
);
645 rr
->ptr
.name
= strdup(to
);
649 return dns_answer_add(*answer
, rr
, ifindex
, flags
);
652 static int synthesize_localhost_ptr(DnsQuery
*q
, const DnsResourceKey
*key
, DnsAnswer
**answer
) {
659 if (IN_SET(key
->type
, DNS_TYPE_PTR
, DNS_TYPE_ANY
)) {
660 r
= dns_answer_reserve(answer
, 1);
664 r
= answer_add_ptr(answer
, DNS_RESOURCE_KEY_NAME(key
), "localhost", SYNTHESIZE_IFINDEX(q
->ifindex
), DNS_ANSWER_AUTHENTICATED
);
672 static int answer_add_addresses_rr(
675 struct local_address
*addresses
,
676 unsigned n_addresses
) {
684 r
= dns_answer_reserve(answer
, n_addresses
);
688 for (j
= 0; j
< n_addresses
; j
++) {
689 _cleanup_(dns_resource_record_unrefp
) DnsResourceRecord
*rr
= NULL
;
691 r
= dns_resource_record_new_address(&rr
, addresses
[j
].family
, &addresses
[j
].address
, name
);
695 r
= dns_answer_add(*answer
, rr
, addresses
[j
].ifindex
, DNS_ANSWER_AUTHENTICATED
);
703 static int answer_add_addresses_ptr(
706 struct local_address
*addresses
,
707 unsigned n_addresses
,
708 int af
, const union in_addr_union
*match
) {
716 for (j
= 0; j
< n_addresses
; j
++) {
717 _cleanup_(dns_resource_record_unrefp
) DnsResourceRecord
*rr
= NULL
;
719 if (af
!= AF_UNSPEC
) {
721 if (addresses
[j
].family
!= af
)
724 if (match
&& !in_addr_equal(af
, match
, &addresses
[j
].address
))
728 r
= dns_answer_reserve(answer
, 1);
732 r
= dns_resource_record_new_reverse(&rr
, addresses
[j
].family
, &addresses
[j
].address
, name
);
736 r
= dns_answer_add(*answer
, rr
, addresses
[j
].ifindex
, DNS_ANSWER_AUTHENTICATED
);
744 static int synthesize_system_hostname_rr(DnsQuery
*q
, const DnsResourceKey
*key
, DnsAnswer
**answer
) {
745 _cleanup_free_
struct local_address
*addresses
= NULL
;
752 af
= dns_type_to_af(key
->type
);
754 n
= local_addresses(q
->manager
->rtnl
, q
->ifindex
, af
, &addresses
);
759 struct local_address buffer
[2];
761 /* If we have no local addresses then use ::1
762 * and 127.0.0.2 as local ones. */
764 if (af
== AF_INET
|| af
== AF_UNSPEC
)
765 buffer
[n
++] = (struct local_address
) {
767 .ifindex
= SYNTHESIZE_IFINDEX(q
->ifindex
),
768 .address
.in
.s_addr
= htobe32(0x7F000002),
771 if (af
== AF_INET6
|| af
== AF_UNSPEC
)
772 buffer
[n
++] = (struct local_address
) {
774 .ifindex
= SYNTHESIZE_IFINDEX(q
->ifindex
),
775 .address
.in6
= in6addr_loopback
,
778 return answer_add_addresses_rr(answer
, DNS_RESOURCE_KEY_NAME(key
), buffer
, n
);
782 return answer_add_addresses_rr(answer
, DNS_RESOURCE_KEY_NAME(key
), addresses
, n
);
785 static int synthesize_system_hostname_ptr(DnsQuery
*q
, int af
, const union in_addr_union
*address
, DnsAnswer
**answer
) {
786 _cleanup_free_
struct local_address
*addresses
= NULL
;
793 if (af
== AF_INET
&& address
->in
.s_addr
== htobe32(0x7F000002)) {
795 /* Always map the IPv4 address 127.0.0.2 to the local
796 * hostname, in addition to "localhost": */
798 r
= dns_answer_reserve(answer
, 3);
802 r
= answer_add_ptr(answer
, "2.0.0.127.in-addr.arpa", q
->manager
->llmnr_hostname
, SYNTHESIZE_IFINDEX(q
->ifindex
), DNS_ANSWER_AUTHENTICATED
);
806 r
= answer_add_ptr(answer
, "2.0.0.127.in-addr.arpa", q
->manager
->mdns_hostname
, SYNTHESIZE_IFINDEX(q
->ifindex
), DNS_ANSWER_AUTHENTICATED
);
810 r
= answer_add_ptr(answer
, "2.0.0.127.in-addr.arpa", "localhost", SYNTHESIZE_IFINDEX(q
->ifindex
), DNS_ANSWER_AUTHENTICATED
);
817 n
= local_addresses(q
->manager
->rtnl
, q
->ifindex
, af
, &addresses
);
821 r
= answer_add_addresses_ptr(answer
, q
->manager
->llmnr_hostname
, addresses
, n
, af
, address
);
825 return answer_add_addresses_ptr(answer
, q
->manager
->mdns_hostname
, addresses
, n
, af
, address
);
828 static int synthesize_gateway_rr(DnsQuery
*q
, const DnsResourceKey
*key
, DnsAnswer
**answer
) {
829 _cleanup_free_
struct local_address
*addresses
= NULL
;
836 af
= dns_type_to_af(key
->type
);
838 n
= local_gateways(q
->manager
->rtnl
, q
->ifindex
, af
, &addresses
);
843 return answer_add_addresses_rr(answer
, DNS_RESOURCE_KEY_NAME(key
), addresses
, n
);
846 static int synthesize_gateway_ptr(DnsQuery
*q
, int af
, const union in_addr_union
*address
, DnsAnswer
**answer
) {
847 _cleanup_free_
struct local_address
*addresses
= NULL
;
854 n
= local_gateways(q
->manager
->rtnl
, q
->ifindex
, af
, &addresses
);
858 return answer_add_addresses_ptr(answer
, "gateway", addresses
, n
, af
, address
);
861 static int dns_query_synthesize_reply(DnsQuery
*q
, DnsTransactionState
*state
) {
862 _cleanup_(dns_answer_unrefp
) DnsAnswer
*answer
= NULL
;
869 /* Tries to synthesize localhost RR replies where appropriate */
872 DNS_TRANSACTION_RCODE_FAILURE
,
873 DNS_TRANSACTION_NO_SERVERS
,
874 DNS_TRANSACTION_TIMEOUT
,
875 DNS_TRANSACTION_ATTEMPTS_MAX_REACHED
))
878 DNS_QUESTION_FOREACH(key
, q
->question_utf8
) {
879 union in_addr_union address
;
883 if (key
->class != DNS_CLASS_IN
&&
884 key
->class != DNS_CLASS_ANY
)
887 name
= DNS_RESOURCE_KEY_NAME(key
);
889 if (is_localhost(name
)) {
891 r
= synthesize_localhost_rr(q
, key
, &answer
);
893 return log_error_errno(r
, "Failed to synthesize localhost RRs: %m");
895 } else if (manager_is_own_hostname(q
->manager
, name
)) {
897 r
= synthesize_system_hostname_rr(q
, key
, &answer
);
899 return log_error_errno(r
, "Failed to synthesize system hostname RRs: %m");
901 } else if (is_gateway_hostname(name
)) {
903 r
= synthesize_gateway_rr(q
, key
, &answer
);
905 return log_error_errno(r
, "Failed to synthesize gateway RRs: %m");
907 } else if ((dns_name_endswith(name
, "127.in-addr.arpa") > 0 && dns_name_equal(name
, "2.0.0.127.in-addr.arpa") == 0) ||
908 dns_name_equal(name
, "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa") > 0) {
910 r
= synthesize_localhost_ptr(q
, key
, &answer
);
912 return log_error_errno(r
, "Failed to synthesize localhost PTR RRs: %m");
914 } else if (dns_name_address(name
, &af
, &address
) > 0) {
916 r
= synthesize_system_hostname_ptr(q
, af
, &address
, &answer
);
918 return log_error_errno(r
, "Failed to synthesize system hostname PTR RR: %m");
920 r
= synthesize_gateway_ptr(q
, af
, &address
, &answer
);
922 return log_error_errno(r
, "Failed to synthesize gateway hostname PTR RR: %m");
929 dns_answer_unref(q
->answer
);
933 q
->answer_rcode
= DNS_RCODE_SUCCESS
;
934 q
->answer_protocol
= SYNTHESIZE_PROTOCOL(q
->flags
);
935 q
->answer_family
= SYNTHESIZE_FAMILY(q
->flags
);
937 *state
= DNS_TRANSACTION_SUCCESS
;
942 int dns_query_go(DnsQuery
*q
) {
943 DnsScopeMatch found
= DNS_SCOPE_NO
;
944 DnsScope
*s
, *first
= NULL
;
945 DnsQueryCandidate
*c
;
950 if (q
->state
!= DNS_TRANSACTION_NULL
)
953 LIST_FOREACH(scopes
, s
, q
->manager
->dns_scopes
) {
957 name
= dns_question_first_name(dns_query_question_for_protocol(q
, s
->protocol
));
961 match
= dns_scope_good_domain(s
, q
->ifindex
, q
->flags
, name
);
965 if (match
== DNS_SCOPE_NO
)
970 if (match
== DNS_SCOPE_YES
) {
974 assert(match
== DNS_SCOPE_MAYBE
);
981 if (found
== DNS_SCOPE_NO
) {
982 DnsTransactionState state
= DNS_TRANSACTION_NO_SERVERS
;
984 dns_query_synthesize_reply(q
, &state
);
985 dns_query_complete(q
, state
);
989 r
= dns_query_add_candidate(q
, first
);
993 LIST_FOREACH(scopes
, s
, first
->scopes_next
) {
997 name
= dns_question_first_name(dns_query_question_for_protocol(q
, s
->protocol
));
1001 match
= dns_scope_good_domain(s
, q
->ifindex
, q
->flags
, name
);
1008 r
= dns_query_add_candidate(q
, s
);
1013 q
->answer
= dns_answer_unref(q
->answer
);
1014 q
->answer_rcode
= 0;
1015 q
->answer_family
= AF_UNSPEC
;
1016 q
->answer_protocol
= _DNS_PROTOCOL_INVALID
;
1018 r
= sd_event_add_time(
1020 &q
->timeout_event_source
,
1021 clock_boottime_or_monotonic(),
1022 now(clock_boottime_or_monotonic()) + QUERY_TIMEOUT_USEC
, 0,
1023 on_query_timeout
, q
);
1027 (void) sd_event_source_set_description(q
->timeout_event_source
, "query-timeout");
1029 q
->state
= DNS_TRANSACTION_PENDING
;
1032 /* Start the transactions */
1033 LIST_FOREACH(candidates_by_query
, c
, q
->candidates
) {
1034 r
= dns_query_candidate_go(c
);
1051 static void dns_query_accept(DnsQuery
*q
, DnsQueryCandidate
*c
) {
1052 DnsTransactionState state
= DNS_TRANSACTION_NO_SERVERS
;
1053 bool has_authenticated
= false, has_non_authenticated
= false;
1054 DnssecResult dnssec_result_authenticated
= _DNSSEC_RESULT_INVALID
, dnssec_result_non_authenticated
= _DNSSEC_RESULT_INVALID
;
1062 dns_query_synthesize_reply(q
, &state
);
1063 dns_query_complete(q
, state
);
1067 SET_FOREACH(t
, c
->transactions
, i
) {
1071 case DNS_TRANSACTION_SUCCESS
: {
1072 /* We found a successfuly reply, merge it into the answer */
1073 r
= dns_answer_extend(&q
->answer
, t
->answer
);
1075 dns_query_complete(q
, DNS_TRANSACTION_RESOURCES
);
1079 q
->answer_rcode
= t
->answer_rcode
;
1081 if (t
->answer_authenticated
) {
1082 has_authenticated
= true;
1083 dnssec_result_authenticated
= t
->answer_dnssec_result
;
1085 has_non_authenticated
= true;
1086 dnssec_result_non_authenticated
= t
->answer_dnssec_result
;
1089 state
= DNS_TRANSACTION_SUCCESS
;
1093 case DNS_TRANSACTION_NULL
:
1094 case DNS_TRANSACTION_PENDING
:
1095 case DNS_TRANSACTION_VALIDATING
:
1096 case DNS_TRANSACTION_ABORTED
:
1097 /* Ignore transactions that didn't complete */
1101 /* Any kind of failure? Store the data away,
1102 * if there's nothing stored yet. */
1104 if (state
== DNS_TRANSACTION_SUCCESS
)
1107 q
->answer
= dns_answer_unref(q
->answer
);
1108 q
->answer_rcode
= t
->answer_rcode
;
1109 q
->answer_dnssec_result
= t
->answer_dnssec_result
;
1116 if (state
== DNS_TRANSACTION_SUCCESS
) {
1117 q
->answer_authenticated
= has_authenticated
&& !has_non_authenticated
;
1118 q
->answer_dnssec_result
= q
->answer_authenticated
? dnssec_result_authenticated
: dnssec_result_non_authenticated
;
1121 q
->answer_protocol
= c
->scope
->protocol
;
1122 q
->answer_family
= c
->scope
->family
;
1124 dns_search_domain_unref(q
->answer_search_domain
);
1125 q
->answer_search_domain
= dns_search_domain_ref(c
->search_domain
);
1127 dns_query_synthesize_reply(q
, &state
);
1128 dns_query_complete(q
, state
);
1131 void dns_query_ready(DnsQuery
*q
) {
1133 DnsQueryCandidate
*bad
= NULL
, *c
;
1134 bool pending
= false;
1137 assert(DNS_TRANSACTION_IS_LIVE(q
->state
));
1139 /* Note that this call might invalidate the query. Callers
1140 * should hence not attempt to access the query or transaction
1141 * after calling this function, unless the block_ready
1142 * counter was explicitly bumped before doing so. */
1144 if (q
->block_ready
> 0)
1147 LIST_FOREACH(candidates_by_query
, c
, q
->candidates
) {
1148 DnsTransactionState state
;
1150 state
= dns_query_candidate_state(c
);
1153 case DNS_TRANSACTION_SUCCESS
:
1154 /* One of the candidates is successful,
1155 * let's use it, and copy its data out */
1156 dns_query_accept(q
, c
);
1159 case DNS_TRANSACTION_NULL
:
1160 case DNS_TRANSACTION_PENDING
:
1161 case DNS_TRANSACTION_VALIDATING
:
1162 /* One of the candidates is still going on,
1163 * let's maybe wait for it */
1168 /* Any kind of failure */
1177 dns_query_accept(q
, bad
);
1180 static int dns_query_cname_redirect(DnsQuery
*q
, const DnsResourceRecord
*cname
) {
1181 _cleanup_(dns_question_unrefp
) DnsQuestion
*nq_idna
= NULL
, *nq_utf8
= NULL
;
1186 q
->n_cname_redirects
++;
1187 if (q
->n_cname_redirects
> CNAME_MAX
)
1190 r
= dns_question_cname_redirect(q
->question_idna
, cname
, &nq_idna
);
1194 log_debug("Following CNAME/DNAME %s → %s", dns_question_first_name(q
->question_idna
), dns_question_first_name(nq_idna
));
1196 k
= dns_question_is_equal(q
->question_idna
, q
->question_utf8
);
1200 /* Same question? Shortcut new question generation */
1201 nq_utf8
= dns_question_ref(nq_idna
);
1204 k
= dns_question_cname_redirect(q
->question_utf8
, cname
, &nq_utf8
);
1208 log_debug("Following UTF8 CNAME/DNAME %s → %s", dns_question_first_name(q
->question_utf8
), dns_question_first_name(nq_utf8
));
1211 if (r
== 0 && k
== 0) /* No actual cname happened? */
1214 dns_question_unref(q
->question_idna
);
1215 q
->question_idna
= nq_idna
;
1218 dns_question_unref(q
->question_utf8
);
1219 q
->question_utf8
= nq_utf8
;
1223 q
->state
= DNS_TRANSACTION_NULL
;
1228 int dns_query_process_cname(DnsQuery
*q
) {
1229 _cleanup_(dns_resource_record_unrefp
) DnsResourceRecord
*cname
= NULL
;
1230 DnsQuestion
*question
;
1231 DnsResourceRecord
*rr
;
1236 if (!IN_SET(q
->state
, DNS_TRANSACTION_SUCCESS
, DNS_TRANSACTION_NULL
))
1237 return DNS_QUERY_NOMATCH
;
1239 question
= dns_query_question_for_protocol(q
, q
->answer_protocol
);
1241 DNS_ANSWER_FOREACH(rr
, q
->answer
) {
1242 r
= dns_question_matches_rr(question
, rr
, DNS_SEARCH_DOMAIN_NAME(q
->answer_search_domain
));
1246 return DNS_QUERY_MATCH
; /* The answer matches directly, no need to follow cnames */
1248 r
= dns_question_matches_cname(question
, rr
, DNS_SEARCH_DOMAIN_NAME(q
->answer_search_domain
));
1251 if (r
> 0 && !cname
)
1252 cname
= dns_resource_record_ref(rr
);
1256 return DNS_QUERY_NOMATCH
; /* No match and no cname to follow */
1258 if (q
->flags
& SD_RESOLVED_NO_CNAME
)
1261 /* OK, let's actually follow the CNAME */
1262 r
= dns_query_cname_redirect(q
, cname
);
1266 /* Let's see if the answer can already answer the new
1267 * redirected question */
1268 r
= dns_query_process_cname(q
);
1269 if (r
!= DNS_QUERY_NOMATCH
)
1272 /* OK, it cannot, let's begin with the new query */
1273 r
= dns_query_go(q
);
1277 return DNS_QUERY_RESTARTED
; /* We restarted the query for a new cname */
1280 static int on_bus_track(sd_bus_track
*t
, void *userdata
) {
1281 DnsQuery
*q
= userdata
;
1286 log_debug("Client of active query vanished, aborting query.");
1287 dns_query_complete(q
, DNS_TRANSACTION_ABORTED
);
1291 int dns_query_bus_track(DnsQuery
*q
, sd_bus_message
*m
) {
1297 if (!q
->bus_track
) {
1298 r
= sd_bus_track_new(sd_bus_message_get_bus(m
), &q
->bus_track
, on_bus_track
, q
);
1303 r
= sd_bus_track_add_sender(q
->bus_track
, m
);
1310 DnsQuestion
* dns_query_question_for_protocol(DnsQuery
*q
, DnsProtocol protocol
) {
1315 case DNS_PROTOCOL_DNS
:
1316 return q
->question_idna
;
1318 case DNS_PROTOCOL_MDNS
:
1319 case DNS_PROTOCOL_LLMNR
:
1320 return q
->question_utf8
;
1327 const char *dns_query_string(DnsQuery
*q
) {
1331 /* Returns a somewhat useful human-readable lookup key string for this query */
1333 if (q
->request_address_string
)
1334 return q
->request_address_string
;
1336 if (q
->request_address_valid
) {
1337 r
= in_addr_to_string(q
->request_family
, &q
->request_address
, &q
->request_address_string
);
1339 return q
->request_address_string
;
1342 name
= dns_question_first_name(q
->question_utf8
);
1346 return dns_question_first_name(q
->question_idna
);