2 This file is part of systemd.
4 Copyright 2014 Lennart Poettering
6 systemd is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation; either version 2.1 of the License, or
9 (at your option) any later version.
11 systemd is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public License
17 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 #include "alloc-util.h"
21 #include "bus-common-errors.h"
23 #include "dns-domain.h"
24 #include "resolved-bus.h"
25 #include "resolved-def.h"
26 #include "resolved-dns-synthesize.h"
27 #include "resolved-link-bus.h"
29 static int reply_query_state(DnsQuery
*q
) {
33 case DNS_TRANSACTION_NO_SERVERS
:
34 return sd_bus_reply_method_errorf(q
->request
, BUS_ERROR_NO_NAME_SERVERS
, "No appropriate name servers or networks for name found");
36 case DNS_TRANSACTION_TIMEOUT
:
37 return sd_bus_reply_method_errorf(q
->request
, SD_BUS_ERROR_TIMEOUT
, "Query timed out");
39 case DNS_TRANSACTION_ATTEMPTS_MAX_REACHED
:
40 return sd_bus_reply_method_errorf(q
->request
, SD_BUS_ERROR_TIMEOUT
, "All attempts to contact name servers or networks failed");
42 case DNS_TRANSACTION_INVALID_REPLY
:
43 return sd_bus_reply_method_errorf(q
->request
, BUS_ERROR_INVALID_REPLY
, "Received invalid reply");
45 case DNS_TRANSACTION_ERRNO
:
46 return sd_bus_reply_method_errnof(q
->request
, q
->answer_errno
, "Lookup failed due to system error: %m");
48 case DNS_TRANSACTION_ABORTED
:
49 return sd_bus_reply_method_errorf(q
->request
, BUS_ERROR_ABORTED
, "Query aborted");
51 case DNS_TRANSACTION_DNSSEC_FAILED
:
52 return sd_bus_reply_method_errorf(q
->request
, BUS_ERROR_DNSSEC_FAILED
, "DNSSEC validation failed: %s",
53 dnssec_result_to_string(q
->answer_dnssec_result
));
55 case DNS_TRANSACTION_NO_TRUST_ANCHOR
:
56 return sd_bus_reply_method_errorf(q
->request
, BUS_ERROR_NO_TRUST_ANCHOR
, "No suitable trust anchor known");
58 case DNS_TRANSACTION_RR_TYPE_UNSUPPORTED
:
59 return sd_bus_reply_method_errorf(q
->request
, BUS_ERROR_RR_TYPE_UNSUPPORTED
, "Server does not support requested resource record type");
61 case DNS_TRANSACTION_NETWORK_DOWN
:
62 return sd_bus_reply_method_errorf(q
->request
, BUS_ERROR_NETWORK_DOWN
, "Network is down");
64 case DNS_TRANSACTION_NOT_FOUND
:
65 /* We return this as NXDOMAIN. This is only generated when a host doesn't implement LLMNR/TCP, and we
66 * thus quickly know that we cannot resolve an in-addr.arpa or ip6.arpa address. */
67 return sd_bus_reply_method_errorf(q
->request
, _BUS_ERROR_DNS
"NXDOMAIN", "'%s' not found", dns_query_string(q
));
69 case DNS_TRANSACTION_RCODE_FAILURE
: {
70 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
72 if (q
->answer_rcode
== DNS_RCODE_NXDOMAIN
)
73 sd_bus_error_setf(&error
, _BUS_ERROR_DNS
"NXDOMAIN", "'%s' not found", dns_query_string(q
));
76 char p
[DECIMAL_STR_MAX(q
->answer_rcode
)];
78 rc
= dns_rcode_to_string(q
->answer_rcode
);
80 sprintf(p
, "%i", q
->answer_rcode
);
84 n
= strjoina(_BUS_ERROR_DNS
, rc
);
85 sd_bus_error_setf(&error
, n
, "Could not resolve '%s', server or network returned error %s", dns_query_string(q
), rc
);
88 return sd_bus_reply_method_error(q
->request
, &error
);
91 case DNS_TRANSACTION_NULL
:
92 case DNS_TRANSACTION_PENDING
:
93 case DNS_TRANSACTION_VALIDATING
:
94 case DNS_TRANSACTION_SUCCESS
:
96 assert_not_reached("Impossible state");
100 static int append_address(sd_bus_message
*reply
, DnsResourceRecord
*rr
, int ifindex
) {
106 r
= sd_bus_message_open_container(reply
, 'r', "iiay");
110 r
= sd_bus_message_append(reply
, "i", ifindex
);
114 if (rr
->key
->type
== DNS_TYPE_A
) {
115 r
= sd_bus_message_append(reply
, "i", AF_INET
);
119 r
= sd_bus_message_append_array(reply
, 'y', &rr
->a
.in_addr
, sizeof(struct in_addr
));
121 } else if (rr
->key
->type
== DNS_TYPE_AAAA
) {
122 r
= sd_bus_message_append(reply
, "i", AF_INET6
);
126 r
= sd_bus_message_append_array(reply
, 'y', &rr
->aaaa
.in6_addr
, sizeof(struct in6_addr
));
128 return -EAFNOSUPPORT
;
133 r
= sd_bus_message_close_container(reply
);
140 static void bus_method_resolve_hostname_complete(DnsQuery
*q
) {
141 _cleanup_(dns_resource_record_unrefp
) DnsResourceRecord
*canonical
= NULL
;
142 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
143 _cleanup_free_
char *normalized
= NULL
;
144 DnsResourceRecord
*rr
;
150 if (q
->state
!= DNS_TRANSACTION_SUCCESS
) {
151 r
= reply_query_state(q
);
155 r
= dns_query_process_cname(q
);
157 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
));
162 if (r
== DNS_QUERY_RESTARTED
) /* This was a cname, and the query was restarted. */
165 r
= sd_bus_message_new_method_return(q
->request
, &reply
);
169 r
= sd_bus_message_open_container(reply
, 'a', "(iiay)");
173 DNS_ANSWER_FOREACH_IFINDEX(rr
, ifindex
, q
->answer
) {
174 DnsQuestion
*question
;
176 question
= dns_query_question_for_protocol(q
, q
->answer_protocol
);
178 r
= dns_question_matches_rr(question
, rr
, DNS_SEARCH_DOMAIN_NAME(q
->answer_search_domain
));
184 r
= append_address(reply
, rr
, ifindex
);
189 canonical
= dns_resource_record_ref(rr
);
195 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
));
199 r
= sd_bus_message_close_container(reply
);
203 /* The key names are not necessarily normalized, make sure that they are when we return them to our bus
205 r
= dns_name_normalize(dns_resource_key_name(canonical
->key
), &normalized
);
209 /* Return the precise spelling and uppercasing and CNAME target reported by the server */
211 r
= sd_bus_message_append(
214 SD_RESOLVED_FLAGS_MAKE(q
->answer_protocol
, q
->answer_family
, dns_query_fully_authenticated(q
)));
218 r
= sd_bus_send(q
->manager
->bus
, reply
, NULL
);
222 log_error_errno(r
, "Failed to send hostname reply: %m");
223 sd_bus_reply_method_errno(q
->request
, r
, NULL
);
229 static int check_ifindex_flags(int ifindex
, uint64_t *flags
, uint64_t ok
, sd_bus_error
*error
) {
233 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid interface index");
235 if (*flags
& ~(SD_RESOLVED_PROTOCOLS_ALL
|SD_RESOLVED_NO_CNAME
|ok
))
236 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid flags parameter");
238 if ((*flags
& SD_RESOLVED_PROTOCOLS_ALL
) == 0) /* If no protocol is enabled, enable all */
239 *flags
|= SD_RESOLVED_PROTOCOLS_ALL
;
244 static int parse_as_address(sd_bus_message
*m
, int ifindex
, const char *hostname
, int family
, uint64_t flags
) {
245 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
246 _cleanup_free_
char *canonical
= NULL
;
247 union in_addr_union parsed
;
248 int r
, ff
, parsed_ifindex
= 0;
250 /* Check if the hostname is actually already an IP address formatted as string. In that case just parse it,
251 * let's not attempt to look it up. */
253 r
= in_addr_ifindex_from_string_auto(hostname
, &ff
, &parsed
, &parsed_ifindex
);
254 if (r
< 0) /* not an address */
257 if (family
!= AF_UNSPEC
&& ff
!= family
)
258 return sd_bus_reply_method_errorf(m
, BUS_ERROR_NO_SUCH_RR
, "The specified address is not of the requested family.");
259 if (ifindex
> 0 && parsed_ifindex
> 0 && parsed_ifindex
!= ifindex
)
260 return sd_bus_reply_method_errorf(m
, BUS_ERROR_NO_SUCH_RR
, "The specified address interface index does not match requested interface.");
262 if (parsed_ifindex
> 0)
263 ifindex
= parsed_ifindex
;
265 r
= sd_bus_message_new_method_return(m
, &reply
);
269 r
= sd_bus_message_open_container(reply
, 'a', "(iiay)");
273 r
= sd_bus_message_open_container(reply
, 'r', "iiay");
277 r
= sd_bus_message_append(reply
, "ii", ifindex
, ff
);
281 r
= sd_bus_message_append_array(reply
, 'y', &parsed
, FAMILY_ADDRESS_SIZE(ff
));
285 r
= sd_bus_message_close_container(reply
);
289 r
= sd_bus_message_close_container(reply
);
293 /* When an IP address is specified we just return it as canonical name, in order to avoid a DNS
294 * look-up. However, we reformat it to make sure it's in a truly canonical form (i.e. on IPv6 the inner
295 * omissions are always done the same way). */
296 r
= in_addr_ifindex_to_string(ff
, &parsed
, ifindex
, &canonical
);
300 r
= sd_bus_message_append(reply
, "st", canonical
,
301 SD_RESOLVED_FLAGS_MAKE(dns_synthesize_protocol(flags
), ff
, true));
305 return sd_bus_send(sd_bus_message_get_bus(m
), reply
, NULL
);
308 static int bus_method_resolve_hostname(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
309 _cleanup_(dns_question_unrefp
) DnsQuestion
*question_idna
= NULL
, *question_utf8
= NULL
;
310 Manager
*m
= userdata
;
311 const char *hostname
;
320 assert_cc(sizeof(int) == sizeof(int32_t));
322 r
= sd_bus_message_read(message
, "isit", &ifindex
, &hostname
, &family
, &flags
);
326 if (!IN_SET(family
, AF_INET
, AF_INET6
, AF_UNSPEC
))
327 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Unknown address family %i", family
);
329 r
= check_ifindex_flags(ifindex
, &flags
, SD_RESOLVED_NO_SEARCH
, error
);
333 r
= parse_as_address(message
, ifindex
, hostname
, family
, flags
);
337 r
= dns_name_is_valid(hostname
);
341 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid hostname '%s'", hostname
);
343 r
= dns_question_new_address(&question_utf8
, family
, hostname
, false);
347 r
= dns_question_new_address(&question_idna
, family
, hostname
, true);
351 r
= dns_query_new(m
, &q
, question_utf8
, question_idna
, ifindex
, flags
);
355 q
->request
= sd_bus_message_ref(message
);
356 q
->request_family
= family
;
357 q
->complete
= bus_method_resolve_hostname_complete
;
358 q
->suppress_unroutable_family
= family
== AF_UNSPEC
;
360 r
= dns_query_bus_track(q
, message
);
375 static void bus_method_resolve_address_complete(DnsQuery
*q
) {
376 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
377 DnsQuestion
*question
;
378 DnsResourceRecord
*rr
;
384 if (q
->state
!= DNS_TRANSACTION_SUCCESS
) {
385 r
= reply_query_state(q
);
389 r
= dns_query_process_cname(q
);
391 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
));
396 if (r
== DNS_QUERY_RESTARTED
) /* This was a cname, and the query was restarted. */
399 r
= sd_bus_message_new_method_return(q
->request
, &reply
);
403 r
= sd_bus_message_open_container(reply
, 'a', "(is)");
407 question
= dns_query_question_for_protocol(q
, q
->answer_protocol
);
409 DNS_ANSWER_FOREACH_IFINDEX(rr
, ifindex
, q
->answer
) {
410 _cleanup_free_
char *normalized
= NULL
;
412 r
= dns_question_matches_rr(question
, rr
, NULL
);
418 r
= dns_name_normalize(rr
->ptr
.name
, &normalized
);
422 r
= sd_bus_message_append(reply
, "(is)", ifindex
, normalized
);
430 _cleanup_free_
char *ip
= NULL
;
432 (void) in_addr_to_string(q
->request_family
, &q
->request_address
, &ip
);
433 r
= sd_bus_reply_method_errorf(q
->request
, BUS_ERROR_NO_SUCH_RR
,
434 "Address '%s' does not have any RR of requested type", strnull(ip
));
438 r
= sd_bus_message_close_container(reply
);
442 r
= sd_bus_message_append(reply
, "t", SD_RESOLVED_FLAGS_MAKE(q
->answer_protocol
, q
->answer_family
, dns_query_fully_authenticated(q
)));
446 r
= sd_bus_send(q
->manager
->bus
, reply
, NULL
);
450 log_error_errno(r
, "Failed to send address reply: %m");
451 sd_bus_reply_method_errno(q
->request
, r
, NULL
);
457 static int bus_method_resolve_address(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
458 _cleanup_(dns_question_unrefp
) DnsQuestion
*question
= NULL
;
459 Manager
*m
= userdata
;
470 assert_cc(sizeof(int) == sizeof(int32_t));
472 r
= sd_bus_message_read(message
, "ii", &ifindex
, &family
);
476 if (!IN_SET(family
, AF_INET
, AF_INET6
))
477 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Unknown address family %i", family
);
479 r
= sd_bus_message_read_array(message
, 'y', &d
, &sz
);
483 if (sz
!= FAMILY_ADDRESS_SIZE(family
))
484 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid address size");
486 r
= sd_bus_message_read(message
, "t", &flags
);
490 r
= check_ifindex_flags(ifindex
, &flags
, 0, error
);
494 r
= dns_question_new_reverse(&question
, family
, d
);
498 r
= dns_query_new(m
, &q
, question
, question
, ifindex
, flags
|SD_RESOLVED_NO_SEARCH
);
502 q
->request
= sd_bus_message_ref(message
);
503 q
->request_family
= family
;
504 memcpy(&q
->request_address
, d
, sz
);
505 q
->complete
= bus_method_resolve_address_complete
;
507 r
= dns_query_bus_track(q
, message
);
522 static int bus_message_append_rr(sd_bus_message
*m
, DnsResourceRecord
*rr
, int ifindex
) {
528 r
= sd_bus_message_open_container(m
, 'r', "iqqay");
532 r
= sd_bus_message_append(m
, "iqq",
539 r
= dns_resource_record_to_wire_format(rr
, false);
543 r
= sd_bus_message_append_array(m
, 'y', rr
->wire_format
, rr
->wire_format_size
);
547 return sd_bus_message_close_container(m
);
550 static void bus_method_resolve_record_complete(DnsQuery
*q
) {
551 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
552 DnsResourceRecord
*rr
;
553 DnsQuestion
*question
;
560 if (q
->state
!= DNS_TRANSACTION_SUCCESS
) {
561 r
= reply_query_state(q
);
565 r
= dns_query_process_cname(q
);
567 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
));
572 if (r
== DNS_QUERY_RESTARTED
) /* This was a cname, and the query was restarted. */
575 r
= sd_bus_message_new_method_return(q
->request
, &reply
);
579 r
= sd_bus_message_open_container(reply
, 'a', "(iqqay)");
583 question
= dns_query_question_for_protocol(q
, q
->answer_protocol
);
585 DNS_ANSWER_FOREACH_IFINDEX(rr
, ifindex
, q
->answer
) {
586 r
= dns_question_matches_rr(question
, rr
, NULL
);
592 r
= bus_message_append_rr(reply
, rr
, ifindex
);
600 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
));
604 r
= sd_bus_message_close_container(reply
);
608 r
= sd_bus_message_append(reply
, "t", SD_RESOLVED_FLAGS_MAKE(q
->answer_protocol
, q
->answer_family
, dns_query_fully_authenticated(q
)));
612 r
= sd_bus_send(q
->manager
->bus
, reply
, NULL
);
616 log_error_errno(r
, "Failed to send record reply: %m");
617 sd_bus_reply_method_errno(q
->request
, r
, NULL
);
623 static int bus_method_resolve_record(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
624 _cleanup_(dns_resource_key_unrefp
) DnsResourceKey
*key
= NULL
;
625 _cleanup_(dns_question_unrefp
) DnsQuestion
*question
= NULL
;
626 Manager
*m
= userdata
;
627 uint16_t class, type
;
636 assert_cc(sizeof(int) == sizeof(int32_t));
638 r
= sd_bus_message_read(message
, "isqqt", &ifindex
, &name
, &class, &type
, &flags
);
642 r
= dns_name_is_valid(name
);
646 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid name '%s'", name
);
648 if (!dns_type_is_valid_query(type
))
649 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Specified resource record type %" PRIu16
" may not be used in a query.", type
);
650 if (dns_type_is_zone_transer(type
))
651 return sd_bus_error_setf(error
, SD_BUS_ERROR_NOT_SUPPORTED
, "Zone transfers not permitted via this programming interface.");
652 if (dns_type_is_obsolete(type
))
653 return sd_bus_error_setf(error
, SD_BUS_ERROR_NOT_SUPPORTED
, "Specified DNS resource record type %" PRIu16
" is obsolete.", type
);
655 r
= check_ifindex_flags(ifindex
, &flags
, 0, error
);
659 question
= dns_question_new(1);
663 key
= dns_resource_key_new(class, type
, name
);
667 r
= dns_question_add(question
, key
);
671 r
= dns_query_new(m
, &q
, question
, question
, ifindex
, flags
|SD_RESOLVED_NO_SEARCH
);
675 /* Let's request that the TTL is fixed up for locally cached entries, after all we return it in the wire format
679 q
->request
= sd_bus_message_ref(message
);
680 q
->complete
= bus_method_resolve_record_complete
;
682 r
= dns_query_bus_track(q
, message
);
697 static int append_srv(DnsQuery
*q
, sd_bus_message
*reply
, DnsResourceRecord
*rr
) {
698 _cleanup_(dns_resource_record_unrefp
) DnsResourceRecord
*canonical
= NULL
;
699 _cleanup_free_
char *normalized
= NULL
;
708 if (rr
->key
->type
!= DNS_TYPE_SRV
)
711 if ((q
->flags
& SD_RESOLVED_NO_ADDRESS
) == 0) {
712 /* First, let's see if we could find an appropriate A or AAAA
713 * record for the SRV record */
714 LIST_FOREACH(auxiliary_queries
, aux
, q
->auxiliary_queries
) {
715 DnsResourceRecord
*zz
;
716 DnsQuestion
*question
;
718 if (aux
->state
!= DNS_TRANSACTION_SUCCESS
)
720 if (aux
->auxiliary_result
!= 0)
723 question
= dns_query_question_for_protocol(aux
, aux
->answer_protocol
);
725 r
= dns_name_equal(dns_question_first_name(question
), rr
->srv
.name
);
731 DNS_ANSWER_FOREACH(zz
, aux
->answer
) {
733 r
= dns_question_matches_rr(question
, zz
, NULL
);
739 canonical
= dns_resource_record_ref(zz
);
747 /* Is there are successful A/AAAA lookup for this SRV RR? If not, don't add it */
752 r
= sd_bus_message_open_container(reply
, 'r', "qqqsa(iiay)s");
756 r
= dns_name_normalize(rr
->srv
.name
, &normalized
);
760 r
= sd_bus_message_append(
763 rr
->srv
.priority
, rr
->srv
.weight
, rr
->srv
.port
, normalized
);
767 r
= sd_bus_message_open_container(reply
, 'a', "(iiay)");
771 if ((q
->flags
& SD_RESOLVED_NO_ADDRESS
) == 0) {
772 LIST_FOREACH(auxiliary_queries
, aux
, q
->auxiliary_queries
) {
773 DnsResourceRecord
*zz
;
774 DnsQuestion
*question
;
777 if (aux
->state
!= DNS_TRANSACTION_SUCCESS
)
779 if (aux
->auxiliary_result
!= 0)
782 question
= dns_query_question_for_protocol(aux
, aux
->answer_protocol
);
784 r
= dns_name_equal(dns_question_first_name(question
), rr
->srv
.name
);
790 DNS_ANSWER_FOREACH_IFINDEX(zz
, ifindex
, aux
->answer
) {
792 r
= dns_question_matches_rr(question
, zz
, NULL
);
798 r
= append_address(reply
, zz
, ifindex
);
805 r
= sd_bus_message_close_container(reply
);
810 normalized
= mfree(normalized
);
812 r
= dns_name_normalize(dns_resource_key_name(canonical
->key
), &normalized
);
817 /* Note that above we appended the hostname as encoded in the
818 * SRV, and here the canonical hostname this maps to. */
819 r
= sd_bus_message_append(reply
, "s", normalized
);
823 r
= sd_bus_message_close_container(reply
);
830 static int append_txt(sd_bus_message
*reply
, DnsResourceRecord
*rr
) {
838 if (rr
->key
->type
!= DNS_TYPE_TXT
)
841 LIST_FOREACH(items
, i
, rr
->txt
.items
) {
846 r
= sd_bus_message_append_array(reply
, 'y', i
->data
, i
->length
);
854 static void resolve_service_all_complete(DnsQuery
*q
) {
855 _cleanup_(dns_resource_record_unrefp
) DnsResourceRecord
*canonical
= NULL
;
856 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
857 _cleanup_free_
char *name
= NULL
, *type
= NULL
, *domain
= NULL
;
858 DnsQuestion
*question
;
859 DnsResourceRecord
*rr
;
866 if (q
->block_all_complete
> 0)
869 if ((q
->flags
& SD_RESOLVED_NO_ADDRESS
) == 0) {
870 DnsQuery
*bad
= NULL
;
871 bool have_success
= false;
873 LIST_FOREACH(auxiliary_queries
, aux
, q
->auxiliary_queries
) {
875 switch (aux
->state
) {
877 case DNS_TRANSACTION_PENDING
:
878 /* If an auxiliary query is still pending, let's wait */
881 case DNS_TRANSACTION_SUCCESS
:
882 if (aux
->auxiliary_result
== 0)
895 /* We can only return one error, hence pick the last error we encountered */
899 if (bad
->state
== DNS_TRANSACTION_SUCCESS
) {
900 assert(bad
->auxiliary_result
!= 0);
902 if (bad
->auxiliary_result
== -ELOOP
) {
903 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
));
907 r
= bad
->auxiliary_result
;
911 r
= reply_query_state(bad
);
916 r
= sd_bus_message_new_method_return(q
->request
, &reply
);
920 r
= sd_bus_message_open_container(reply
, 'a', "(qqqsa(iiay)s)");
924 question
= dns_query_question_for_protocol(q
, q
->answer_protocol
);
925 DNS_ANSWER_FOREACH(rr
, q
->answer
) {
926 r
= dns_question_matches_rr(question
, rr
, NULL
);
932 r
= append_srv(q
, reply
, rr
);
935 if (r
== 0) /* not an SRV record */
939 canonical
= dns_resource_record_ref(rr
);
945 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
));
949 r
= sd_bus_message_close_container(reply
);
953 r
= sd_bus_message_open_container(reply
, 'a', "ay");
957 DNS_ANSWER_FOREACH(rr
, q
->answer
) {
958 r
= dns_question_matches_rr(question
, rr
, NULL
);
964 r
= append_txt(reply
, rr
);
969 r
= sd_bus_message_close_container(reply
);
974 r
= dns_service_split(dns_resource_key_name(canonical
->key
), &name
, &type
, &domain
);
978 r
= sd_bus_message_append(
982 SD_RESOLVED_FLAGS_MAKE(q
->answer_protocol
, q
->answer_family
, dns_query_fully_authenticated(q
)));
986 r
= sd_bus_send(q
->manager
->bus
, reply
, NULL
);
990 log_error_errno(r
, "Failed to send service reply: %m");
991 sd_bus_reply_method_errno(q
->request
, r
, NULL
);
997 static void resolve_service_hostname_complete(DnsQuery
*q
) {
1001 assert(q
->auxiliary_for
);
1003 if (q
->state
!= DNS_TRANSACTION_SUCCESS
) {
1004 resolve_service_all_complete(q
->auxiliary_for
);
1008 r
= dns_query_process_cname(q
);
1009 if (r
== DNS_QUERY_RESTARTED
) /* This was a cname, and the query was restarted. */
1012 /* This auxiliary lookup is finished or failed, let's see if all are finished now. */
1013 q
->auxiliary_result
= r
;
1014 resolve_service_all_complete(q
->auxiliary_for
);
1017 static int resolve_service_hostname(DnsQuery
*q
, DnsResourceRecord
*rr
, int ifindex
) {
1018 _cleanup_(dns_question_unrefp
) DnsQuestion
*question
= NULL
;
1025 assert(rr
->key
->type
== DNS_TYPE_SRV
);
1027 /* OK, we found an SRV record for the service. Let's resolve
1028 * the hostname included in it */
1030 r
= dns_question_new_address(&question
, q
->request_family
, rr
->srv
.name
, false);
1034 r
= dns_query_new(q
->manager
, &aux
, question
, question
, ifindex
, q
->flags
|SD_RESOLVED_NO_SEARCH
);
1038 aux
->request_family
= q
->request_family
;
1039 aux
->complete
= resolve_service_hostname_complete
;
1041 r
= dns_query_make_auxiliary(aux
, q
);
1043 /* Too many auxiliary lookups? If so, don't complain,
1044 * let's just not add this one, we already have more
1047 dns_query_free(aux
);
1053 /* Note that auxiliary queries do not track the original bus
1054 * client, only the primary request does that. */
1056 r
= dns_query_go(aux
);
1063 dns_query_free(aux
);
1067 static void bus_method_resolve_service_complete(DnsQuery
*q
) {
1068 bool has_root_domain
= false;
1069 DnsResourceRecord
*rr
;
1070 DnsQuestion
*question
;
1076 if (q
->state
!= DNS_TRANSACTION_SUCCESS
) {
1077 r
= reply_query_state(q
);
1081 r
= dns_query_process_cname(q
);
1083 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
));
1088 if (r
== DNS_QUERY_RESTARTED
) /* This was a cname, and the query was restarted. */
1091 question
= dns_query_question_for_protocol(q
, q
->answer_protocol
);
1093 DNS_ANSWER_FOREACH_IFINDEX(rr
, ifindex
, q
->answer
) {
1094 r
= dns_question_matches_rr(question
, rr
, NULL
);
1100 if (rr
->key
->type
!= DNS_TYPE_SRV
)
1103 if (dns_name_is_root(rr
->srv
.name
)) {
1104 has_root_domain
= true;
1108 if ((q
->flags
& SD_RESOLVED_NO_ADDRESS
) == 0) {
1109 q
->block_all_complete
++;
1110 r
= resolve_service_hostname(q
, rr
, ifindex
);
1111 q
->block_all_complete
--;
1120 if (has_root_domain
&& found
<= 0) {
1121 /* If there's exactly one SRV RR and it uses
1122 * the root domain as host name, then the
1123 * service is explicitly not offered on the
1124 * domain. Report this as a recognizable
1125 * error. See RFC 2782, Section "Usage
1127 r
= sd_bus_reply_method_errorf(q
->request
, BUS_ERROR_NO_SUCH_SERVICE
, "'%s' does not provide the requested service", dns_query_string(q
));
1132 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
));
1136 /* Maybe we are already finished? check now... */
1137 resolve_service_all_complete(q
);
1142 log_error_errno(r
, "Failed to send service reply: %m");
1143 sd_bus_reply_method_errno(q
->request
, r
, NULL
);
1149 static int bus_method_resolve_service(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1150 _cleanup_(dns_question_unrefp
) DnsQuestion
*question_idna
= NULL
, *question_utf8
= NULL
;
1151 const char *name
, *type
, *domain
;
1152 Manager
*m
= userdata
;
1153 int family
, ifindex
;
1161 assert_cc(sizeof(int) == sizeof(int32_t));
1163 r
= sd_bus_message_read(message
, "isssit", &ifindex
, &name
, &type
, &domain
, &family
, &flags
);
1167 if (!IN_SET(family
, AF_INET
, AF_INET6
, AF_UNSPEC
))
1168 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Unknown address family %i", family
);
1172 else if (!dns_service_name_is_valid(name
))
1173 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid service name '%s'", name
);
1177 else if (!dns_srv_type_is_valid(type
))
1178 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid SRV service type '%s'", type
);
1180 r
= dns_name_is_valid(domain
);
1184 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid domain '%s'", domain
);
1187 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Service name cannot be specified without service type.");
1189 r
= check_ifindex_flags(ifindex
, &flags
, SD_RESOLVED_NO_TXT
|SD_RESOLVED_NO_ADDRESS
, error
);
1193 r
= dns_question_new_service(&question_utf8
, name
, type
, domain
, !(flags
& SD_RESOLVED_NO_TXT
), false);
1197 r
= dns_question_new_service(&question_idna
, name
, type
, domain
, !(flags
& SD_RESOLVED_NO_TXT
), true);
1201 r
= dns_query_new(m
, &q
, question_utf8
, question_idna
, ifindex
, flags
|SD_RESOLVED_NO_SEARCH
);
1205 q
->request
= sd_bus_message_ref(message
);
1206 q
->request_family
= family
;
1207 q
->complete
= bus_method_resolve_service_complete
;
1209 r
= dns_query_bus_track(q
, message
);
1213 r
= dns_query_go(q
);
1224 int bus_dns_server_append(sd_bus_message
*reply
, DnsServer
*s
, bool with_ifindex
) {
1230 r
= sd_bus_message_open_container(reply
, 'r', with_ifindex
? "iiay" : "iay");
1235 r
= sd_bus_message_append(reply
, "i", dns_server_ifindex(s
));
1240 r
= sd_bus_message_append(reply
, "i", s
->family
);
1244 r
= sd_bus_message_append_array(reply
, 'y', &s
->address
, FAMILY_ADDRESS_SIZE(s
->family
));
1248 return sd_bus_message_close_container(reply
);
1251 static int bus_property_get_dns_servers(
1254 const char *interface
,
1255 const char *property
,
1256 sd_bus_message
*reply
,
1258 sd_bus_error
*error
) {
1260 Manager
*m
= userdata
;
1270 r
= sd_bus_message_open_container(reply
, 'a', "(iiay)");
1274 LIST_FOREACH(servers
, s
, m
->dns_servers
) {
1275 r
= bus_dns_server_append(reply
, s
, true);
1282 HASHMAP_FOREACH(l
, m
->links
, i
) {
1283 LIST_FOREACH(servers
, s
, l
->dns_servers
) {
1284 r
= bus_dns_server_append(reply
, s
, true);
1292 LIST_FOREACH(servers
, s
, m
->fallback_dns_servers
) {
1293 r
= bus_dns_server_append(reply
, s
, true);
1299 return sd_bus_message_close_container(reply
);
1302 static int bus_property_get_domains(
1305 const char *interface
,
1306 const char *property
,
1307 sd_bus_message
*reply
,
1309 sd_bus_error
*error
) {
1311 Manager
*m
= userdata
;
1320 r
= sd_bus_message_open_container(reply
, 'a', "(isb)");
1324 LIST_FOREACH(domains
, d
, m
->search_domains
) {
1325 r
= sd_bus_message_append(reply
, "(isb)", 0, d
->name
, d
->route_only
);
1330 HASHMAP_FOREACH(l
, m
->links
, i
) {
1331 LIST_FOREACH(domains
, d
, l
->search_domains
) {
1332 r
= sd_bus_message_append(reply
, "(isb)", l
->ifindex
, d
->name
, d
->route_only
);
1338 return sd_bus_message_close_container(reply
);
1341 static int bus_property_get_transaction_statistics(
1344 const char *interface
,
1345 const char *property
,
1346 sd_bus_message
*reply
,
1348 sd_bus_error
*error
) {
1350 Manager
*m
= userdata
;
1355 return sd_bus_message_append(reply
, "(tt)",
1356 (uint64_t) hashmap_size(m
->dns_transactions
),
1357 (uint64_t) m
->n_transactions_total
);
1360 static int bus_property_get_cache_statistics(
1363 const char *interface
,
1364 const char *property
,
1365 sd_bus_message
*reply
,
1367 sd_bus_error
*error
) {
1369 uint64_t size
= 0, hit
= 0, miss
= 0;
1370 Manager
*m
= userdata
;
1376 LIST_FOREACH(scopes
, s
, m
->dns_scopes
) {
1377 size
+= dns_cache_size(&s
->cache
);
1378 hit
+= s
->cache
.n_hit
;
1379 miss
+= s
->cache
.n_miss
;
1382 return sd_bus_message_append(reply
, "(ttt)", size
, hit
, miss
);
1385 static int bus_property_get_dnssec_statistics(
1388 const char *interface
,
1389 const char *property
,
1390 sd_bus_message
*reply
,
1392 sd_bus_error
*error
) {
1394 Manager
*m
= userdata
;
1399 return sd_bus_message_append(reply
, "(tttt)",
1400 (uint64_t) m
->n_dnssec_verdict
[DNSSEC_SECURE
],
1401 (uint64_t) m
->n_dnssec_verdict
[DNSSEC_INSECURE
],
1402 (uint64_t) m
->n_dnssec_verdict
[DNSSEC_BOGUS
],
1403 (uint64_t) m
->n_dnssec_verdict
[DNSSEC_INDETERMINATE
]);
1406 static int bus_property_get_dnssec_supported(
1409 const char *interface
,
1410 const char *property
,
1411 sd_bus_message
*reply
,
1413 sd_bus_error
*error
) {
1415 Manager
*m
= userdata
;
1420 return sd_bus_message_append(reply
, "b", manager_dnssec_supported(m
));
1423 static int bus_property_get_ntas(
1426 const char *interface
,
1427 const char *property
,
1428 sd_bus_message
*reply
,
1430 sd_bus_error
*error
) {
1432 Manager
*m
= userdata
;
1440 r
= sd_bus_message_open_container(reply
, 'a', "s");
1444 SET_FOREACH(domain
, m
->trust_anchor
.negative_by_name
, i
) {
1445 r
= sd_bus_message_append(reply
, "s", domain
);
1450 return sd_bus_message_close_container(reply
);
1453 static BUS_DEFINE_PROPERTY_GET_ENUM(bus_property_get_dns_stub_listener_mode
, dns_stub_listener_mode
, DnsStubListenerMode
);
1455 static int bus_method_reset_statistics(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1456 Manager
*m
= userdata
;
1462 LIST_FOREACH(scopes
, s
, m
->dns_scopes
)
1463 s
->cache
.n_hit
= s
->cache
.n_miss
= 0;
1465 m
->n_transactions_total
= 0;
1466 zero(m
->n_dnssec_verdict
);
1468 return sd_bus_reply_method_return(message
, NULL
);
1471 static int get_any_link(Manager
*m
, int ifindex
, Link
**ret
, sd_bus_error
*error
) {
1478 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid interface index");
1480 l
= hashmap_get(m
->links
, INT_TO_PTR(ifindex
));
1482 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_LINK
, "Link %i not known", ifindex
);
1488 static int call_link_method(Manager
*m
, sd_bus_message
*message
, sd_bus_message_handler_t handler
, sd_bus_error
*error
) {
1496 assert_cc(sizeof(int) == sizeof(int32_t));
1497 r
= sd_bus_message_read(message
, "i", &ifindex
);
1501 r
= get_any_link(m
, ifindex
, &l
, error
);
1505 return handler(message
, l
, error
);
1508 static int bus_method_set_link_dns_servers(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1509 return call_link_method(userdata
, message
, bus_link_method_set_dns_servers
, error
);
1512 static int bus_method_set_link_domains(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1513 return call_link_method(userdata
, message
, bus_link_method_set_domains
, error
);
1516 static int bus_method_set_link_llmnr(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1517 return call_link_method(userdata
, message
, bus_link_method_set_llmnr
, error
);
1520 static int bus_method_set_link_mdns(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1521 return call_link_method(userdata
, message
, bus_link_method_set_mdns
, error
);
1524 static int bus_method_set_link_dnssec(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1525 return call_link_method(userdata
, message
, bus_link_method_set_dnssec
, error
);
1528 static int bus_method_set_link_dnssec_negative_trust_anchors(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1529 return call_link_method(userdata
, message
, bus_link_method_set_dnssec_negative_trust_anchors
, error
);
1532 static int bus_method_revert_link(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1533 return call_link_method(userdata
, message
, bus_link_method_revert
, error
);
1536 static int bus_method_get_link(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1537 _cleanup_free_
char *p
= NULL
;
1538 Manager
*m
= userdata
;
1545 assert_cc(sizeof(int) == sizeof(int32_t));
1546 r
= sd_bus_message_read(message
, "i", &ifindex
);
1550 r
= get_any_link(m
, ifindex
, &l
, error
);
1554 p
= link_bus_path(l
);
1558 return sd_bus_reply_method_return(message
, "o", p
);
1561 static int bus_method_flush_caches(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1562 Manager
*m
= userdata
;
1567 manager_flush_caches(m
);
1569 return sd_bus_reply_method_return(message
, NULL
);
1572 static const sd_bus_vtable resolve_vtable
[] = {
1573 SD_BUS_VTABLE_START(0),
1574 SD_BUS_PROPERTY("LLMNRHostname", "s", NULL
, offsetof(Manager
, llmnr_hostname
), 0),
1575 SD_BUS_PROPERTY("DNS", "a(iiay)", bus_property_get_dns_servers
, 0, 0),
1576 SD_BUS_PROPERTY("Domains", "a(isb)", bus_property_get_domains
, 0, 0),
1577 SD_BUS_PROPERTY("TransactionStatistics", "(tt)", bus_property_get_transaction_statistics
, 0, 0),
1578 SD_BUS_PROPERTY("CacheStatistics", "(ttt)", bus_property_get_cache_statistics
, 0, 0),
1579 SD_BUS_PROPERTY("DNSSECStatistics", "(tttt)", bus_property_get_dnssec_statistics
, 0, 0),
1580 SD_BUS_PROPERTY("DNSSECSupported", "b", bus_property_get_dnssec_supported
, 0, 0),
1581 SD_BUS_PROPERTY("DNSSECNegativeTrustAnchors", "as", bus_property_get_ntas
, 0, 0),
1582 SD_BUS_PROPERTY("DNSStubListener", "s", bus_property_get_dns_stub_listener_mode
, offsetof(Manager
, dns_stub_listener_mode
), 0),
1584 SD_BUS_METHOD("ResolveHostname", "isit", "a(iiay)st", bus_method_resolve_hostname
, SD_BUS_VTABLE_UNPRIVILEGED
),
1585 SD_BUS_METHOD("ResolveAddress", "iiayt", "a(is)t", bus_method_resolve_address
, SD_BUS_VTABLE_UNPRIVILEGED
),
1586 SD_BUS_METHOD("ResolveRecord", "isqqt", "a(iqqay)t", bus_method_resolve_record
, SD_BUS_VTABLE_UNPRIVILEGED
),
1587 SD_BUS_METHOD("ResolveService", "isssit", "a(qqqsa(iiay)s)aayssst", bus_method_resolve_service
, SD_BUS_VTABLE_UNPRIVILEGED
),
1588 SD_BUS_METHOD("ResetStatistics", NULL
, NULL
, bus_method_reset_statistics
, 0),
1589 SD_BUS_METHOD("FlushCaches", NULL
, NULL
, bus_method_flush_caches
, 0),
1590 SD_BUS_METHOD("GetLink", "i", "o", bus_method_get_link
, SD_BUS_VTABLE_UNPRIVILEGED
),
1591 SD_BUS_METHOD("SetLinkDNS", "ia(iay)", NULL
, bus_method_set_link_dns_servers
, 0),
1592 SD_BUS_METHOD("SetLinkDomains", "ia(sb)", NULL
, bus_method_set_link_domains
, 0),
1593 SD_BUS_METHOD("SetLinkLLMNR", "is", NULL
, bus_method_set_link_llmnr
, 0),
1594 SD_BUS_METHOD("SetLinkMulticastDNS", "is", NULL
, bus_method_set_link_mdns
, 0),
1595 SD_BUS_METHOD("SetLinkDNSSEC", "is", NULL
, bus_method_set_link_dnssec
, 0),
1596 SD_BUS_METHOD("SetLinkDNSSECNegativeTrustAnchors", "ias", NULL
, bus_method_set_link_dnssec_negative_trust_anchors
, 0),
1597 SD_BUS_METHOD("RevertLink", "i", NULL
, bus_method_revert_link
, 0),
1602 static int on_bus_retry(sd_event_source
*s
, usec_t usec
, void *userdata
) {
1603 Manager
*m
= userdata
;
1608 m
->bus_retry_event_source
= sd_event_source_unref(m
->bus_retry_event_source
);
1610 manager_connect_bus(m
);
1614 static int match_prepare_for_sleep(sd_bus_message
*message
, void *userdata
, sd_bus_error
*ret_error
) {
1615 Manager
*m
= userdata
;
1621 r
= sd_bus_message_read(message
, "b", &b
);
1623 log_debug_errno(r
, "Failed to parse PrepareForSleep signal: %m");
1630 log_debug("Coming back from suspend, verifying all RRs...");
1632 manager_verify_all(m
);
1636 int manager_connect_bus(Manager
*m
) {
1644 r
= sd_bus_default_system(&m
->bus
);
1646 /* We failed to connect? Yuck, we must be in early
1647 * boot. Let's try in 5s again. As soon as we have
1648 * kdbus we can stop doing this... */
1650 log_debug_errno(r
, "Failed to connect to bus, trying again in 5s: %m");
1652 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
);
1654 return log_error_errno(r
, "Failed to install bus reconnect time event: %m");
1656 (void) sd_event_source_set_description(m
->bus_retry_event_source
, "bus-retry");
1660 r
= sd_bus_add_object_vtable(m
->bus
, NULL
, "/org/freedesktop/resolve1", "org.freedesktop.resolve1.Manager", resolve_vtable
, m
);
1662 return log_error_errno(r
, "Failed to register object: %m");
1664 r
= sd_bus_add_fallback_vtable(m
->bus
, NULL
, "/org/freedesktop/resolve1/link", "org.freedesktop.resolve1.Link", link_vtable
, link_object_find
, m
);
1666 return log_error_errno(r
, "Failed to register link objects: %m");
1668 r
= sd_bus_add_node_enumerator(m
->bus
, NULL
, "/org/freedesktop/resolve1/link", link_node_enumerator
, m
);
1670 return log_error_errno(r
, "Failed to register link enumerator: %m");
1672 r
= sd_bus_request_name(m
->bus
, "org.freedesktop.resolve1", 0);
1674 return log_error_errno(r
, "Failed to register name: %m");
1676 r
= sd_bus_attach_event(m
->bus
, m
->event
, 0);
1678 return log_error_errno(r
, "Failed to attach bus to event loop: %m");
1680 r
= sd_bus_add_match(m
->bus
, &m
->prepare_for_sleep_slot
,
1682 "sender='org.freedesktop.login1',"
1683 "interface='org.freedesktop.login1.Manager',"
1684 "member='PrepareForSleep',"
1685 "path='/org/freedesktop/login1'",
1686 match_prepare_for_sleep
,
1689 log_error_errno(r
, "Failed to add match for PrepareForSleep: %m");