1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 This file is part of systemd.
5 Copyright 2014 Lennart Poettering
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
21 #include "alloc-util.h"
22 #include "bus-common-errors.h"
24 #include "dns-domain.h"
25 #include "resolved-bus.h"
26 #include "resolved-def.h"
27 #include "resolved-dns-synthesize.h"
28 #include "resolved-link-bus.h"
30 static int reply_query_state(DnsQuery
*q
) {
34 case DNS_TRANSACTION_NO_SERVERS
:
35 return sd_bus_reply_method_errorf(q
->request
, BUS_ERROR_NO_NAME_SERVERS
, "No appropriate name servers or networks for name found");
37 case DNS_TRANSACTION_TIMEOUT
:
38 return sd_bus_reply_method_errorf(q
->request
, SD_BUS_ERROR_TIMEOUT
, "Query timed out");
40 case DNS_TRANSACTION_ATTEMPTS_MAX_REACHED
:
41 return sd_bus_reply_method_errorf(q
->request
, SD_BUS_ERROR_TIMEOUT
, "All attempts to contact name servers or networks failed");
43 case DNS_TRANSACTION_INVALID_REPLY
:
44 return sd_bus_reply_method_errorf(q
->request
, BUS_ERROR_INVALID_REPLY
, "Received invalid reply");
46 case DNS_TRANSACTION_ERRNO
:
47 return sd_bus_reply_method_errnof(q
->request
, q
->answer_errno
, "Lookup failed due to system error: %m");
49 case DNS_TRANSACTION_ABORTED
:
50 return sd_bus_reply_method_errorf(q
->request
, BUS_ERROR_ABORTED
, "Query aborted");
52 case DNS_TRANSACTION_DNSSEC_FAILED
:
53 return sd_bus_reply_method_errorf(q
->request
, BUS_ERROR_DNSSEC_FAILED
, "DNSSEC validation failed: %s",
54 dnssec_result_to_string(q
->answer_dnssec_result
));
56 case DNS_TRANSACTION_NO_TRUST_ANCHOR
:
57 return sd_bus_reply_method_errorf(q
->request
, BUS_ERROR_NO_TRUST_ANCHOR
, "No suitable trust anchor known");
59 case DNS_TRANSACTION_RR_TYPE_UNSUPPORTED
:
60 return sd_bus_reply_method_errorf(q
->request
, BUS_ERROR_RR_TYPE_UNSUPPORTED
, "Server does not support requested resource record type");
62 case DNS_TRANSACTION_NETWORK_DOWN
:
63 return sd_bus_reply_method_errorf(q
->request
, BUS_ERROR_NETWORK_DOWN
, "Network is down");
65 case DNS_TRANSACTION_NOT_FOUND
:
66 /* We return this as NXDOMAIN. This is only generated when a host doesn't implement LLMNR/TCP, and we
67 * thus quickly know that we cannot resolve an in-addr.arpa or ip6.arpa address. */
68 return sd_bus_reply_method_errorf(q
->request
, _BUS_ERROR_DNS
"NXDOMAIN", "'%s' not found", dns_query_string(q
));
70 case DNS_TRANSACTION_RCODE_FAILURE
: {
71 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
73 if (q
->answer_rcode
== DNS_RCODE_NXDOMAIN
)
74 sd_bus_error_setf(&error
, _BUS_ERROR_DNS
"NXDOMAIN", "'%s' not found", dns_query_string(q
));
77 char p
[DECIMAL_STR_MAX(q
->answer_rcode
)];
79 rc
= dns_rcode_to_string(q
->answer_rcode
);
81 sprintf(p
, "%i", q
->answer_rcode
);
85 n
= strjoina(_BUS_ERROR_DNS
, rc
);
86 sd_bus_error_setf(&error
, n
, "Could not resolve '%s', server or network returned error %s", dns_query_string(q
), rc
);
89 return sd_bus_reply_method_error(q
->request
, &error
);
92 case DNS_TRANSACTION_NULL
:
93 case DNS_TRANSACTION_PENDING
:
94 case DNS_TRANSACTION_VALIDATING
:
95 case DNS_TRANSACTION_SUCCESS
:
97 assert_not_reached("Impossible state");
101 static int append_address(sd_bus_message
*reply
, DnsResourceRecord
*rr
, int ifindex
) {
107 r
= sd_bus_message_open_container(reply
, 'r', "iiay");
111 r
= sd_bus_message_append(reply
, "i", ifindex
);
115 if (rr
->key
->type
== DNS_TYPE_A
) {
116 r
= sd_bus_message_append(reply
, "i", AF_INET
);
120 r
= sd_bus_message_append_array(reply
, 'y', &rr
->a
.in_addr
, sizeof(struct in_addr
));
122 } else if (rr
->key
->type
== DNS_TYPE_AAAA
) {
123 r
= sd_bus_message_append(reply
, "i", AF_INET6
);
127 r
= sd_bus_message_append_array(reply
, 'y', &rr
->aaaa
.in6_addr
, sizeof(struct in6_addr
));
129 return -EAFNOSUPPORT
;
134 r
= sd_bus_message_close_container(reply
);
141 static void bus_method_resolve_hostname_complete(DnsQuery
*q
) {
142 _cleanup_(dns_resource_record_unrefp
) DnsResourceRecord
*canonical
= NULL
;
143 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
144 _cleanup_free_
char *normalized
= NULL
;
145 DnsResourceRecord
*rr
;
151 if (q
->state
!= DNS_TRANSACTION_SUCCESS
) {
152 r
= reply_query_state(q
);
156 r
= dns_query_process_cname(q
);
158 r
= sd_bus_reply_method_errorf(q
->request
, BUS_ERROR_CNAME_LOOP
, "CNAME loop detected, or CNAME resolving disabled on '%s'", dns_query_string(q
));
163 if (r
== DNS_QUERY_RESTARTED
) /* This was a cname, and the query was restarted. */
166 r
= sd_bus_message_new_method_return(q
->request
, &reply
);
170 r
= sd_bus_message_open_container(reply
, 'a', "(iiay)");
174 DNS_ANSWER_FOREACH_IFINDEX(rr
, ifindex
, q
->answer
) {
175 DnsQuestion
*question
;
177 question
= dns_query_question_for_protocol(q
, q
->answer_protocol
);
179 r
= dns_question_matches_rr(question
, rr
, DNS_SEARCH_DOMAIN_NAME(q
->answer_search_domain
));
185 r
= append_address(reply
, rr
, ifindex
);
190 canonical
= dns_resource_record_ref(rr
);
196 r
= sd_bus_reply_method_errorf(q
->request
, BUS_ERROR_NO_SUCH_RR
, "'%s' does not have any RR of the requested type", dns_query_string(q
));
200 r
= sd_bus_message_close_container(reply
);
204 /* The key names are not necessarily normalized, make sure that they are when we return them to our bus
206 r
= dns_name_normalize(dns_resource_key_name(canonical
->key
), &normalized
);
210 /* Return the precise spelling and uppercasing and CNAME target reported by the server */
212 r
= sd_bus_message_append(
215 SD_RESOLVED_FLAGS_MAKE(q
->answer_protocol
, q
->answer_family
, dns_query_fully_authenticated(q
)));
219 r
= sd_bus_send(q
->manager
->bus
, reply
, NULL
);
223 log_error_errno(r
, "Failed to send hostname reply: %m");
224 sd_bus_reply_method_errno(q
->request
, r
, NULL
);
230 static int check_ifindex_flags(int ifindex
, uint64_t *flags
, uint64_t ok
, sd_bus_error
*error
) {
234 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid interface index");
236 if (*flags
& ~(SD_RESOLVED_PROTOCOLS_ALL
|SD_RESOLVED_NO_CNAME
|ok
))
237 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid flags parameter");
239 if ((*flags
& SD_RESOLVED_PROTOCOLS_ALL
) == 0) /* If no protocol is enabled, enable all */
240 *flags
|= SD_RESOLVED_PROTOCOLS_ALL
;
245 static int parse_as_address(sd_bus_message
*m
, int ifindex
, const char *hostname
, int family
, uint64_t flags
) {
246 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
247 _cleanup_free_
char *canonical
= NULL
;
248 union in_addr_union parsed
;
249 int r
, ff
, parsed_ifindex
= 0;
251 /* Check if the hostname is actually already an IP address formatted as string. In that case just parse it,
252 * let's not attempt to look it up. */
254 r
= in_addr_ifindex_from_string_auto(hostname
, &ff
, &parsed
, &parsed_ifindex
);
255 if (r
< 0) /* not an address */
258 if (family
!= AF_UNSPEC
&& ff
!= family
)
259 return sd_bus_reply_method_errorf(m
, BUS_ERROR_NO_SUCH_RR
, "The specified address is not of the requested family.");
260 if (ifindex
> 0 && parsed_ifindex
> 0 && parsed_ifindex
!= ifindex
)
261 return sd_bus_reply_method_errorf(m
, BUS_ERROR_NO_SUCH_RR
, "The specified address interface index does not match requested interface.");
263 if (parsed_ifindex
> 0)
264 ifindex
= parsed_ifindex
;
266 r
= sd_bus_message_new_method_return(m
, &reply
);
270 r
= sd_bus_message_open_container(reply
, 'a', "(iiay)");
274 r
= sd_bus_message_open_container(reply
, 'r', "iiay");
278 r
= sd_bus_message_append(reply
, "ii", ifindex
, ff
);
282 r
= sd_bus_message_append_array(reply
, 'y', &parsed
, FAMILY_ADDRESS_SIZE(ff
));
286 r
= sd_bus_message_close_container(reply
);
290 r
= sd_bus_message_close_container(reply
);
294 /* When an IP address is specified we just return it as canonical name, in order to avoid a DNS
295 * look-up. However, we reformat it to make sure it's in a truly canonical form (i.e. on IPv6 the inner
296 * omissions are always done the same way). */
297 r
= in_addr_ifindex_to_string(ff
, &parsed
, ifindex
, &canonical
);
301 r
= sd_bus_message_append(reply
, "st", canonical
,
302 SD_RESOLVED_FLAGS_MAKE(dns_synthesize_protocol(flags
), ff
, true));
306 return sd_bus_send(sd_bus_message_get_bus(m
), reply
, NULL
);
309 static int bus_method_resolve_hostname(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
310 _cleanup_(dns_question_unrefp
) DnsQuestion
*question_idna
= NULL
, *question_utf8
= NULL
;
311 Manager
*m
= userdata
;
312 const char *hostname
;
321 assert_cc(sizeof(int) == sizeof(int32_t));
323 r
= sd_bus_message_read(message
, "isit", &ifindex
, &hostname
, &family
, &flags
);
327 if (!IN_SET(family
, AF_INET
, AF_INET6
, AF_UNSPEC
))
328 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Unknown address family %i", family
);
330 r
= check_ifindex_flags(ifindex
, &flags
, SD_RESOLVED_NO_SEARCH
, error
);
334 r
= parse_as_address(message
, ifindex
, hostname
, family
, flags
);
338 r
= dns_name_is_valid(hostname
);
342 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid hostname '%s'", hostname
);
344 r
= dns_question_new_address(&question_utf8
, family
, hostname
, false);
348 r
= dns_question_new_address(&question_idna
, family
, hostname
, true);
349 if (r
< 0 && r
!= -EALREADY
)
352 r
= dns_query_new(m
, &q
, question_utf8
, question_idna
?: question_utf8
, ifindex
, flags
);
356 q
->request
= sd_bus_message_ref(message
);
357 q
->request_family
= family
;
358 q
->complete
= bus_method_resolve_hostname_complete
;
359 q
->suppress_unroutable_family
= family
== AF_UNSPEC
;
361 r
= dns_query_bus_track(q
, message
);
376 static void bus_method_resolve_address_complete(DnsQuery
*q
) {
377 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
378 DnsQuestion
*question
;
379 DnsResourceRecord
*rr
;
385 if (q
->state
!= DNS_TRANSACTION_SUCCESS
) {
386 r
= reply_query_state(q
);
390 r
= dns_query_process_cname(q
);
392 r
= sd_bus_reply_method_errorf(q
->request
, BUS_ERROR_CNAME_LOOP
, "CNAME loop detected, or CNAME resolving disabled on '%s'", dns_query_string(q
));
397 if (r
== DNS_QUERY_RESTARTED
) /* This was a cname, and the query was restarted. */
400 r
= sd_bus_message_new_method_return(q
->request
, &reply
);
404 r
= sd_bus_message_open_container(reply
, 'a', "(is)");
408 question
= dns_query_question_for_protocol(q
, q
->answer_protocol
);
410 DNS_ANSWER_FOREACH_IFINDEX(rr
, ifindex
, q
->answer
) {
411 _cleanup_free_
char *normalized
= NULL
;
413 r
= dns_question_matches_rr(question
, rr
, NULL
);
419 r
= dns_name_normalize(rr
->ptr
.name
, &normalized
);
423 r
= sd_bus_message_append(reply
, "(is)", ifindex
, normalized
);
431 _cleanup_free_
char *ip
= NULL
;
433 (void) in_addr_to_string(q
->request_family
, &q
->request_address
, &ip
);
434 r
= sd_bus_reply_method_errorf(q
->request
, BUS_ERROR_NO_SUCH_RR
,
435 "Address '%s' does not have any RR of requested type", strnull(ip
));
439 r
= sd_bus_message_close_container(reply
);
443 r
= sd_bus_message_append(reply
, "t", SD_RESOLVED_FLAGS_MAKE(q
->answer_protocol
, q
->answer_family
, dns_query_fully_authenticated(q
)));
447 r
= sd_bus_send(q
->manager
->bus
, reply
, NULL
);
451 log_error_errno(r
, "Failed to send address reply: %m");
452 sd_bus_reply_method_errno(q
->request
, r
, NULL
);
458 static int bus_method_resolve_address(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
459 _cleanup_(dns_question_unrefp
) DnsQuestion
*question
= NULL
;
460 Manager
*m
= userdata
;
471 assert_cc(sizeof(int) == sizeof(int32_t));
473 r
= sd_bus_message_read(message
, "ii", &ifindex
, &family
);
477 if (!IN_SET(family
, AF_INET
, AF_INET6
))
478 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Unknown address family %i", family
);
480 r
= sd_bus_message_read_array(message
, 'y', &d
, &sz
);
484 if (sz
!= FAMILY_ADDRESS_SIZE(family
))
485 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid address size");
487 r
= sd_bus_message_read(message
, "t", &flags
);
491 r
= check_ifindex_flags(ifindex
, &flags
, 0, error
);
495 r
= dns_question_new_reverse(&question
, family
, d
);
499 r
= dns_query_new(m
, &q
, question
, question
, ifindex
, flags
|SD_RESOLVED_NO_SEARCH
);
503 q
->request
= sd_bus_message_ref(message
);
504 q
->request_family
= family
;
505 memcpy(&q
->request_address
, d
, sz
);
506 q
->complete
= bus_method_resolve_address_complete
;
508 r
= dns_query_bus_track(q
, message
);
523 static int bus_message_append_rr(sd_bus_message
*m
, DnsResourceRecord
*rr
, int ifindex
) {
529 r
= sd_bus_message_open_container(m
, 'r', "iqqay");
533 r
= sd_bus_message_append(m
, "iqq",
540 r
= dns_resource_record_to_wire_format(rr
, false);
544 r
= sd_bus_message_append_array(m
, 'y', rr
->wire_format
, rr
->wire_format_size
);
548 return sd_bus_message_close_container(m
);
551 static void bus_method_resolve_record_complete(DnsQuery
*q
) {
552 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
553 DnsResourceRecord
*rr
;
554 DnsQuestion
*question
;
561 if (q
->state
!= DNS_TRANSACTION_SUCCESS
) {
562 r
= reply_query_state(q
);
566 r
= dns_query_process_cname(q
);
568 r
= sd_bus_reply_method_errorf(q
->request
, BUS_ERROR_CNAME_LOOP
, "CNAME loop detected, or CNAME resolving disabled on '%s'", dns_query_string(q
));
573 if (r
== DNS_QUERY_RESTARTED
) /* This was a cname, and the query was restarted. */
576 r
= sd_bus_message_new_method_return(q
->request
, &reply
);
580 r
= sd_bus_message_open_container(reply
, 'a', "(iqqay)");
584 question
= dns_query_question_for_protocol(q
, q
->answer_protocol
);
586 DNS_ANSWER_FOREACH_IFINDEX(rr
, ifindex
, q
->answer
) {
587 r
= dns_question_matches_rr(question
, rr
, NULL
);
593 r
= bus_message_append_rr(reply
, rr
, ifindex
);
601 r
= sd_bus_reply_method_errorf(q
->request
, BUS_ERROR_NO_SUCH_RR
, "Name '%s' does not have any RR of the requested type", dns_query_string(q
));
605 r
= sd_bus_message_close_container(reply
);
609 r
= sd_bus_message_append(reply
, "t", SD_RESOLVED_FLAGS_MAKE(q
->answer_protocol
, q
->answer_family
, dns_query_fully_authenticated(q
)));
613 r
= sd_bus_send(q
->manager
->bus
, reply
, NULL
);
617 log_error_errno(r
, "Failed to send record reply: %m");
618 sd_bus_reply_method_errno(q
->request
, r
, NULL
);
624 static int bus_method_resolve_record(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
625 _cleanup_(dns_resource_key_unrefp
) DnsResourceKey
*key
= NULL
;
626 _cleanup_(dns_question_unrefp
) DnsQuestion
*question
= NULL
;
627 Manager
*m
= userdata
;
628 uint16_t class, type
;
637 assert_cc(sizeof(int) == sizeof(int32_t));
639 r
= sd_bus_message_read(message
, "isqqt", &ifindex
, &name
, &class, &type
, &flags
);
643 r
= dns_name_is_valid(name
);
647 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid name '%s'", name
);
649 if (!dns_type_is_valid_query(type
))
650 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Specified resource record type %" PRIu16
" may not be used in a query.", type
);
651 if (dns_type_is_zone_transer(type
))
652 return sd_bus_error_setf(error
, SD_BUS_ERROR_NOT_SUPPORTED
, "Zone transfers not permitted via this programming interface.");
653 if (dns_type_is_obsolete(type
))
654 return sd_bus_error_setf(error
, SD_BUS_ERROR_NOT_SUPPORTED
, "Specified DNS resource record type %" PRIu16
" is obsolete.", type
);
656 r
= check_ifindex_flags(ifindex
, &flags
, 0, error
);
660 question
= dns_question_new(1);
664 key
= dns_resource_key_new(class, type
, name
);
668 r
= dns_question_add(question
, key
);
672 r
= dns_query_new(m
, &q
, question
, question
, ifindex
, flags
|SD_RESOLVED_NO_SEARCH
);
676 /* Let's request that the TTL is fixed up for locally cached entries, after all we return it in the wire format
680 q
->request
= sd_bus_message_ref(message
);
681 q
->complete
= bus_method_resolve_record_complete
;
683 r
= dns_query_bus_track(q
, message
);
698 static int append_srv(DnsQuery
*q
, sd_bus_message
*reply
, DnsResourceRecord
*rr
) {
699 _cleanup_(dns_resource_record_unrefp
) DnsResourceRecord
*canonical
= NULL
;
700 _cleanup_free_
char *normalized
= NULL
;
709 if (rr
->key
->type
!= DNS_TYPE_SRV
)
712 if ((q
->flags
& SD_RESOLVED_NO_ADDRESS
) == 0) {
713 /* First, let's see if we could find an appropriate A or AAAA
714 * record for the SRV record */
715 LIST_FOREACH(auxiliary_queries
, aux
, q
->auxiliary_queries
) {
716 DnsResourceRecord
*zz
;
717 DnsQuestion
*question
;
719 if (aux
->state
!= DNS_TRANSACTION_SUCCESS
)
721 if (aux
->auxiliary_result
!= 0)
724 question
= dns_query_question_for_protocol(aux
, aux
->answer_protocol
);
726 r
= dns_name_equal(dns_question_first_name(question
), rr
->srv
.name
);
732 DNS_ANSWER_FOREACH(zz
, aux
->answer
) {
734 r
= dns_question_matches_rr(question
, zz
, NULL
);
740 canonical
= dns_resource_record_ref(zz
);
748 /* Is there are successful A/AAAA lookup for this SRV RR? If not, don't add it */
753 r
= sd_bus_message_open_container(reply
, 'r', "qqqsa(iiay)s");
757 r
= dns_name_normalize(rr
->srv
.name
, &normalized
);
761 r
= sd_bus_message_append(
764 rr
->srv
.priority
, rr
->srv
.weight
, rr
->srv
.port
, normalized
);
768 r
= sd_bus_message_open_container(reply
, 'a', "(iiay)");
772 if ((q
->flags
& SD_RESOLVED_NO_ADDRESS
) == 0) {
773 LIST_FOREACH(auxiliary_queries
, aux
, q
->auxiliary_queries
) {
774 DnsResourceRecord
*zz
;
775 DnsQuestion
*question
;
778 if (aux
->state
!= DNS_TRANSACTION_SUCCESS
)
780 if (aux
->auxiliary_result
!= 0)
783 question
= dns_query_question_for_protocol(aux
, aux
->answer_protocol
);
785 r
= dns_name_equal(dns_question_first_name(question
), rr
->srv
.name
);
791 DNS_ANSWER_FOREACH_IFINDEX(zz
, ifindex
, aux
->answer
) {
793 r
= dns_question_matches_rr(question
, zz
, NULL
);
799 r
= append_address(reply
, zz
, ifindex
);
806 r
= sd_bus_message_close_container(reply
);
811 normalized
= mfree(normalized
);
813 r
= dns_name_normalize(dns_resource_key_name(canonical
->key
), &normalized
);
818 /* Note that above we appended the hostname as encoded in the
819 * SRV, and here the canonical hostname this maps to. */
820 r
= sd_bus_message_append(reply
, "s", normalized
);
824 r
= sd_bus_message_close_container(reply
);
831 static int append_txt(sd_bus_message
*reply
, DnsResourceRecord
*rr
) {
839 if (rr
->key
->type
!= DNS_TYPE_TXT
)
842 LIST_FOREACH(items
, i
, rr
->txt
.items
) {
847 r
= sd_bus_message_append_array(reply
, 'y', i
->data
, i
->length
);
855 static void resolve_service_all_complete(DnsQuery
*q
) {
856 _cleanup_(dns_resource_record_unrefp
) DnsResourceRecord
*canonical
= NULL
;
857 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
858 _cleanup_free_
char *name
= NULL
, *type
= NULL
, *domain
= NULL
;
859 DnsQuestion
*question
;
860 DnsResourceRecord
*rr
;
867 if (q
->block_all_complete
> 0)
870 if ((q
->flags
& SD_RESOLVED_NO_ADDRESS
) == 0) {
871 DnsQuery
*bad
= NULL
;
872 bool have_success
= false;
874 LIST_FOREACH(auxiliary_queries
, aux
, q
->auxiliary_queries
) {
876 switch (aux
->state
) {
878 case DNS_TRANSACTION_PENDING
:
879 /* If an auxiliary query is still pending, let's wait */
882 case DNS_TRANSACTION_SUCCESS
:
883 if (aux
->auxiliary_result
== 0)
896 /* We can only return one error, hence pick the last error we encountered */
900 if (bad
->state
== DNS_TRANSACTION_SUCCESS
) {
901 assert(bad
->auxiliary_result
!= 0);
903 if (bad
->auxiliary_result
== -ELOOP
) {
904 r
= sd_bus_reply_method_errorf(q
->request
, BUS_ERROR_CNAME_LOOP
, "CNAME loop detected, or CNAME resolving disabled on '%s'", dns_query_string(bad
));
908 r
= bad
->auxiliary_result
;
912 r
= reply_query_state(bad
);
917 r
= sd_bus_message_new_method_return(q
->request
, &reply
);
921 r
= sd_bus_message_open_container(reply
, 'a', "(qqqsa(iiay)s)");
925 question
= dns_query_question_for_protocol(q
, q
->answer_protocol
);
926 DNS_ANSWER_FOREACH(rr
, q
->answer
) {
927 r
= dns_question_matches_rr(question
, rr
, NULL
);
933 r
= append_srv(q
, reply
, rr
);
936 if (r
== 0) /* not an SRV record */
940 canonical
= dns_resource_record_ref(rr
);
946 r
= sd_bus_reply_method_errorf(q
->request
, BUS_ERROR_NO_SUCH_RR
, "'%s' does not have any RR of the requested type", dns_query_string(q
));
950 r
= sd_bus_message_close_container(reply
);
954 r
= sd_bus_message_open_container(reply
, 'a', "ay");
958 DNS_ANSWER_FOREACH(rr
, q
->answer
) {
959 r
= dns_question_matches_rr(question
, rr
, NULL
);
965 r
= append_txt(reply
, rr
);
970 r
= sd_bus_message_close_container(reply
);
975 r
= dns_service_split(dns_resource_key_name(canonical
->key
), &name
, &type
, &domain
);
979 r
= sd_bus_message_append(
983 SD_RESOLVED_FLAGS_MAKE(q
->answer_protocol
, q
->answer_family
, dns_query_fully_authenticated(q
)));
987 r
= sd_bus_send(q
->manager
->bus
, reply
, NULL
);
991 log_error_errno(r
, "Failed to send service reply: %m");
992 sd_bus_reply_method_errno(q
->request
, r
, NULL
);
998 static void resolve_service_hostname_complete(DnsQuery
*q
) {
1002 assert(q
->auxiliary_for
);
1004 if (q
->state
!= DNS_TRANSACTION_SUCCESS
) {
1005 resolve_service_all_complete(q
->auxiliary_for
);
1009 r
= dns_query_process_cname(q
);
1010 if (r
== DNS_QUERY_RESTARTED
) /* This was a cname, and the query was restarted. */
1013 /* This auxiliary lookup is finished or failed, let's see if all are finished now. */
1014 q
->auxiliary_result
= r
;
1015 resolve_service_all_complete(q
->auxiliary_for
);
1018 static int resolve_service_hostname(DnsQuery
*q
, DnsResourceRecord
*rr
, int ifindex
) {
1019 _cleanup_(dns_question_unrefp
) DnsQuestion
*question
= NULL
;
1026 assert(rr
->key
->type
== DNS_TYPE_SRV
);
1028 /* OK, we found an SRV record for the service. Let's resolve
1029 * the hostname included in it */
1031 r
= dns_question_new_address(&question
, q
->request_family
, rr
->srv
.name
, false);
1035 r
= dns_query_new(q
->manager
, &aux
, question
, question
, ifindex
, q
->flags
|SD_RESOLVED_NO_SEARCH
);
1039 aux
->request_family
= q
->request_family
;
1040 aux
->complete
= resolve_service_hostname_complete
;
1042 r
= dns_query_make_auxiliary(aux
, q
);
1044 /* Too many auxiliary lookups? If so, don't complain,
1045 * let's just not add this one, we already have more
1048 dns_query_free(aux
);
1054 /* Note that auxiliary queries do not track the original bus
1055 * client, only the primary request does that. */
1057 r
= dns_query_go(aux
);
1064 dns_query_free(aux
);
1068 static void bus_method_resolve_service_complete(DnsQuery
*q
) {
1069 bool has_root_domain
= false;
1070 DnsResourceRecord
*rr
;
1071 DnsQuestion
*question
;
1077 if (q
->state
!= DNS_TRANSACTION_SUCCESS
) {
1078 r
= reply_query_state(q
);
1082 r
= dns_query_process_cname(q
);
1084 r
= sd_bus_reply_method_errorf(q
->request
, BUS_ERROR_CNAME_LOOP
, "CNAME loop detected, or CNAME resolving disabled on '%s'", dns_query_string(q
));
1089 if (r
== DNS_QUERY_RESTARTED
) /* This was a cname, and the query was restarted. */
1092 question
= dns_query_question_for_protocol(q
, q
->answer_protocol
);
1094 DNS_ANSWER_FOREACH_IFINDEX(rr
, ifindex
, q
->answer
) {
1095 r
= dns_question_matches_rr(question
, rr
, NULL
);
1101 if (rr
->key
->type
!= DNS_TYPE_SRV
)
1104 if (dns_name_is_root(rr
->srv
.name
)) {
1105 has_root_domain
= true;
1109 if ((q
->flags
& SD_RESOLVED_NO_ADDRESS
) == 0) {
1110 q
->block_all_complete
++;
1111 r
= resolve_service_hostname(q
, rr
, ifindex
);
1112 q
->block_all_complete
--;
1121 if (has_root_domain
&& found
<= 0) {
1122 /* If there's exactly one SRV RR and it uses
1123 * the root domain as host name, then the
1124 * service is explicitly not offered on the
1125 * domain. Report this as a recognizable
1126 * error. See RFC 2782, Section "Usage
1128 r
= sd_bus_reply_method_errorf(q
->request
, BUS_ERROR_NO_SUCH_SERVICE
, "'%s' does not provide the requested service", dns_query_string(q
));
1133 r
= sd_bus_reply_method_errorf(q
->request
, BUS_ERROR_NO_SUCH_RR
, "'%s' does not have any RR of the requested type", dns_query_string(q
));
1137 /* Maybe we are already finished? check now... */
1138 resolve_service_all_complete(q
);
1143 log_error_errno(r
, "Failed to send service reply: %m");
1144 sd_bus_reply_method_errno(q
->request
, r
, NULL
);
1150 static int bus_method_resolve_service(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1151 _cleanup_(dns_question_unrefp
) DnsQuestion
*question_idna
= NULL
, *question_utf8
= NULL
;
1152 const char *name
, *type
, *domain
;
1153 Manager
*m
= userdata
;
1154 int family
, ifindex
;
1162 assert_cc(sizeof(int) == sizeof(int32_t));
1164 r
= sd_bus_message_read(message
, "isssit", &ifindex
, &name
, &type
, &domain
, &family
, &flags
);
1168 if (!IN_SET(family
, AF_INET
, AF_INET6
, AF_UNSPEC
))
1169 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Unknown address family %i", family
);
1173 else if (!dns_service_name_is_valid(name
))
1174 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid service name '%s'", name
);
1178 else if (!dns_srv_type_is_valid(type
))
1179 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid SRV service type '%s'", type
);
1181 r
= dns_name_is_valid(domain
);
1185 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid domain '%s'", domain
);
1188 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Service name cannot be specified without service type.");
1190 r
= check_ifindex_flags(ifindex
, &flags
, SD_RESOLVED_NO_TXT
|SD_RESOLVED_NO_ADDRESS
, error
);
1194 r
= dns_question_new_service(&question_utf8
, name
, type
, domain
, !(flags
& SD_RESOLVED_NO_TXT
), false);
1198 r
= dns_question_new_service(&question_idna
, name
, type
, domain
, !(flags
& SD_RESOLVED_NO_TXT
), true);
1202 r
= dns_query_new(m
, &q
, question_utf8
, question_idna
, ifindex
, flags
|SD_RESOLVED_NO_SEARCH
);
1206 q
->request
= sd_bus_message_ref(message
);
1207 q
->request_family
= family
;
1208 q
->complete
= bus_method_resolve_service_complete
;
1210 r
= dns_query_bus_track(q
, message
);
1214 r
= dns_query_go(q
);
1225 int bus_dns_server_append(sd_bus_message
*reply
, DnsServer
*s
, bool with_ifindex
) {
1231 r
= sd_bus_message_open_container(reply
, 'r', with_ifindex
? "iiay" : "iay");
1236 r
= sd_bus_message_append(reply
, "i", dns_server_ifindex(s
));
1241 r
= sd_bus_message_append(reply
, "i", s
->family
);
1245 r
= sd_bus_message_append_array(reply
, 'y', &s
->address
, FAMILY_ADDRESS_SIZE(s
->family
));
1249 return sd_bus_message_close_container(reply
);
1252 static int bus_property_get_dns_servers(
1255 const char *interface
,
1256 const char *property
,
1257 sd_bus_message
*reply
,
1259 sd_bus_error
*error
) {
1261 Manager
*m
= userdata
;
1271 r
= sd_bus_message_open_container(reply
, 'a', "(iiay)");
1275 LIST_FOREACH(servers
, s
, m
->dns_servers
) {
1276 r
= bus_dns_server_append(reply
, s
, true);
1283 HASHMAP_FOREACH(l
, m
->links
, i
) {
1284 LIST_FOREACH(servers
, s
, l
->dns_servers
) {
1285 r
= bus_dns_server_append(reply
, s
, true);
1293 LIST_FOREACH(servers
, s
, m
->fallback_dns_servers
) {
1294 r
= bus_dns_server_append(reply
, s
, true);
1300 return sd_bus_message_close_container(reply
);
1303 static int bus_property_get_domains(
1306 const char *interface
,
1307 const char *property
,
1308 sd_bus_message
*reply
,
1310 sd_bus_error
*error
) {
1312 Manager
*m
= userdata
;
1321 r
= sd_bus_message_open_container(reply
, 'a', "(isb)");
1325 LIST_FOREACH(domains
, d
, m
->search_domains
) {
1326 r
= sd_bus_message_append(reply
, "(isb)", 0, d
->name
, d
->route_only
);
1331 HASHMAP_FOREACH(l
, m
->links
, i
) {
1332 LIST_FOREACH(domains
, d
, l
->search_domains
) {
1333 r
= sd_bus_message_append(reply
, "(isb)", l
->ifindex
, d
->name
, d
->route_only
);
1339 return sd_bus_message_close_container(reply
);
1342 static int bus_property_get_transaction_statistics(
1345 const char *interface
,
1346 const char *property
,
1347 sd_bus_message
*reply
,
1349 sd_bus_error
*error
) {
1351 Manager
*m
= userdata
;
1356 return sd_bus_message_append(reply
, "(tt)",
1357 (uint64_t) hashmap_size(m
->dns_transactions
),
1358 (uint64_t) m
->n_transactions_total
);
1361 static int bus_property_get_cache_statistics(
1364 const char *interface
,
1365 const char *property
,
1366 sd_bus_message
*reply
,
1368 sd_bus_error
*error
) {
1370 uint64_t size
= 0, hit
= 0, miss
= 0;
1371 Manager
*m
= userdata
;
1377 LIST_FOREACH(scopes
, s
, m
->dns_scopes
) {
1378 size
+= dns_cache_size(&s
->cache
);
1379 hit
+= s
->cache
.n_hit
;
1380 miss
+= s
->cache
.n_miss
;
1383 return sd_bus_message_append(reply
, "(ttt)", size
, hit
, miss
);
1386 static int bus_property_get_dnssec_statistics(
1389 const char *interface
,
1390 const char *property
,
1391 sd_bus_message
*reply
,
1393 sd_bus_error
*error
) {
1395 Manager
*m
= userdata
;
1400 return sd_bus_message_append(reply
, "(tttt)",
1401 (uint64_t) m
->n_dnssec_verdict
[DNSSEC_SECURE
],
1402 (uint64_t) m
->n_dnssec_verdict
[DNSSEC_INSECURE
],
1403 (uint64_t) m
->n_dnssec_verdict
[DNSSEC_BOGUS
],
1404 (uint64_t) m
->n_dnssec_verdict
[DNSSEC_INDETERMINATE
]);
1407 static int bus_property_get_dnssec_supported(
1410 const char *interface
,
1411 const char *property
,
1412 sd_bus_message
*reply
,
1414 sd_bus_error
*error
) {
1416 Manager
*m
= userdata
;
1421 return sd_bus_message_append(reply
, "b", manager_dnssec_supported(m
));
1424 static int bus_property_get_ntas(
1427 const char *interface
,
1428 const char *property
,
1429 sd_bus_message
*reply
,
1431 sd_bus_error
*error
) {
1433 Manager
*m
= userdata
;
1441 r
= sd_bus_message_open_container(reply
, 'a', "s");
1445 SET_FOREACH(domain
, m
->trust_anchor
.negative_by_name
, i
) {
1446 r
= sd_bus_message_append(reply
, "s", domain
);
1451 return sd_bus_message_close_container(reply
);
1454 static BUS_DEFINE_PROPERTY_GET_ENUM(bus_property_get_dns_stub_listener_mode
, dns_stub_listener_mode
, DnsStubListenerMode
);
1456 static int bus_method_reset_statistics(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1457 Manager
*m
= userdata
;
1463 LIST_FOREACH(scopes
, s
, m
->dns_scopes
)
1464 s
->cache
.n_hit
= s
->cache
.n_miss
= 0;
1466 m
->n_transactions_total
= 0;
1467 zero(m
->n_dnssec_verdict
);
1469 return sd_bus_reply_method_return(message
, NULL
);
1472 static int get_any_link(Manager
*m
, int ifindex
, Link
**ret
, sd_bus_error
*error
) {
1479 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid interface index");
1481 l
= hashmap_get(m
->links
, INT_TO_PTR(ifindex
));
1483 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_LINK
, "Link %i not known", ifindex
);
1489 static int call_link_method(Manager
*m
, sd_bus_message
*message
, sd_bus_message_handler_t handler
, sd_bus_error
*error
) {
1497 assert_cc(sizeof(int) == sizeof(int32_t));
1498 r
= sd_bus_message_read(message
, "i", &ifindex
);
1502 r
= get_any_link(m
, ifindex
, &l
, error
);
1506 return handler(message
, l
, error
);
1509 static int bus_method_set_link_dns_servers(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1510 return call_link_method(userdata
, message
, bus_link_method_set_dns_servers
, error
);
1513 static int bus_method_set_link_domains(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1514 return call_link_method(userdata
, message
, bus_link_method_set_domains
, error
);
1517 static int bus_method_set_link_llmnr(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1518 return call_link_method(userdata
, message
, bus_link_method_set_llmnr
, error
);
1521 static int bus_method_set_link_mdns(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1522 return call_link_method(userdata
, message
, bus_link_method_set_mdns
, error
);
1525 static int bus_method_set_link_dnssec(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1526 return call_link_method(userdata
, message
, bus_link_method_set_dnssec
, error
);
1529 static int bus_method_set_link_dnssec_negative_trust_anchors(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1530 return call_link_method(userdata
, message
, bus_link_method_set_dnssec_negative_trust_anchors
, error
);
1533 static int bus_method_revert_link(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1534 return call_link_method(userdata
, message
, bus_link_method_revert
, error
);
1537 static int bus_method_get_link(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1538 _cleanup_free_
char *p
= NULL
;
1539 Manager
*m
= userdata
;
1546 assert_cc(sizeof(int) == sizeof(int32_t));
1547 r
= sd_bus_message_read(message
, "i", &ifindex
);
1551 r
= get_any_link(m
, ifindex
, &l
, error
);
1555 p
= link_bus_path(l
);
1559 return sd_bus_reply_method_return(message
, "o", p
);
1562 static int bus_method_flush_caches(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1563 Manager
*m
= userdata
;
1568 manager_flush_caches(m
);
1570 return sd_bus_reply_method_return(message
, NULL
);
1573 static int bus_method_reset_server_features(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1574 Manager
*m
= userdata
;
1579 manager_reset_server_features(m
);
1581 return sd_bus_reply_method_return(message
, NULL
);
1584 static const sd_bus_vtable resolve_vtable
[] = {
1585 SD_BUS_VTABLE_START(0),
1586 SD_BUS_PROPERTY("LLMNRHostname", "s", NULL
, offsetof(Manager
, llmnr_hostname
), 0),
1587 SD_BUS_PROPERTY("DNS", "a(iiay)", bus_property_get_dns_servers
, 0, 0),
1588 SD_BUS_PROPERTY("Domains", "a(isb)", bus_property_get_domains
, 0, 0),
1589 SD_BUS_PROPERTY("TransactionStatistics", "(tt)", bus_property_get_transaction_statistics
, 0, 0),
1590 SD_BUS_PROPERTY("CacheStatistics", "(ttt)", bus_property_get_cache_statistics
, 0, 0),
1591 SD_BUS_PROPERTY("DNSSECStatistics", "(tttt)", bus_property_get_dnssec_statistics
, 0, 0),
1592 SD_BUS_PROPERTY("DNSSECSupported", "b", bus_property_get_dnssec_supported
, 0, 0),
1593 SD_BUS_PROPERTY("DNSSECNegativeTrustAnchors", "as", bus_property_get_ntas
, 0, 0),
1594 SD_BUS_PROPERTY("DNSStubListener", "s", bus_property_get_dns_stub_listener_mode
, offsetof(Manager
, dns_stub_listener_mode
), 0),
1596 SD_BUS_METHOD("ResolveHostname", "isit", "a(iiay)st", bus_method_resolve_hostname
, SD_BUS_VTABLE_UNPRIVILEGED
),
1597 SD_BUS_METHOD("ResolveAddress", "iiayt", "a(is)t", bus_method_resolve_address
, SD_BUS_VTABLE_UNPRIVILEGED
),
1598 SD_BUS_METHOD("ResolveRecord", "isqqt", "a(iqqay)t", bus_method_resolve_record
, SD_BUS_VTABLE_UNPRIVILEGED
),
1599 SD_BUS_METHOD("ResolveService", "isssit", "a(qqqsa(iiay)s)aayssst", bus_method_resolve_service
, SD_BUS_VTABLE_UNPRIVILEGED
),
1600 SD_BUS_METHOD("ResetStatistics", NULL
, NULL
, bus_method_reset_statistics
, 0),
1601 SD_BUS_METHOD("FlushCaches", NULL
, NULL
, bus_method_flush_caches
, 0),
1602 SD_BUS_METHOD("ResetServerFeatures", NULL
, NULL
, bus_method_reset_server_features
, 0),
1603 SD_BUS_METHOD("GetLink", "i", "o", bus_method_get_link
, SD_BUS_VTABLE_UNPRIVILEGED
),
1604 SD_BUS_METHOD("SetLinkDNS", "ia(iay)", NULL
, bus_method_set_link_dns_servers
, 0),
1605 SD_BUS_METHOD("SetLinkDomains", "ia(sb)", NULL
, bus_method_set_link_domains
, 0),
1606 SD_BUS_METHOD("SetLinkLLMNR", "is", NULL
, bus_method_set_link_llmnr
, 0),
1607 SD_BUS_METHOD("SetLinkMulticastDNS", "is", NULL
, bus_method_set_link_mdns
, 0),
1608 SD_BUS_METHOD("SetLinkDNSSEC", "is", NULL
, bus_method_set_link_dnssec
, 0),
1609 SD_BUS_METHOD("SetLinkDNSSECNegativeTrustAnchors", "ias", NULL
, bus_method_set_link_dnssec_negative_trust_anchors
, 0),
1610 SD_BUS_METHOD("RevertLink", "i", NULL
, bus_method_revert_link
, 0),
1615 static int on_bus_retry(sd_event_source
*s
, usec_t usec
, void *userdata
) {
1616 Manager
*m
= userdata
;
1621 m
->bus_retry_event_source
= sd_event_source_unref(m
->bus_retry_event_source
);
1623 manager_connect_bus(m
);
1627 static int match_prepare_for_sleep(sd_bus_message
*message
, void *userdata
, sd_bus_error
*ret_error
) {
1628 Manager
*m
= userdata
;
1634 r
= sd_bus_message_read(message
, "b", &b
);
1636 log_debug_errno(r
, "Failed to parse PrepareForSleep signal: %m");
1643 log_debug("Coming back from suspend, verifying all RRs...");
1645 manager_verify_all(m
);
1649 int manager_connect_bus(Manager
*m
) {
1657 r
= sd_bus_default_system(&m
->bus
);
1659 /* We failed to connect? Yuck, we must be in early
1660 * boot. Let's try in 5s again. */
1662 log_debug_errno(r
, "Failed to connect to bus, trying again in 5s: %m");
1664 r
= sd_event_add_time(m
->event
, &m
->bus_retry_event_source
, CLOCK_MONOTONIC
, now(CLOCK_MONOTONIC
) + 5*USEC_PER_SEC
, 0, on_bus_retry
, m
);
1666 return log_error_errno(r
, "Failed to install bus reconnect time event: %m");
1668 (void) sd_event_source_set_description(m
->bus_retry_event_source
, "bus-retry");
1672 r
= sd_bus_add_object_vtable(m
->bus
, NULL
, "/org/freedesktop/resolve1", "org.freedesktop.resolve1.Manager", resolve_vtable
, m
);
1674 return log_error_errno(r
, "Failed to register object: %m");
1676 r
= sd_bus_add_fallback_vtable(m
->bus
, NULL
, "/org/freedesktop/resolve1/link", "org.freedesktop.resolve1.Link", link_vtable
, link_object_find
, m
);
1678 return log_error_errno(r
, "Failed to register link objects: %m");
1680 r
= sd_bus_add_node_enumerator(m
->bus
, NULL
, "/org/freedesktop/resolve1/link", link_node_enumerator
, m
);
1682 return log_error_errno(r
, "Failed to register link enumerator: %m");
1684 r
= sd_bus_request_name(m
->bus
, "org.freedesktop.resolve1", 0);
1686 return log_error_errno(r
, "Failed to register name: %m");
1688 r
= sd_bus_attach_event(m
->bus
, m
->event
, 0);
1690 return log_error_errno(r
, "Failed to attach bus to event loop: %m");
1692 r
= sd_bus_add_match(m
->bus
, &m
->prepare_for_sleep_slot
,
1694 "sender='org.freedesktop.login1',"
1695 "interface='org.freedesktop.login1.Manager',"
1696 "member='PrepareForSleep',"
1697 "path='/org/freedesktop/login1'",
1698 match_prepare_for_sleep
,
1701 log_error_errno(r
, "Failed to add match for PrepareForSleep: %m");