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 "bus-common-errors.h"
25 #include "dns-domain.h"
26 #include "resolved-bus.h"
27 #include "resolved-def.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 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 /* Return the precise spelling and uppercasing and CNAME target reported by the server */
205 r
= sd_bus_message_append(
207 DNS_RESOURCE_KEY_NAME(canonical
->key
),
208 SD_RESOLVED_FLAGS_MAKE(q
->answer_protocol
, q
->answer_family
, q
->answer_authenticated
));
212 r
= sd_bus_send(q
->manager
->bus
, reply
, NULL
);
216 log_error_errno(r
, "Failed to send hostname reply: %m");
217 sd_bus_reply_method_errno(q
->request
, r
, NULL
);
223 static int check_ifindex_flags(int ifindex
, uint64_t *flags
, uint64_t ok
, sd_bus_error
*error
) {
227 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid interface index");
229 if (*flags
& ~(SD_RESOLVED_PROTOCOLS_ALL
|SD_RESOLVED_NO_CNAME
|ok
))
230 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid flags parameter");
232 if ((*flags
& SD_RESOLVED_PROTOCOLS_ALL
) == 0) /* If no protocol is enabled, enable all */
233 *flags
|= SD_RESOLVED_PROTOCOLS_ALL
;
238 static int bus_method_resolve_hostname(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
239 _cleanup_(dns_question_unrefp
) DnsQuestion
*question_idna
= NULL
, *question_utf8
= NULL
;
240 Manager
*m
= userdata
;
241 const char *hostname
;
250 assert_cc(sizeof(int) == sizeof(int32_t));
252 r
= sd_bus_message_read(message
, "isit", &ifindex
, &hostname
, &family
, &flags
);
256 if (!IN_SET(family
, AF_INET
, AF_INET6
, AF_UNSPEC
))
257 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Unknown address family %i", family
);
259 r
= dns_name_is_valid(hostname
);
263 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid hostname '%s'", hostname
);
265 r
= check_ifindex_flags(ifindex
, &flags
, SD_RESOLVED_NO_SEARCH
, error
);
269 r
= dns_question_new_address(&question_utf8
, family
, hostname
, false);
273 r
= dns_question_new_address(&question_idna
, family
, hostname
, true);
277 r
= dns_query_new(m
, &q
, question_utf8
, question_idna
, ifindex
, flags
);
281 q
->request
= sd_bus_message_ref(message
);
282 q
->request_family
= family
;
283 q
->complete
= bus_method_resolve_hostname_complete
;
284 q
->suppress_unroutable_family
= family
== AF_UNSPEC
;
286 r
= dns_query_bus_track(q
, message
);
301 static void bus_method_resolve_address_complete(DnsQuery
*q
) {
302 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
303 DnsQuestion
*question
;
304 DnsResourceRecord
*rr
;
310 if (q
->state
!= DNS_TRANSACTION_SUCCESS
) {
311 r
= reply_query_state(q
);
315 r
= dns_query_process_cname(q
);
317 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
));
322 if (r
== DNS_QUERY_RESTARTED
) /* This was a cname, and the query was restarted. */
325 r
= sd_bus_message_new_method_return(q
->request
, &reply
);
329 r
= sd_bus_message_open_container(reply
, 'a', "(is)");
333 question
= dns_query_question_for_protocol(q
, q
->answer_protocol
);
335 DNS_ANSWER_FOREACH_IFINDEX(rr
, ifindex
, q
->answer
) {
336 r
= dns_question_matches_rr(question
, rr
, NULL
);
342 r
= sd_bus_message_append(reply
, "(is)", ifindex
, rr
->ptr
.name
);
350 _cleanup_free_
char *ip
= NULL
;
352 in_addr_to_string(q
->request_family
, &q
->request_address
, &ip
);
353 r
= sd_bus_reply_method_errorf(q
->request
, BUS_ERROR_NO_SUCH_RR
, "Address '%s' does not have any RR of requested type", strna(ip
));
357 r
= sd_bus_message_close_container(reply
);
361 r
= sd_bus_message_append(reply
, "t", SD_RESOLVED_FLAGS_MAKE(q
->answer_protocol
, q
->answer_family
, q
->answer_authenticated
));
365 r
= sd_bus_send(q
->manager
->bus
, reply
, NULL
);
369 log_error_errno(r
, "Failed to send address reply: %m");
370 sd_bus_reply_method_errno(q
->request
, r
, NULL
);
376 static int bus_method_resolve_address(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
377 _cleanup_(dns_question_unrefp
) DnsQuestion
*question
= NULL
;
378 Manager
*m
= userdata
;
389 assert_cc(sizeof(int) == sizeof(int32_t));
391 r
= sd_bus_message_read(message
, "ii", &ifindex
, &family
);
395 if (!IN_SET(family
, AF_INET
, AF_INET6
))
396 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Unknown address family %i", family
);
398 r
= sd_bus_message_read_array(message
, 'y', &d
, &sz
);
402 if (sz
!= FAMILY_ADDRESS_SIZE(family
))
403 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid address size");
405 r
= sd_bus_message_read(message
, "t", &flags
);
409 r
= check_ifindex_flags(ifindex
, &flags
, 0, error
);
413 r
= dns_question_new_reverse(&question
, family
, d
);
417 r
= dns_query_new(m
, &q
, question
, question
, ifindex
, flags
|SD_RESOLVED_NO_SEARCH
);
421 q
->request
= sd_bus_message_ref(message
);
422 q
->request_family
= family
;
423 memcpy(&q
->request_address
, d
, sz
);
424 q
->complete
= bus_method_resolve_address_complete
;
426 r
= dns_query_bus_track(q
, message
);
441 static int bus_message_append_rr(sd_bus_message
*m
, DnsResourceRecord
*rr
, int ifindex
) {
447 r
= sd_bus_message_open_container(m
, 'r', "iqqay");
451 r
= sd_bus_message_append(m
, "iqq",
458 r
= dns_resource_record_to_wire_format(rr
, false);
462 r
= sd_bus_message_append_array(m
, 'y', rr
->wire_format
, rr
->wire_format_size
);
466 return sd_bus_message_close_container(m
);
469 static void bus_method_resolve_record_complete(DnsQuery
*q
) {
470 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
471 DnsResourceRecord
*rr
;
472 DnsQuestion
*question
;
479 if (q
->state
!= DNS_TRANSACTION_SUCCESS
) {
480 r
= reply_query_state(q
);
484 r
= dns_query_process_cname(q
);
486 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
));
491 if (r
== DNS_QUERY_RESTARTED
) /* This was a cname, and the query was restarted. */
494 r
= sd_bus_message_new_method_return(q
->request
, &reply
);
498 r
= sd_bus_message_open_container(reply
, 'a', "(iqqay)");
502 question
= dns_query_question_for_protocol(q
, q
->answer_protocol
);
504 DNS_ANSWER_FOREACH_IFINDEX(rr
, ifindex
, q
->answer
) {
505 r
= dns_question_matches_rr(question
, rr
, NULL
);
511 r
= bus_message_append_rr(reply
, rr
, ifindex
);
519 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
));
523 r
= sd_bus_message_close_container(reply
);
527 r
= sd_bus_message_append(reply
, "t", SD_RESOLVED_FLAGS_MAKE(q
->answer_protocol
, q
->answer_family
, q
->answer_authenticated
));
531 r
= sd_bus_send(q
->manager
->bus
, reply
, NULL
);
535 log_error_errno(r
, "Failed to send record reply: %m");
536 sd_bus_reply_method_errno(q
->request
, r
, NULL
);
542 static int bus_method_resolve_record(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
543 _cleanup_(dns_resource_key_unrefp
) DnsResourceKey
*key
= NULL
;
544 _cleanup_(dns_question_unrefp
) DnsQuestion
*question
= NULL
;
545 Manager
*m
= userdata
;
546 uint16_t class, type
;
555 assert_cc(sizeof(int) == sizeof(int32_t));
557 r
= sd_bus_message_read(message
, "isqqt", &ifindex
, &name
, &class, &type
, &flags
);
561 r
= dns_name_is_valid(name
);
565 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid name '%s'", name
);
567 if (!dns_type_is_valid_query(type
))
568 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Specified resource record type %" PRIu16
" may not be used in a query.", type
);
569 if (dns_type_is_obsolete(type
))
570 return sd_bus_error_setf(error
, SD_BUS_ERROR_NOT_SUPPORTED
, "Specified DNS resource record type %" PRIu16
" is obsolete.", type
);
572 r
= check_ifindex_flags(ifindex
, &flags
, 0, error
);
576 question
= dns_question_new(1);
580 key
= dns_resource_key_new(class, type
, name
);
584 r
= dns_question_add(question
, key
);
588 r
= dns_query_new(m
, &q
, question
, question
, ifindex
, flags
|SD_RESOLVED_NO_SEARCH
);
592 q
->request
= sd_bus_message_ref(message
);
593 q
->complete
= bus_method_resolve_record_complete
;
595 r
= dns_query_bus_track(q
, message
);
610 static int append_srv(DnsQuery
*q
, sd_bus_message
*reply
, DnsResourceRecord
*rr
) {
611 _cleanup_(dns_resource_record_unrefp
) DnsResourceRecord
*canonical
= NULL
;
620 if (rr
->key
->type
!= DNS_TYPE_SRV
)
623 if ((q
->flags
& SD_RESOLVED_NO_ADDRESS
) == 0) {
624 /* First, let's see if we could find an appropriate A or AAAA
625 * record for the SRV record */
626 LIST_FOREACH(auxiliary_queries
, aux
, q
->auxiliary_queries
) {
627 DnsResourceRecord
*zz
;
628 DnsQuestion
*question
;
630 if (aux
->state
!= DNS_TRANSACTION_SUCCESS
)
632 if (aux
->auxiliary_result
!= 0)
635 question
= dns_query_question_for_protocol(aux
, aux
->answer_protocol
);
637 r
= dns_name_equal(dns_question_first_name(question
), rr
->srv
.name
);
643 DNS_ANSWER_FOREACH(zz
, aux
->answer
) {
645 r
= dns_question_matches_rr(question
, zz
, NULL
);
651 canonical
= dns_resource_record_ref(zz
);
659 /* Is there are successful A/AAAA lookup for this SRV RR? If not, don't add it */
664 r
= sd_bus_message_open_container(reply
, 'r', "qqqsa(iiay)s");
668 r
= sd_bus_message_append(
671 rr
->srv
.priority
, rr
->srv
.weight
, rr
->srv
.port
, rr
->srv
.name
);
675 r
= sd_bus_message_open_container(reply
, 'a', "(iiay)");
679 if ((q
->flags
& SD_RESOLVED_NO_ADDRESS
) == 0) {
680 LIST_FOREACH(auxiliary_queries
, aux
, q
->auxiliary_queries
) {
681 DnsResourceRecord
*zz
;
682 DnsQuestion
*question
;
685 if (aux
->state
!= DNS_TRANSACTION_SUCCESS
)
687 if (aux
->auxiliary_result
!= 0)
690 question
= dns_query_question_for_protocol(aux
, aux
->answer_protocol
);
692 r
= dns_name_equal(dns_question_first_name(question
), rr
->srv
.name
);
698 DNS_ANSWER_FOREACH_IFINDEX(zz
, ifindex
, aux
->answer
) {
700 r
= dns_question_matches_rr(question
, zz
, NULL
);
706 r
= append_address(reply
, zz
, ifindex
);
713 r
= sd_bus_message_close_container(reply
);
717 /* Note that above we appended the hostname as encoded in the
718 * SRV, and here the canonical hostname this maps to. */
719 r
= sd_bus_message_append(reply
, "s", canonical
? DNS_RESOURCE_KEY_NAME(canonical
->key
) : rr
->srv
.name
);
723 r
= sd_bus_message_close_container(reply
);
730 static int append_txt(sd_bus_message
*reply
, DnsResourceRecord
*rr
) {
738 if (rr
->key
->type
!= DNS_TYPE_TXT
)
741 LIST_FOREACH(items
, i
, rr
->txt
.items
) {
746 r
= sd_bus_message_append_array(reply
, 'y', i
->data
, i
->length
);
754 static void resolve_service_all_complete(DnsQuery
*q
) {
755 _cleanup_(dns_resource_record_unrefp
) DnsResourceRecord
*canonical
= NULL
;
756 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
757 _cleanup_free_
char *name
= NULL
, *type
= NULL
, *domain
= NULL
;
758 DnsQuestion
*question
;
759 DnsResourceRecord
*rr
;
766 if (q
->block_all_complete
> 0)
769 if ((q
->flags
& SD_RESOLVED_NO_ADDRESS
) == 0) {
770 DnsQuery
*bad
= NULL
;
771 bool have_success
= false;
773 LIST_FOREACH(auxiliary_queries
, aux
, q
->auxiliary_queries
) {
775 switch (aux
->state
) {
777 case DNS_TRANSACTION_PENDING
:
778 /* If an auxiliary query is still pending, let's wait */
781 case DNS_TRANSACTION_SUCCESS
:
782 if (aux
->auxiliary_result
== 0)
795 /* We can only return one error, hence pick the last error we encountered */
799 if (bad
->state
== DNS_TRANSACTION_SUCCESS
) {
800 assert(bad
->auxiliary_result
!= 0);
802 if (bad
->auxiliary_result
== -ELOOP
) {
803 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
));
807 r
= bad
->auxiliary_result
;
811 r
= reply_query_state(bad
);
816 r
= sd_bus_message_new_method_return(q
->request
, &reply
);
820 r
= sd_bus_message_open_container(reply
, 'a', "(qqqsa(iiay)s)");
824 question
= dns_query_question_for_protocol(q
, q
->answer_protocol
);
825 DNS_ANSWER_FOREACH(rr
, q
->answer
) {
826 r
= dns_question_matches_rr(question
, rr
, NULL
);
832 r
= append_srv(q
, reply
, rr
);
835 if (r
== 0) /* not an SRV record */
839 canonical
= dns_resource_record_ref(rr
);
845 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
));
849 r
= sd_bus_message_close_container(reply
);
853 r
= sd_bus_message_open_container(reply
, 'a', "ay");
857 DNS_ANSWER_FOREACH(rr
, q
->answer
) {
858 r
= dns_question_matches_rr(question
, rr
, NULL
);
864 r
= append_txt(reply
, rr
);
869 r
= sd_bus_message_close_container(reply
);
874 r
= dns_service_split(DNS_RESOURCE_KEY_NAME(canonical
->key
), &name
, &type
, &domain
);
878 r
= sd_bus_message_append(
882 SD_RESOLVED_FLAGS_MAKE(q
->answer_protocol
, q
->answer_family
, q
->answer_authenticated
));
886 r
= sd_bus_send(q
->manager
->bus
, reply
, NULL
);
890 log_error_errno(r
, "Failed to send service reply: %m");
891 sd_bus_reply_method_errno(q
->request
, r
, NULL
);
897 static void resolve_service_hostname_complete(DnsQuery
*q
) {
901 assert(q
->auxiliary_for
);
903 if (q
->state
!= DNS_TRANSACTION_SUCCESS
) {
904 resolve_service_all_complete(q
->auxiliary_for
);
908 r
= dns_query_process_cname(q
);
909 if (r
== DNS_QUERY_RESTARTED
) /* This was a cname, and the query was restarted. */
912 /* This auxiliary lookup is finished or failed, let's see if all are finished now. */
913 q
->auxiliary_result
= r
;
914 resolve_service_all_complete(q
->auxiliary_for
);
917 static int resolve_service_hostname(DnsQuery
*q
, DnsResourceRecord
*rr
, int ifindex
) {
918 _cleanup_(dns_question_unrefp
) DnsQuestion
*question
= NULL
;
925 assert(rr
->key
->type
== DNS_TYPE_SRV
);
927 /* OK, we found an SRV record for the service. Let's resolve
928 * the hostname included in it */
930 r
= dns_question_new_address(&question
, q
->request_family
, rr
->srv
.name
, false);
934 r
= dns_query_new(q
->manager
, &aux
, question
, question
, ifindex
, q
->flags
|SD_RESOLVED_NO_SEARCH
);
938 aux
->request_family
= q
->request_family
;
939 aux
->complete
= resolve_service_hostname_complete
;
941 r
= dns_query_make_auxiliary(aux
, q
);
943 /* Too many auxiliary lookups? If so, don't complain,
944 * let's just not add this one, we already have more
953 /* Note that auxiliary queries do not track the original bus
954 * client, only the primary request does that. */
956 r
= dns_query_go(aux
);
967 static void bus_method_resolve_service_complete(DnsQuery
*q
) {
968 bool has_root_domain
= false;
969 DnsResourceRecord
*rr
;
970 DnsQuestion
*question
;
976 if (q
->state
!= DNS_TRANSACTION_SUCCESS
) {
977 r
= reply_query_state(q
);
981 r
= dns_query_process_cname(q
);
983 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
));
988 if (r
== DNS_QUERY_RESTARTED
) /* This was a cname, and the query was restarted. */
991 question
= dns_query_question_for_protocol(q
, q
->answer_protocol
);
993 DNS_ANSWER_FOREACH_IFINDEX(rr
, ifindex
, q
->answer
) {
994 r
= dns_question_matches_rr(question
, rr
, NULL
);
1000 if (rr
->key
->type
!= DNS_TYPE_SRV
)
1003 if (dns_name_is_root(rr
->srv
.name
)) {
1004 has_root_domain
= true;
1008 if ((q
->flags
& SD_RESOLVED_NO_ADDRESS
) == 0) {
1009 q
->block_all_complete
++;
1010 r
= resolve_service_hostname(q
, rr
, ifindex
);
1011 q
->block_all_complete
--;
1020 if (has_root_domain
&& found
<= 0) {
1021 /* If there's exactly one SRV RR and it uses
1022 * the root domain as host name, then the
1023 * service is explicitly not offered on the
1024 * domain. Report this as a recognizable
1025 * error. See RFC 2782, Section "Usage
1027 r
= sd_bus_reply_method_errorf(q
->request
, BUS_ERROR_NO_SUCH_SERVICE
, "'%s' does not provide the requested service", dns_query_string(q
));
1032 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
));
1036 /* Maybe we are already finished? check now... */
1037 resolve_service_all_complete(q
);
1042 log_error_errno(r
, "Failed to send service reply: %m");
1043 sd_bus_reply_method_errno(q
->request
, r
, NULL
);
1049 static int bus_method_resolve_service(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1050 _cleanup_(dns_question_unrefp
) DnsQuestion
*question_idna
= NULL
, *question_utf8
= NULL
;
1051 const char *name
, *type
, *domain
;
1052 _cleanup_free_
char *n
= NULL
;
1053 Manager
*m
= userdata
;
1054 int family
, ifindex
;
1062 assert_cc(sizeof(int) == sizeof(int32_t));
1064 r
= sd_bus_message_read(message
, "isssit", &ifindex
, &name
, &type
, &domain
, &family
, &flags
);
1068 if (!IN_SET(family
, AF_INET
, AF_INET6
, AF_UNSPEC
))
1069 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Unknown address family %i", family
);
1073 else if (!dns_service_name_is_valid(name
))
1074 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid service name '%s'", name
);
1078 else if (!dns_srv_type_is_valid(type
))
1079 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid SRV service type '%s'", type
);
1081 r
= dns_name_is_valid(domain
);
1085 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid domain '%s'", domain
);
1088 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Service name cannot be specified without service type.");
1090 r
= check_ifindex_flags(ifindex
, &flags
, SD_RESOLVED_NO_TXT
|SD_RESOLVED_NO_ADDRESS
, error
);
1094 r
= dns_question_new_service(&question_utf8
, name
, type
, domain
, !(flags
& SD_RESOLVED_NO_TXT
), false);
1098 r
= dns_question_new_service(&question_idna
, name
, type
, domain
, !(flags
& SD_RESOLVED_NO_TXT
), true);
1102 r
= dns_query_new(m
, &q
, question_utf8
, question_idna
, ifindex
, flags
|SD_RESOLVED_NO_SEARCH
);
1106 q
->request
= sd_bus_message_ref(message
);
1107 q
->request_family
= family
;
1108 q
->complete
= bus_method_resolve_service_complete
;
1110 r
= dns_query_bus_track(q
, message
);
1114 r
= dns_query_go(q
);
1125 int bus_dns_server_append(sd_bus_message
*reply
, DnsServer
*s
, bool with_ifindex
) {
1131 r
= sd_bus_message_open_container(reply
, 'r', with_ifindex
? "iiay" : "iay");
1136 r
= sd_bus_message_append(reply
, "i", s
->link
? s
->link
->ifindex
: 0);
1141 r
= sd_bus_message_append(reply
, "i", s
->family
);
1145 r
= sd_bus_message_append_array(reply
, 'y', &s
->address
, FAMILY_ADDRESS_SIZE(s
->family
));
1149 return sd_bus_message_close_container(reply
);
1152 static int bus_property_get_dns_servers(
1155 const char *interface
,
1156 const char *property
,
1157 sd_bus_message
*reply
,
1159 sd_bus_error
*error
) {
1161 Manager
*m
= userdata
;
1171 r
= sd_bus_message_open_container(reply
, 'a', "(iiay)");
1175 LIST_FOREACH(servers
, s
, m
->dns_servers
) {
1176 r
= bus_dns_server_append(reply
, s
, true);
1183 HASHMAP_FOREACH(l
, m
->links
, i
) {
1184 LIST_FOREACH(servers
, s
, l
->dns_servers
) {
1185 r
= bus_dns_server_append(reply
, s
, true);
1193 LIST_FOREACH(servers
, s
, m
->fallback_dns_servers
) {
1194 r
= bus_dns_server_append(reply
, s
, true);
1200 return sd_bus_message_close_container(reply
);
1203 static int bus_property_get_search_domains(
1206 const char *interface
,
1207 const char *property
,
1208 sd_bus_message
*reply
,
1210 sd_bus_error
*error
) {
1212 Manager
*m
= userdata
;
1221 r
= sd_bus_message_open_container(reply
, 'a', "(isb)");
1225 LIST_FOREACH(domains
, d
, m
->search_domains
) {
1226 r
= sd_bus_message_append(reply
, "(isb)", 0, d
->name
, d
->route_only
);
1231 HASHMAP_FOREACH(l
, m
->links
, i
) {
1232 LIST_FOREACH(domains
, d
, l
->search_domains
) {
1233 r
= sd_bus_message_append(reply
, "(isb)", l
->ifindex
, d
->name
, d
->route_only
);
1239 return sd_bus_message_close_container(reply
);
1242 static int bus_property_get_transaction_statistics(
1245 const char *interface
,
1246 const char *property
,
1247 sd_bus_message
*reply
,
1249 sd_bus_error
*error
) {
1251 Manager
*m
= userdata
;
1256 return sd_bus_message_append(reply
, "(tt)",
1257 (uint64_t) hashmap_size(m
->dns_transactions
),
1258 (uint64_t) m
->n_transactions_total
);
1261 static int bus_property_get_cache_statistics(
1264 const char *interface
,
1265 const char *property
,
1266 sd_bus_message
*reply
,
1268 sd_bus_error
*error
) {
1270 uint64_t size
= 0, hit
= 0, miss
= 0;
1271 Manager
*m
= userdata
;
1277 LIST_FOREACH(scopes
, s
, m
->dns_scopes
) {
1278 size
+= dns_cache_size(&s
->cache
);
1279 hit
+= s
->cache
.n_hit
;
1280 miss
+= s
->cache
.n_miss
;
1283 return sd_bus_message_append(reply
, "(ttt)", size
, hit
, miss
);
1286 static int bus_property_get_dnssec_statistics(
1289 const char *interface
,
1290 const char *property
,
1291 sd_bus_message
*reply
,
1293 sd_bus_error
*error
) {
1295 Manager
*m
= userdata
;
1300 return sd_bus_message_append(reply
, "(tttt)",
1301 (uint64_t) m
->n_dnssec_verdict
[DNSSEC_SECURE
],
1302 (uint64_t) m
->n_dnssec_verdict
[DNSSEC_INSECURE
],
1303 (uint64_t) m
->n_dnssec_verdict
[DNSSEC_BOGUS
],
1304 (uint64_t) m
->n_dnssec_verdict
[DNSSEC_INDETERMINATE
]);
1307 static int bus_property_get_dnssec_supported(
1310 const char *interface
,
1311 const char *property
,
1312 sd_bus_message
*reply
,
1314 sd_bus_error
*error
) {
1316 Manager
*m
= userdata
;
1321 return sd_bus_message_append(reply
, "b", manager_dnssec_supported(m
));
1324 static int bus_method_reset_statistics(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1325 Manager
*m
= userdata
;
1331 LIST_FOREACH(scopes
, s
, m
->dns_scopes
)
1332 s
->cache
.n_hit
= s
->cache
.n_miss
= 0;
1334 m
->n_transactions_total
= 0;
1335 zero(m
->n_dnssec_verdict
);
1337 return sd_bus_reply_method_return(message
, NULL
);
1340 static int get_any_link(Manager
*m
, int ifindex
, Link
**ret
, sd_bus_error
*error
) {
1347 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid interface index");
1349 l
= hashmap_get(m
->links
, INT_TO_PTR(ifindex
));
1351 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_LINK
, "Link %i not known", ifindex
);
1357 static int get_unmanaged_link(Manager
*m
, int ifindex
, Link
**ret
, sd_bus_error
*error
) {
1364 r
= get_any_link(m
, ifindex
, &l
, error
);
1368 if (l
->flags
& IFF_LOOPBACK
)
1369 return sd_bus_error_setf(error
, BUS_ERROR_LINK_BUSY
, "Link %s is loopback device.", l
->name
);
1371 return sd_bus_error_setf(error
, BUS_ERROR_LINK_BUSY
, "Link %s is managed.", l
->name
);
1377 static int call_link_method(Manager
*m
, sd_bus_message
*message
, sd_bus_message_handler_t handler
, sd_bus_error
*error
) {
1385 assert_cc(sizeof(int) == sizeof(int32_t));
1386 r
= sd_bus_message_read(message
, "i", &ifindex
);
1390 r
= get_unmanaged_link(m
, ifindex
, &l
, error
);
1394 return handler(message
, l
, error
);
1397 static int bus_method_set_link_dns_servers(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1398 return call_link_method(userdata
, message
, bus_link_method_set_dns_servers
, error
);
1401 static int bus_method_set_link_search_domains(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1402 return call_link_method(userdata
, message
, bus_link_method_set_search_domains
, error
);
1405 static int bus_method_set_link_llmnr(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1406 return call_link_method(userdata
, message
, bus_link_method_set_llmnr
, error
);
1409 static int bus_method_set_link_mdns(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1410 return call_link_method(userdata
, message
, bus_link_method_set_mdns
, error
);
1413 static int bus_method_set_link_dnssec(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1414 return call_link_method(userdata
, message
, bus_link_method_set_dnssec
, error
);
1417 static int bus_method_set_link_dnssec_negative_trust_anchors(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1418 return call_link_method(userdata
, message
, bus_link_method_set_dnssec_negative_trust_anchors
, error
);
1421 static int bus_method_revert_link(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1422 return call_link_method(userdata
, message
, bus_link_method_revert
, error
);
1425 static int bus_method_get_link(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1426 _cleanup_free_
char *p
= NULL
;
1427 Manager
*m
= userdata
;
1434 assert_cc(sizeof(int) == sizeof(int32_t));
1435 r
= sd_bus_message_read(message
, "i", &ifindex
);
1439 r
= get_any_link(m
, ifindex
, &l
, error
);
1443 p
= link_bus_path(l
);
1447 return sd_bus_reply_method_return(message
, "o", p
);
1450 static const sd_bus_vtable resolve_vtable
[] = {
1451 SD_BUS_VTABLE_START(0),
1452 SD_BUS_PROPERTY("LLMNRHostname", "s", NULL
, offsetof(Manager
, llmnr_hostname
), 0),
1453 SD_BUS_PROPERTY("DNS", "a(iiay)", bus_property_get_dns_servers
, 0, 0),
1454 SD_BUS_PROPERTY("SearchDomains", "a(isb)", bus_property_get_search_domains
, 0, 0),
1455 SD_BUS_PROPERTY("TransactionStatistics", "(tt)", bus_property_get_transaction_statistics
, 0, 0),
1456 SD_BUS_PROPERTY("CacheStatistics", "(ttt)", bus_property_get_cache_statistics
, 0, 0),
1457 SD_BUS_PROPERTY("DNSSECStatistics", "(tttt)", bus_property_get_dnssec_statistics
, 0, 0),
1458 SD_BUS_PROPERTY("DNSSECSupported", "b", bus_property_get_dnssec_supported
, 0, 0),
1460 SD_BUS_METHOD("ResolveHostname", "isit", "a(iiay)st", bus_method_resolve_hostname
, SD_BUS_VTABLE_UNPRIVILEGED
),
1461 SD_BUS_METHOD("ResolveAddress", "iiayt", "a(is)t", bus_method_resolve_address
, SD_BUS_VTABLE_UNPRIVILEGED
),
1462 SD_BUS_METHOD("ResolveRecord", "isqqt", "a(iqqay)t", bus_method_resolve_record
, SD_BUS_VTABLE_UNPRIVILEGED
),
1463 SD_BUS_METHOD("ResolveService", "isssit", "a(qqqsa(iiay)s)aayssst", bus_method_resolve_service
, SD_BUS_VTABLE_UNPRIVILEGED
),
1464 SD_BUS_METHOD("ResetStatistics", NULL
, NULL
, bus_method_reset_statistics
, 0),
1465 SD_BUS_METHOD("GetLink", "i", "o", bus_method_get_link
, SD_BUS_VTABLE_UNPRIVILEGED
),
1466 SD_BUS_METHOD("SetLinkDNS", "ia(iay)", NULL
, bus_method_set_link_dns_servers
, 0),
1467 SD_BUS_METHOD("SetLinkDomains", "ia(sb)", NULL
, bus_method_set_link_search_domains
, 0),
1468 SD_BUS_METHOD("SetLinkLLMNR", "is", NULL
, bus_method_set_link_llmnr
, 0),
1469 SD_BUS_METHOD("SetLinkMulticastDNS", "is", NULL
, bus_method_set_link_mdns
, 0),
1470 SD_BUS_METHOD("SetLinkDNSSEC", "is", NULL
, bus_method_set_link_dnssec
, 0),
1471 SD_BUS_METHOD("SetLinkDNSSECNegativeTrustAnchors", "ias", NULL
, bus_method_set_link_dnssec_negative_trust_anchors
, 0),
1472 SD_BUS_METHOD("RevertLink", "i", NULL
, bus_method_revert_link
, 0),
1477 static int on_bus_retry(sd_event_source
*s
, usec_t usec
, void *userdata
) {
1478 Manager
*m
= userdata
;
1483 m
->bus_retry_event_source
= sd_event_source_unref(m
->bus_retry_event_source
);
1485 manager_connect_bus(m
);
1489 static int match_prepare_for_sleep(sd_bus_message
*message
, void *userdata
, sd_bus_error
*ret_error
) {
1490 Manager
*m
= userdata
;
1496 r
= sd_bus_message_read(message
, "b", &b
);
1498 log_debug_errno(r
, "Failed to parse PrepareForSleep signal: %m");
1505 log_debug("Coming back from suspend, verifying all RRs...");
1507 manager_verify_all(m
);
1511 int manager_connect_bus(Manager
*m
) {
1519 r
= sd_bus_default_system(&m
->bus
);
1521 /* We failed to connect? Yuck, we must be in early
1522 * boot. Let's try in 5s again. As soon as we have
1523 * kdbus we can stop doing this... */
1525 log_debug_errno(r
, "Failed to connect to bus, trying again in 5s: %m");
1527 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
);
1529 return log_error_errno(r
, "Failed to install bus reconnect time event: %m");
1531 (void) sd_event_source_set_description(m
->bus_retry_event_source
, "bus-retry");
1535 r
= sd_bus_add_object_vtable(m
->bus
, NULL
, "/org/freedesktop/resolve1", "org.freedesktop.resolve1.Manager", resolve_vtable
, m
);
1537 return log_error_errno(r
, "Failed to register object: %m");
1539 r
= sd_bus_add_fallback_vtable(m
->bus
, NULL
, "/org/freedesktop/resolve1/link", "org.freedesktop.resolve1.Link", link_vtable
, link_object_find
, m
);
1541 return log_error_errno(r
, "Failed to register link objects: %m");
1543 r
= sd_bus_add_node_enumerator(m
->bus
, NULL
, "/org/freedesktop/resolve1/link", link_node_enumerator
, m
);
1545 return log_error_errno(r
, "Failed to register link enumerator: %m");
1547 r
= sd_bus_request_name(m
->bus
, "org.freedesktop.resolve1", 0);
1549 return log_error_errno(r
, "Failed to register name: %m");
1551 r
= sd_bus_attach_event(m
->bus
, m
->event
, 0);
1553 return log_error_errno(r
, "Failed to attach bus to event loop: %m");
1555 r
= sd_bus_add_match(m
->bus
, &m
->prepare_for_sleep_slot
,
1557 "sender='org.freedesktop.login1',"
1558 "interface='org.freedesktop.login1.Manager',"
1559 "member='PrepareForSleep',"
1560 "path='/org/freedesktop/login1'",
1561 match_prepare_for_sleep
,
1564 log_error_errno(r
, "Failed to add match for PrepareForSleep: %m");