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 static void dns_query_free_candidates(DnsQuery
*q
) {
315 while (q
->candidates
)
316 dns_query_candidate_free(q
->candidates
);
319 static void dns_query_reset_answer(DnsQuery
*q
) {
322 q
->answer
= dns_answer_unref(q
->answer
);
324 q
->answer_dnssec_result
= _DNSSEC_RESULT_INVALID
;
325 q
->answer_authenticated
= false;
326 q
->answer_protocol
= _DNS_PROTOCOL_INVALID
;
327 q
->answer_family
= AF_UNSPEC
;
328 q
->answer_search_domain
= dns_search_domain_unref(q
->answer_search_domain
);
331 DnsQuery
*dns_query_free(DnsQuery
*q
) {
335 while (q
->auxiliary_queries
)
336 dns_query_free(q
->auxiliary_queries
);
338 if (q
->auxiliary_for
) {
339 assert(q
->auxiliary_for
->n_auxiliary_queries
> 0);
340 q
->auxiliary_for
->n_auxiliary_queries
--;
341 LIST_REMOVE(auxiliary_queries
, q
->auxiliary_for
->auxiliary_queries
, q
);
344 dns_query_free_candidates(q
);
346 dns_question_unref(q
->question_idna
);
347 dns_question_unref(q
->question_utf8
);
349 dns_query_reset_answer(q
);
351 sd_bus_message_unref(q
->request
);
352 sd_bus_track_unref(q
->bus_track
);
354 free(q
->request_address_string
);
357 LIST_REMOVE(queries
, q
->manager
->dns_queries
, q
);
358 q
->manager
->n_dns_queries
--;
369 DnsQuestion
*question_utf8
,
370 DnsQuestion
*question_idna
,
371 int ifindex
, uint64_t flags
) {
373 _cleanup_(dns_query_freep
) DnsQuery
*q
= NULL
;
380 if (dns_question_size(question_utf8
) > 0) {
381 r
= dns_question_is_valid_for_query(question_utf8
);
390 /* If the IDNA and UTF8 questions are the same, merge their references */
391 r
= dns_question_is_equal(question_idna
, question_utf8
);
395 question_idna
= question_utf8
;
397 if (dns_question_size(question_idna
) > 0) {
398 r
= dns_question_is_valid_for_query(question_idna
);
408 if (!good
) /* don't allow empty queries */
411 if (m
->n_dns_queries
>= QUERIES_MAX
)
414 q
= new0(DnsQuery
, 1);
418 q
->question_utf8
= dns_question_ref(question_utf8
);
419 q
->question_idna
= dns_question_ref(question_idna
);
420 q
->ifindex
= ifindex
;
422 q
->answer_dnssec_result
= _DNSSEC_RESULT_INVALID
;
423 q
->answer_protocol
= _DNS_PROTOCOL_INVALID
;
424 q
->answer_family
= AF_UNSPEC
;
426 /* First dump UTF8 question */
427 DNS_QUESTION_FOREACH(key
, question_utf8
) {
428 _cleanup_free_
char *p
= NULL
;
430 r
= dns_resource_key_to_string(key
, &p
);
434 log_debug("Looking up RR for %s.", strstrip(p
));
437 /* And then dump the IDNA question, but only what hasn't been dumped already through the UTF8 question. */
438 DNS_QUESTION_FOREACH(key
, question_idna
) {
439 _cleanup_free_
char *p
= NULL
;
441 r
= dns_question_contains(question_utf8
, key
);
447 r
= dns_resource_key_to_string(key
, &p
);
451 log_debug("Looking up IDNA RR for %s.", strstrip(p
));
454 LIST_PREPEND(queries
, m
->dns_queries
, q
);
465 int dns_query_make_auxiliary(DnsQuery
*q
, DnsQuery
*auxiliary_for
) {
467 assert(auxiliary_for
);
469 /* Ensure that that the query is not auxiliary yet, and
470 * nothing else is auxiliary to it either */
471 assert(!q
->auxiliary_for
);
472 assert(!q
->auxiliary_queries
);
474 /* Ensure that the unit we shall be made auxiliary for isn't
475 * auxiliary itself */
476 assert(!auxiliary_for
->auxiliary_for
);
478 if (auxiliary_for
->n_auxiliary_queries
>= AUXILIARY_QUERIES_MAX
)
481 LIST_PREPEND(auxiliary_queries
, auxiliary_for
->auxiliary_queries
, q
);
482 q
->auxiliary_for
= auxiliary_for
;
484 auxiliary_for
->n_auxiliary_queries
++;
488 static void dns_query_complete(DnsQuery
*q
, DnsTransactionState state
) {
490 assert(!DNS_TRANSACTION_IS_LIVE(state
));
491 assert(DNS_TRANSACTION_IS_LIVE(q
->state
));
493 /* Note that this call might invalidate the query. Callers
494 * should hence not attempt to access the query or transaction
495 * after calling this function. */
504 static int on_query_timeout(sd_event_source
*s
, usec_t usec
, void *userdata
) {
505 DnsQuery
*q
= userdata
;
510 dns_query_complete(q
, DNS_TRANSACTION_TIMEOUT
);
514 static int dns_query_add_candidate(DnsQuery
*q
, DnsScope
*s
) {
515 DnsQueryCandidate
*c
;
521 r
= dns_query_candidate_new(&c
, q
, s
);
525 /* If this a single-label domain on DNS, we might append a suitable search domain first. */
526 if ((q
->flags
& SD_RESOLVED_NO_SEARCH
) == 0) {
527 r
= dns_scope_name_needs_search_domain(s
, dns_question_first_name(q
->question_idna
));
531 /* OK, we need a search domain now. Let's find one for this scope */
533 r
= dns_query_candidate_next_search_domain(c
);
534 if (r
<= 0) /* if there's no search domain, then we won't add any transaction. */
539 r
= dns_query_candidate_setup_transactions(c
);
546 dns_query_candidate_free(c
);
550 static int SYNTHESIZE_IFINDEX(int ifindex
) {
552 /* When the caller asked for resolving on a specific
553 * interface, we synthesize the answer for that
554 * interface. However, if nothing specific was claimed and we
555 * only return localhost RRs, we synthesize the answer for
561 return LOOPBACK_IFINDEX
;
564 static int SYNTHESIZE_FAMILY(uint64_t flags
) {
566 /* Picks an address family depending on set flags. This is
567 * purely for synthesized answers, where the family we return
568 * for the reply should match what was requested in the
569 * question, even though we are synthesizing the answer
572 if (!(flags
& SD_RESOLVED_DNS
)) {
573 if (flags
& SD_RESOLVED_LLMNR_IPV4
)
575 if (flags
& SD_RESOLVED_LLMNR_IPV6
)
582 static DnsProtocol
SYNTHESIZE_PROTOCOL(uint64_t flags
) {
584 /* Similar as SYNTHESIZE_FAMILY() but does this for the
585 * protocol. If resolving via DNS was requested, we claim it
586 * was DNS. Similar, if nothing specific was
587 * requested. However, if only resolving via LLMNR was
588 * requested we return that. */
590 if (flags
& SD_RESOLVED_DNS
)
591 return DNS_PROTOCOL_DNS
;
592 if (flags
& SD_RESOLVED_LLMNR
)
593 return DNS_PROTOCOL_LLMNR
;
595 return DNS_PROTOCOL_DNS
;
598 static int dns_type_to_af(uint16_t t
) {
615 static int synthesize_localhost_rr(DnsQuery
*q
, const DnsResourceKey
*key
, DnsAnswer
**answer
) {
622 r
= dns_answer_reserve(answer
, 2);
626 if (IN_SET(key
->type
, DNS_TYPE_A
, DNS_TYPE_ANY
)) {
627 _cleanup_(dns_resource_record_unrefp
) DnsResourceRecord
*rr
= NULL
;
629 rr
= dns_resource_record_new_full(DNS_CLASS_IN
, DNS_TYPE_A
, DNS_RESOURCE_KEY_NAME(key
));
633 rr
->a
.in_addr
.s_addr
= htobe32(INADDR_LOOPBACK
);
635 r
= dns_answer_add(*answer
, rr
, SYNTHESIZE_IFINDEX(q
->ifindex
), DNS_ANSWER_AUTHENTICATED
);
640 if (IN_SET(key
->type
, DNS_TYPE_AAAA
, DNS_TYPE_ANY
)) {
641 _cleanup_(dns_resource_record_unrefp
) DnsResourceRecord
*rr
= NULL
;
643 rr
= dns_resource_record_new_full(DNS_CLASS_IN
, DNS_TYPE_AAAA
, DNS_RESOURCE_KEY_NAME(key
));
647 rr
->aaaa
.in6_addr
= in6addr_loopback
;
649 r
= dns_answer_add(*answer
, rr
, SYNTHESIZE_IFINDEX(q
->ifindex
), DNS_ANSWER_AUTHENTICATED
);
657 static int answer_add_ptr(DnsAnswer
**answer
, const char *from
, const char *to
, int ifindex
, DnsAnswerFlags flags
) {
658 _cleanup_(dns_resource_record_unrefp
) DnsResourceRecord
*rr
= NULL
;
660 rr
= dns_resource_record_new_full(DNS_CLASS_IN
, DNS_TYPE_PTR
, from
);
664 rr
->ptr
.name
= strdup(to
);
668 return dns_answer_add(*answer
, rr
, ifindex
, flags
);
671 static int synthesize_localhost_ptr(DnsQuery
*q
, const DnsResourceKey
*key
, DnsAnswer
**answer
) {
678 if (IN_SET(key
->type
, DNS_TYPE_PTR
, DNS_TYPE_ANY
)) {
679 r
= dns_answer_reserve(answer
, 1);
683 r
= answer_add_ptr(answer
, DNS_RESOURCE_KEY_NAME(key
), "localhost", SYNTHESIZE_IFINDEX(q
->ifindex
), DNS_ANSWER_AUTHENTICATED
);
691 static int answer_add_addresses_rr(
694 struct local_address
*addresses
,
695 unsigned n_addresses
) {
703 r
= dns_answer_reserve(answer
, n_addresses
);
707 for (j
= 0; j
< n_addresses
; j
++) {
708 _cleanup_(dns_resource_record_unrefp
) DnsResourceRecord
*rr
= NULL
;
710 r
= dns_resource_record_new_address(&rr
, addresses
[j
].family
, &addresses
[j
].address
, name
);
714 r
= dns_answer_add(*answer
, rr
, addresses
[j
].ifindex
, DNS_ANSWER_AUTHENTICATED
);
722 static int answer_add_addresses_ptr(
725 struct local_address
*addresses
,
726 unsigned n_addresses
,
727 int af
, const union in_addr_union
*match
) {
735 for (j
= 0; j
< n_addresses
; j
++) {
736 _cleanup_(dns_resource_record_unrefp
) DnsResourceRecord
*rr
= NULL
;
738 if (af
!= AF_UNSPEC
) {
740 if (addresses
[j
].family
!= af
)
743 if (match
&& !in_addr_equal(af
, match
, &addresses
[j
].address
))
747 r
= dns_answer_reserve(answer
, 1);
751 r
= dns_resource_record_new_reverse(&rr
, addresses
[j
].family
, &addresses
[j
].address
, name
);
755 r
= dns_answer_add(*answer
, rr
, addresses
[j
].ifindex
, DNS_ANSWER_AUTHENTICATED
);
763 static int synthesize_system_hostname_rr(DnsQuery
*q
, const DnsResourceKey
*key
, DnsAnswer
**answer
) {
764 _cleanup_free_
struct local_address
*addresses
= NULL
;
771 af
= dns_type_to_af(key
->type
);
773 n
= local_addresses(q
->manager
->rtnl
, q
->ifindex
, af
, &addresses
);
778 struct local_address buffer
[2];
780 /* If we have no local addresses then use ::1
781 * and 127.0.0.2 as local ones. */
783 if (af
== AF_INET
|| af
== AF_UNSPEC
)
784 buffer
[n
++] = (struct local_address
) {
786 .ifindex
= SYNTHESIZE_IFINDEX(q
->ifindex
),
787 .address
.in
.s_addr
= htobe32(0x7F000002),
790 if (af
== AF_INET6
|| af
== AF_UNSPEC
)
791 buffer
[n
++] = (struct local_address
) {
793 .ifindex
= SYNTHESIZE_IFINDEX(q
->ifindex
),
794 .address
.in6
= in6addr_loopback
,
797 return answer_add_addresses_rr(answer
, DNS_RESOURCE_KEY_NAME(key
), buffer
, n
);
801 return answer_add_addresses_rr(answer
, DNS_RESOURCE_KEY_NAME(key
), addresses
, n
);
804 static int synthesize_system_hostname_ptr(DnsQuery
*q
, int af
, const union in_addr_union
*address
, DnsAnswer
**answer
) {
805 _cleanup_free_
struct local_address
*addresses
= NULL
;
812 if (af
== AF_INET
&& address
->in
.s_addr
== htobe32(0x7F000002)) {
814 /* Always map the IPv4 address 127.0.0.2 to the local
815 * hostname, in addition to "localhost": */
817 r
= dns_answer_reserve(answer
, 3);
821 r
= answer_add_ptr(answer
, "2.0.0.127.in-addr.arpa", q
->manager
->llmnr_hostname
, SYNTHESIZE_IFINDEX(q
->ifindex
), DNS_ANSWER_AUTHENTICATED
);
825 r
= answer_add_ptr(answer
, "2.0.0.127.in-addr.arpa", q
->manager
->mdns_hostname
, SYNTHESIZE_IFINDEX(q
->ifindex
), DNS_ANSWER_AUTHENTICATED
);
829 r
= answer_add_ptr(answer
, "2.0.0.127.in-addr.arpa", "localhost", SYNTHESIZE_IFINDEX(q
->ifindex
), DNS_ANSWER_AUTHENTICATED
);
836 n
= local_addresses(q
->manager
->rtnl
, q
->ifindex
, af
, &addresses
);
840 r
= answer_add_addresses_ptr(answer
, q
->manager
->llmnr_hostname
, addresses
, n
, af
, address
);
844 return answer_add_addresses_ptr(answer
, q
->manager
->mdns_hostname
, addresses
, n
, af
, address
);
847 static int synthesize_gateway_rr(DnsQuery
*q
, const DnsResourceKey
*key
, DnsAnswer
**answer
) {
848 _cleanup_free_
struct local_address
*addresses
= NULL
;
855 af
= dns_type_to_af(key
->type
);
857 n
= local_gateways(q
->manager
->rtnl
, q
->ifindex
, af
, &addresses
);
862 return answer_add_addresses_rr(answer
, DNS_RESOURCE_KEY_NAME(key
), addresses
, n
);
865 static int synthesize_gateway_ptr(DnsQuery
*q
, int af
, const union in_addr_union
*address
, DnsAnswer
**answer
) {
866 _cleanup_free_
struct local_address
*addresses
= NULL
;
873 n
= local_gateways(q
->manager
->rtnl
, q
->ifindex
, af
, &addresses
);
877 return answer_add_addresses_ptr(answer
, "gateway", addresses
, n
, af
, address
);
880 static int dns_query_synthesize_reply(DnsQuery
*q
, DnsTransactionState
*state
) {
881 _cleanup_(dns_answer_unrefp
) DnsAnswer
*answer
= NULL
;
888 /* Tries to synthesize localhost RR replies where appropriate */
891 DNS_TRANSACTION_RCODE_FAILURE
,
892 DNS_TRANSACTION_NO_SERVERS
,
893 DNS_TRANSACTION_TIMEOUT
,
894 DNS_TRANSACTION_ATTEMPTS_MAX_REACHED
))
897 DNS_QUESTION_FOREACH(key
, q
->question_utf8
) {
898 union in_addr_union address
;
902 if (key
->class != DNS_CLASS_IN
&&
903 key
->class != DNS_CLASS_ANY
)
906 name
= DNS_RESOURCE_KEY_NAME(key
);
908 if (is_localhost(name
)) {
910 r
= synthesize_localhost_rr(q
, key
, &answer
);
912 return log_error_errno(r
, "Failed to synthesize localhost RRs: %m");
914 } else if (manager_is_own_hostname(q
->manager
, name
)) {
916 r
= synthesize_system_hostname_rr(q
, key
, &answer
);
918 return log_error_errno(r
, "Failed to synthesize system hostname RRs: %m");
920 } else if (is_gateway_hostname(name
)) {
922 r
= synthesize_gateway_rr(q
, key
, &answer
);
924 return log_error_errno(r
, "Failed to synthesize gateway RRs: %m");
926 } else if ((dns_name_endswith(name
, "127.in-addr.arpa") > 0 && dns_name_equal(name
, "2.0.0.127.in-addr.arpa") == 0) ||
927 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) {
929 r
= synthesize_localhost_ptr(q
, key
, &answer
);
931 return log_error_errno(r
, "Failed to synthesize localhost PTR RRs: %m");
933 } else if (dns_name_address(name
, &af
, &address
) > 0) {
935 r
= synthesize_system_hostname_ptr(q
, af
, &address
, &answer
);
937 return log_error_errno(r
, "Failed to synthesize system hostname PTR RR: %m");
939 r
= synthesize_gateway_ptr(q
, af
, &address
, &answer
);
941 return log_error_errno(r
, "Failed to synthesize gateway hostname PTR RR: %m");
948 dns_answer_unref(q
->answer
);
952 q
->answer_rcode
= DNS_RCODE_SUCCESS
;
953 q
->answer_protocol
= SYNTHESIZE_PROTOCOL(q
->flags
);
954 q
->answer_family
= SYNTHESIZE_FAMILY(q
->flags
);
956 *state
= DNS_TRANSACTION_SUCCESS
;
961 int dns_query_go(DnsQuery
*q
) {
962 DnsScopeMatch found
= DNS_SCOPE_NO
;
963 DnsScope
*s
, *first
= NULL
;
964 DnsQueryCandidate
*c
;
969 if (q
->state
!= DNS_TRANSACTION_NULL
)
972 LIST_FOREACH(scopes
, s
, q
->manager
->dns_scopes
) {
976 name
= dns_question_first_name(dns_query_question_for_protocol(q
, s
->protocol
));
980 match
= dns_scope_good_domain(s
, q
->ifindex
, q
->flags
, name
);
984 if (match
== DNS_SCOPE_NO
)
989 if (match
== DNS_SCOPE_YES
) {
993 assert(match
== DNS_SCOPE_MAYBE
);
1000 if (found
== DNS_SCOPE_NO
) {
1001 DnsTransactionState state
= DNS_TRANSACTION_NO_SERVERS
;
1003 dns_query_synthesize_reply(q
, &state
);
1004 dns_query_complete(q
, state
);
1008 r
= dns_query_add_candidate(q
, first
);
1012 LIST_FOREACH(scopes
, s
, first
->scopes_next
) {
1013 DnsScopeMatch match
;
1016 name
= dns_question_first_name(dns_query_question_for_protocol(q
, s
->protocol
));
1020 match
= dns_scope_good_domain(s
, q
->ifindex
, q
->flags
, name
);
1027 r
= dns_query_add_candidate(q
, s
);
1032 q
->answer
= dns_answer_unref(q
->answer
);
1033 q
->answer_rcode
= 0;
1034 q
->answer_family
= AF_UNSPEC
;
1035 q
->answer_protocol
= _DNS_PROTOCOL_INVALID
;
1037 r
= sd_event_add_time(
1039 &q
->timeout_event_source
,
1040 clock_boottime_or_monotonic(),
1041 now(clock_boottime_or_monotonic()) + QUERY_TIMEOUT_USEC
, 0,
1042 on_query_timeout
, q
);
1046 (void) sd_event_source_set_description(q
->timeout_event_source
, "query-timeout");
1048 q
->state
= DNS_TRANSACTION_PENDING
;
1051 /* Start the transactions */
1052 LIST_FOREACH(candidates_by_query
, c
, q
->candidates
) {
1053 r
= dns_query_candidate_go(c
);
1070 static void dns_query_accept(DnsQuery
*q
, DnsQueryCandidate
*c
) {
1071 DnsTransactionState state
= DNS_TRANSACTION_NO_SERVERS
;
1072 bool has_authenticated
= false, has_non_authenticated
= false;
1073 DnssecResult dnssec_result_authenticated
= _DNSSEC_RESULT_INVALID
, dnssec_result_non_authenticated
= _DNSSEC_RESULT_INVALID
;
1081 dns_query_synthesize_reply(q
, &state
);
1082 dns_query_complete(q
, state
);
1086 SET_FOREACH(t
, c
->transactions
, i
) {
1090 case DNS_TRANSACTION_SUCCESS
: {
1091 /* We found a successfuly reply, merge it into the answer */
1092 r
= dns_answer_extend(&q
->answer
, t
->answer
);
1094 dns_query_complete(q
, DNS_TRANSACTION_RESOURCES
);
1098 q
->answer_rcode
= t
->answer_rcode
;
1100 if (t
->answer_authenticated
) {
1101 has_authenticated
= true;
1102 dnssec_result_authenticated
= t
->answer_dnssec_result
;
1104 has_non_authenticated
= true;
1105 dnssec_result_non_authenticated
= t
->answer_dnssec_result
;
1108 state
= DNS_TRANSACTION_SUCCESS
;
1112 case DNS_TRANSACTION_NULL
:
1113 case DNS_TRANSACTION_PENDING
:
1114 case DNS_TRANSACTION_VALIDATING
:
1115 case DNS_TRANSACTION_ABORTED
:
1116 /* Ignore transactions that didn't complete */
1120 /* Any kind of failure? Store the data away,
1121 * if there's nothing stored yet. */
1123 if (state
== DNS_TRANSACTION_SUCCESS
)
1126 q
->answer
= dns_answer_unref(q
->answer
);
1127 q
->answer_rcode
= t
->answer_rcode
;
1128 q
->answer_dnssec_result
= t
->answer_dnssec_result
;
1135 if (state
== DNS_TRANSACTION_SUCCESS
) {
1136 q
->answer_authenticated
= has_authenticated
&& !has_non_authenticated
;
1137 q
->answer_dnssec_result
= q
->answer_authenticated
? dnssec_result_authenticated
: dnssec_result_non_authenticated
;
1140 q
->answer_protocol
= c
->scope
->protocol
;
1141 q
->answer_family
= c
->scope
->family
;
1143 dns_search_domain_unref(q
->answer_search_domain
);
1144 q
->answer_search_domain
= dns_search_domain_ref(c
->search_domain
);
1146 dns_query_synthesize_reply(q
, &state
);
1147 dns_query_complete(q
, state
);
1150 void dns_query_ready(DnsQuery
*q
) {
1152 DnsQueryCandidate
*bad
= NULL
, *c
;
1153 bool pending
= false;
1156 assert(DNS_TRANSACTION_IS_LIVE(q
->state
));
1158 /* Note that this call might invalidate the query. Callers
1159 * should hence not attempt to access the query or transaction
1160 * after calling this function, unless the block_ready
1161 * counter was explicitly bumped before doing so. */
1163 if (q
->block_ready
> 0)
1166 LIST_FOREACH(candidates_by_query
, c
, q
->candidates
) {
1167 DnsTransactionState state
;
1169 state
= dns_query_candidate_state(c
);
1172 case DNS_TRANSACTION_SUCCESS
:
1173 /* One of the candidates is successful,
1174 * let's use it, and copy its data out */
1175 dns_query_accept(q
, c
);
1178 case DNS_TRANSACTION_NULL
:
1179 case DNS_TRANSACTION_PENDING
:
1180 case DNS_TRANSACTION_VALIDATING
:
1181 /* One of the candidates is still going on,
1182 * let's maybe wait for it */
1187 /* Any kind of failure */
1196 dns_query_accept(q
, bad
);
1199 static int dns_query_cname_redirect(DnsQuery
*q
, const DnsResourceRecord
*cname
) {
1200 _cleanup_(dns_question_unrefp
) DnsQuestion
*nq_idna
= NULL
, *nq_utf8
= NULL
;
1205 q
->n_cname_redirects
++;
1206 if (q
->n_cname_redirects
> CNAME_MAX
)
1209 r
= dns_question_cname_redirect(q
->question_idna
, cname
, &nq_idna
);
1213 log_debug("Following CNAME/DNAME %s → %s.", dns_question_first_name(q
->question_idna
), dns_question_first_name(nq_idna
));
1215 k
= dns_question_is_equal(q
->question_idna
, q
->question_utf8
);
1219 /* Same question? Shortcut new question generation */
1220 nq_utf8
= dns_question_ref(nq_idna
);
1223 k
= dns_question_cname_redirect(q
->question_utf8
, cname
, &nq_utf8
);
1227 log_debug("Following UTF8 CNAME/DNAME %s → %s.", dns_question_first_name(q
->question_utf8
), dns_question_first_name(nq_utf8
));
1230 if (r
== 0 && k
== 0) /* No actual cname happened? */
1233 dns_question_unref(q
->question_idna
);
1234 q
->question_idna
= nq_idna
;
1237 dns_question_unref(q
->question_utf8
);
1238 q
->question_utf8
= nq_utf8
;
1241 dns_query_free_candidates(q
);
1242 dns_query_reset_answer(q
);
1243 q
->state
= DNS_TRANSACTION_NULL
;
1245 /* Turn off searching for the new name */
1246 q
->flags
|= SD_RESOLVED_NO_SEARCH
;
1251 int dns_query_process_cname(DnsQuery
*q
) {
1252 _cleanup_(dns_resource_record_unrefp
) DnsResourceRecord
*cname
= NULL
;
1253 DnsQuestion
*question
;
1254 DnsResourceRecord
*rr
;
1259 if (!IN_SET(q
->state
, DNS_TRANSACTION_SUCCESS
, DNS_TRANSACTION_NULL
))
1260 return DNS_QUERY_NOMATCH
;
1262 question
= dns_query_question_for_protocol(q
, q
->answer_protocol
);
1264 DNS_ANSWER_FOREACH(rr
, q
->answer
) {
1265 r
= dns_question_matches_rr(question
, rr
, DNS_SEARCH_DOMAIN_NAME(q
->answer_search_domain
));
1269 return DNS_QUERY_MATCH
; /* The answer matches directly, no need to follow cnames */
1271 r
= dns_question_matches_cname_or_dname(question
, rr
, DNS_SEARCH_DOMAIN_NAME(q
->answer_search_domain
));
1274 if (r
> 0 && !cname
)
1275 cname
= dns_resource_record_ref(rr
);
1279 return DNS_QUERY_NOMATCH
; /* No match and no cname to follow */
1281 if (q
->flags
& SD_RESOLVED_NO_CNAME
)
1284 /* OK, let's actually follow the CNAME */
1285 r
= dns_query_cname_redirect(q
, cname
);
1289 /* Let's see if the answer can already answer the new
1290 * redirected question */
1291 r
= dns_query_process_cname(q
);
1292 if (r
!= DNS_QUERY_NOMATCH
)
1295 /* OK, it cannot, let's begin with the new query */
1296 r
= dns_query_go(q
);
1300 return DNS_QUERY_RESTARTED
; /* We restarted the query for a new cname */
1303 static int on_bus_track(sd_bus_track
*t
, void *userdata
) {
1304 DnsQuery
*q
= userdata
;
1309 log_debug("Client of active query vanished, aborting query.");
1310 dns_query_complete(q
, DNS_TRANSACTION_ABORTED
);
1314 int dns_query_bus_track(DnsQuery
*q
, sd_bus_message
*m
) {
1320 if (!q
->bus_track
) {
1321 r
= sd_bus_track_new(sd_bus_message_get_bus(m
), &q
->bus_track
, on_bus_track
, q
);
1326 r
= sd_bus_track_add_sender(q
->bus_track
, m
);
1333 DnsQuestion
* dns_query_question_for_protocol(DnsQuery
*q
, DnsProtocol protocol
) {
1338 case DNS_PROTOCOL_DNS
:
1339 return q
->question_idna
;
1341 case DNS_PROTOCOL_MDNS
:
1342 case DNS_PROTOCOL_LLMNR
:
1343 return q
->question_utf8
;
1350 const char *dns_query_string(DnsQuery
*q
) {
1354 /* Returns a somewhat useful human-readable lookup key string for this query */
1356 if (q
->request_address_string
)
1357 return q
->request_address_string
;
1359 if (q
->request_address_valid
) {
1360 r
= in_addr_to_string(q
->request_family
, &q
->request_address
, &q
->request_address_string
);
1362 return q
->request_address_string
;
1365 name
= dns_question_first_name(q
->question_utf8
);
1369 return dns_question_first_name(q
->question_idna
);