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"
29 static int reply_query_state(DnsQuery
*q
) {
30 _cleanup_free_
char *ip
= NULL
;
34 if (q
->request_address_valid
) {
35 r
= in_addr_to_string(q
->request_family
, &q
->request_address
, &ip
);
41 name
= dns_question_first_name(q
->question
);
45 case DNS_TRANSACTION_NO_SERVERS
:
46 return sd_bus_reply_method_errorf(q
->request
, BUS_ERROR_NO_NAME_SERVERS
, "No appropriate name servers or networks for name found");
48 case DNS_TRANSACTION_TIMEOUT
:
49 return sd_bus_reply_method_errorf(q
->request
, SD_BUS_ERROR_TIMEOUT
, "Query timed out");
51 case DNS_TRANSACTION_ATTEMPTS_MAX_REACHED
:
52 return sd_bus_reply_method_errorf(q
->request
, SD_BUS_ERROR_TIMEOUT
, "All attempts to contact name servers or networks failed");
54 case DNS_TRANSACTION_INVALID_REPLY
:
55 return sd_bus_reply_method_errorf(q
->request
, BUS_ERROR_INVALID_REPLY
, "Received invalid reply");
57 case DNS_TRANSACTION_RESOURCES
:
58 return sd_bus_reply_method_errorf(q
->request
, BUS_ERROR_NO_RESOURCES
, "Not enough resources");
60 case DNS_TRANSACTION_ABORTED
:
61 return sd_bus_reply_method_errorf(q
->request
, BUS_ERROR_ABORTED
, "Query aborted");
63 case DNS_TRANSACTION_DNSSEC_FAILED
:
64 return sd_bus_reply_method_errorf(q
->request
, BUS_ERROR_ABORTED
, "DNSSEC validation failed");
66 case DNS_TRANSACTION_FAILURE
: {
67 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
69 if (q
->answer_rcode
== DNS_RCODE_NXDOMAIN
)
70 sd_bus_error_setf(&error
, _BUS_ERROR_DNS
"NXDOMAIN", "'%s' not found", name
);
73 char p
[3]; /* the rcode is 4 bits long */
75 rc
= dns_rcode_to_string(q
->answer_rcode
);
77 sprintf(p
, "%i", q
->answer_rcode
);
81 n
= strjoina(_BUS_ERROR_DNS
, rc
);
82 sd_bus_error_setf(&error
, n
, "Could not resolve '%s', server or network returned error %s", name
, rc
);
85 return sd_bus_reply_method_error(q
->request
, &error
);
88 case DNS_TRANSACTION_NULL
:
89 case DNS_TRANSACTION_PENDING
:
90 case DNS_TRANSACTION_SUCCESS
:
92 assert_not_reached("Impossible state");
96 static int append_address(sd_bus_message
*reply
, DnsResourceRecord
*rr
, int ifindex
) {
102 r
= sd_bus_message_open_container(reply
, 'r', "iiay");
106 r
= sd_bus_message_append(reply
, "i", ifindex
);
110 if (rr
->key
->type
== DNS_TYPE_A
) {
111 r
= sd_bus_message_append(reply
, "i", AF_INET
);
115 r
= sd_bus_message_append_array(reply
, 'y', &rr
->a
.in_addr
, sizeof(struct in_addr
));
117 } else if (rr
->key
->type
== DNS_TYPE_AAAA
) {
118 r
= sd_bus_message_append(reply
, "i", AF_INET6
);
122 r
= sd_bus_message_append_array(reply
, 'y', &rr
->aaaa
.in6_addr
, sizeof(struct in6_addr
));
124 return -EAFNOSUPPORT
;
129 r
= sd_bus_message_close_container(reply
);
136 static void bus_method_resolve_hostname_complete(DnsQuery
*q
) {
137 _cleanup_(dns_resource_record_unrefp
) DnsResourceRecord
*canonical
= NULL
;
138 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
144 if (q
->state
!= DNS_TRANSACTION_SUCCESS
) {
145 r
= reply_query_state(q
);
149 r
= dns_query_process_cname(q
);
151 r
= sd_bus_reply_method_errorf(q
->request
, BUS_ERROR_CNAME_LOOP
, "CNAME loop detected, or CNAME resolving disabled on '%s'", dns_question_first_name(q
->question
));
156 if (r
> 0) /* This was a cname, and the query was restarted. */
159 r
= sd_bus_message_new_method_return(q
->request
, &reply
);
163 r
= sd_bus_message_open_container(reply
, 'a', "(iiay)");
168 DnsResourceRecord
*rr
;
171 DNS_ANSWER_FOREACH_IFINDEX(rr
, ifindex
, q
->answer
) {
172 r
= dns_question_matches_rr(q
->question
, rr
, DNS_SEARCH_DOMAIN_NAME(q
->answer_search_domain
));
178 r
= append_address(reply
, rr
, ifindex
);
183 canonical
= dns_resource_record_ref(rr
);
190 r
= sd_bus_reply_method_errorf(q
->request
, BUS_ERROR_NO_SUCH_RR
, "'%s' does not have any RR of the requested type", dns_question_first_name(q
->question
));
194 r
= sd_bus_message_close_container(reply
);
198 /* Return the precise spelling and uppercasing and CNAME target reported by the server */
200 r
= sd_bus_message_append(
202 DNS_RESOURCE_KEY_NAME(canonical
->key
),
203 SD_RESOLVED_FLAGS_MAKE(q
->answer_protocol
, q
->answer_family
, q
->answer_authenticated
));
207 r
= sd_bus_send(q
->manager
->bus
, reply
, NULL
);
211 log_error_errno(r
, "Failed to send hostname reply: %m");
212 sd_bus_reply_method_errno(q
->request
, r
, NULL
);
218 static int check_ifindex_flags(int ifindex
, uint64_t *flags
, uint64_t ok
, sd_bus_error
*error
) {
222 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid interface index");
224 if (*flags
& ~(SD_RESOLVED_PROTOCOLS_ALL
|SD_RESOLVED_NO_CNAME
|ok
))
225 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid flags parameter");
227 if ((*flags
& SD_RESOLVED_PROTOCOLS_ALL
) == 0) /* If no protocol is enabled, enable all */
228 *flags
|= SD_RESOLVED_PROTOCOLS_ALL
;
233 static int bus_method_resolve_hostname(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
234 _cleanup_(dns_question_unrefp
) DnsQuestion
*question
= NULL
;
235 Manager
*m
= userdata
;
236 const char *hostname
;
245 assert_cc(sizeof(int) == sizeof(int32_t));
247 r
= sd_bus_message_read(message
, "isit", &ifindex
, &hostname
, &family
, &flags
);
251 if (!IN_SET(family
, AF_INET
, AF_INET6
, AF_UNSPEC
))
252 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Unknown address family %i", family
);
254 r
= dns_name_is_valid(hostname
);
258 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid hostname '%s'", hostname
);
260 r
= check_ifindex_flags(ifindex
, &flags
, SD_RESOLVED_NO_SEARCH
, error
);
264 r
= dns_question_new_address(&question
, family
, hostname
);
268 r
= dns_query_new(m
, &q
, question
, ifindex
, flags
);
272 q
->request
= sd_bus_message_ref(message
);
273 q
->request_family
= family
;
274 q
->complete
= bus_method_resolve_hostname_complete
;
276 r
= dns_query_bus_track(q
, message
);
291 static void bus_method_resolve_address_complete(DnsQuery
*q
) {
292 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
293 DnsResourceRecord
*rr
;
299 if (q
->state
!= DNS_TRANSACTION_SUCCESS
) {
300 r
= reply_query_state(q
);
304 r
= dns_query_process_cname(q
);
306 r
= sd_bus_reply_method_errorf(q
->request
, BUS_ERROR_CNAME_LOOP
, "CNAME loop detected, or CNAME resolving disabled on '%s'", dns_question_first_name(q
->question
));
311 if (r
> 0) /* This was a cname, and the query was restarted. */
314 r
= sd_bus_message_new_method_return(q
->request
, &reply
);
318 r
= sd_bus_message_open_container(reply
, 'a', "(is)");
323 DNS_ANSWER_FOREACH_IFINDEX(rr
, ifindex
, q
->answer
) {
324 r
= dns_question_matches_rr(q
->question
, rr
, NULL
);
330 r
= sd_bus_message_append(reply
, "(is)", ifindex
, rr
->ptr
.name
);
339 _cleanup_free_
char *ip
= NULL
;
341 in_addr_to_string(q
->request_family
, &q
->request_address
, &ip
);
342 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
));
346 r
= sd_bus_message_close_container(reply
);
350 r
= sd_bus_message_append(reply
, "t", SD_RESOLVED_FLAGS_MAKE(q
->answer_protocol
, q
->answer_family
, q
->answer_authenticated
));
354 r
= sd_bus_send(q
->manager
->bus
, reply
, NULL
);
358 log_error_errno(r
, "Failed to send address reply: %m");
359 sd_bus_reply_method_errno(q
->request
, r
, NULL
);
365 static int bus_method_resolve_address(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
366 _cleanup_(dns_question_unrefp
) DnsQuestion
*question
= NULL
;
367 Manager
*m
= userdata
;
378 assert_cc(sizeof(int) == sizeof(int32_t));
380 r
= sd_bus_message_read(message
, "ii", &ifindex
, &family
);
384 if (!IN_SET(family
, AF_INET
, AF_INET6
))
385 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Unknown address family %i", family
);
387 r
= sd_bus_message_read_array(message
, 'y', &d
, &sz
);
391 if (sz
!= FAMILY_ADDRESS_SIZE(family
))
392 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid address size");
394 r
= sd_bus_message_read(message
, "t", &flags
);
398 r
= check_ifindex_flags(ifindex
, &flags
, 0, error
);
402 r
= dns_question_new_reverse(&question
, family
, d
);
406 r
= dns_query_new(m
, &q
, question
, ifindex
, flags
|SD_RESOLVED_NO_SEARCH
);
410 q
->request
= sd_bus_message_ref(message
);
411 q
->request_family
= family
;
412 memcpy(&q
->request_address
, d
, sz
);
413 q
->complete
= bus_method_resolve_address_complete
;
415 r
= dns_query_bus_track(q
, message
);
430 static int bus_message_append_rr(sd_bus_message
*m
, DnsResourceRecord
*rr
, int ifindex
) {
436 r
= sd_bus_message_open_container(m
, 'r', "iqqay");
440 r
= sd_bus_message_append(m
, "iqq",
447 r
= dns_resource_record_to_wire_format(rr
, false);
451 r
= sd_bus_message_append_array(m
, 'y', rr
->wire_format
, rr
->wire_format_size
);
455 return sd_bus_message_close_container(m
);
458 static void bus_method_resolve_record_complete(DnsQuery
*q
) {
459 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
465 if (q
->state
!= DNS_TRANSACTION_SUCCESS
) {
466 r
= reply_query_state(q
);
470 r
= dns_query_process_cname(q
);
472 r
= sd_bus_reply_method_errorf(q
->request
, BUS_ERROR_CNAME_LOOP
, "CNAME loop detected, or CNAME resolving disabled on '%s'", dns_question_first_name(q
->question
));
477 if (r
> 0) /* Following a CNAME */
480 r
= sd_bus_message_new_method_return(q
->request
, &reply
);
484 r
= sd_bus_message_open_container(reply
, 'a', "(iqqay)");
489 DnsResourceRecord
*rr
;
492 DNS_ANSWER_FOREACH_IFINDEX(rr
, ifindex
, q
->answer
) {
493 r
= dns_question_matches_rr(q
->question
, rr
, NULL
);
499 r
= bus_message_append_rr(reply
, rr
, ifindex
);
508 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_question_first_name(q
->question
));
512 r
= sd_bus_message_close_container(reply
);
516 r
= sd_bus_message_append(reply
, "t", SD_RESOLVED_FLAGS_MAKE(q
->answer_protocol
, q
->answer_family
, q
->answer_authenticated
));
520 r
= sd_bus_send(q
->manager
->bus
, reply
, NULL
);
524 log_error_errno(r
, "Failed to send record reply: %m");
525 sd_bus_reply_method_errno(q
->request
, r
, NULL
);
531 static int bus_method_resolve_record(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
532 _cleanup_(dns_resource_key_unrefp
) DnsResourceKey
*key
= NULL
;
533 _cleanup_(dns_question_unrefp
) DnsQuestion
*question
= NULL
;
534 Manager
*m
= userdata
;
535 uint16_t class, type
;
544 assert_cc(sizeof(int) == sizeof(int32_t));
546 r
= sd_bus_message_read(message
, "isqqt", &ifindex
, &name
, &class, &type
, &flags
);
550 r
= dns_name_is_valid(name
);
554 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid name '%s'", name
);
556 if (!dns_type_is_valid_query(type
))
557 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid RR type for query %" PRIu16
, type
);
559 r
= check_ifindex_flags(ifindex
, &flags
, 0, error
);
563 question
= dns_question_new(1);
567 key
= dns_resource_key_new(class, type
, name
);
571 r
= dns_question_add(question
, key
);
575 r
= dns_query_new(m
, &q
, question
, ifindex
, flags
|SD_RESOLVED_NO_SEARCH
);
579 q
->request
= sd_bus_message_ref(message
);
580 q
->complete
= bus_method_resolve_record_complete
;
582 r
= dns_query_bus_track(q
, message
);
597 static int append_srv(DnsQuery
*q
, sd_bus_message
*reply
, DnsResourceRecord
*rr
) {
598 _cleanup_(dns_resource_record_unrefp
) DnsResourceRecord
*canonical
= NULL
;
607 if (rr
->key
->type
!= DNS_TYPE_SRV
)
610 if ((q
->flags
& SD_RESOLVED_NO_ADDRESS
) == 0) {
611 /* First, let's see if we could find an appropriate A or AAAA
612 * record for the SRV record */
613 LIST_FOREACH(auxiliary_queries
, aux
, q
->auxiliary_queries
) {
614 DnsResourceRecord
*zz
;
616 if (aux
->state
!= DNS_TRANSACTION_SUCCESS
)
618 if (aux
->auxiliary_result
!= 0)
621 r
= dns_name_equal(dns_question_first_name(aux
->question
), rr
->srv
.name
);
627 DNS_ANSWER_FOREACH(zz
, aux
->answer
) {
629 r
= dns_question_matches_rr(aux
->question
, zz
, NULL
);
635 canonical
= dns_resource_record_ref(zz
);
643 /* Is there are successful A/AAAA lookup for this SRV RR? If not, don't add it */
648 r
= sd_bus_message_open_container(reply
, 'r', "qqqsa(iiay)s");
652 r
= sd_bus_message_append(
655 rr
->srv
.priority
, rr
->srv
.weight
, rr
->srv
.port
, rr
->srv
.name
);
659 r
= sd_bus_message_open_container(reply
, 'a', "(iiay)");
663 if ((q
->flags
& SD_RESOLVED_NO_ADDRESS
) == 0) {
664 LIST_FOREACH(auxiliary_queries
, aux
, q
->auxiliary_queries
) {
665 DnsResourceRecord
*zz
;
668 if (aux
->state
!= DNS_TRANSACTION_SUCCESS
)
670 if (aux
->auxiliary_result
!= 0)
673 r
= dns_name_equal(dns_question_first_name(aux
->question
), rr
->srv
.name
);
679 DNS_ANSWER_FOREACH_IFINDEX(zz
, ifindex
, aux
->answer
) {
681 r
= dns_question_matches_rr(aux
->question
, zz
, NULL
);
687 r
= append_address(reply
, zz
, ifindex
);
694 r
= sd_bus_message_close_container(reply
);
698 /* Note that above we appended the hostname as encoded in the
699 * SRV, and here the canonical hostname this maps to. */
700 r
= sd_bus_message_append(reply
, "s", canonical
? DNS_RESOURCE_KEY_NAME(canonical
->key
) : rr
->srv
.name
);
704 r
= sd_bus_message_close_container(reply
);
711 static int append_txt(sd_bus_message
*reply
, DnsResourceRecord
*rr
) {
719 if (rr
->key
->type
!= DNS_TYPE_TXT
)
722 LIST_FOREACH(items
, i
, rr
->txt
.items
) {
727 r
= sd_bus_message_append_array(reply
, 'y', i
->data
, i
->length
);
735 static void resolve_service_all_complete(DnsQuery
*q
) {
736 _cleanup_(dns_resource_record_unrefp
) DnsResourceRecord
*canonical
= NULL
;
737 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
738 _cleanup_free_
char *name
= NULL
, *type
= NULL
, *domain
= NULL
;
740 unsigned added
= false;
745 if (q
->block_all_complete
> 0)
748 if ((q
->flags
& SD_RESOLVED_NO_ADDRESS
) == 0) {
749 DnsQuery
*bad
= NULL
;
750 bool have_success
= false;
752 LIST_FOREACH(auxiliary_queries
, aux
, q
->auxiliary_queries
) {
754 switch (aux
->state
) {
756 case DNS_TRANSACTION_PENDING
:
757 /* If an auxiliary query is still pending, let's wait */
760 case DNS_TRANSACTION_SUCCESS
:
761 if (aux
->auxiliary_result
== 0)
774 /* We can only return one error, hence pick the last error we encountered */
778 if (bad
->state
== DNS_TRANSACTION_SUCCESS
) {
779 assert(bad
->auxiliary_result
!= 0);
781 if (bad
->auxiliary_result
== -ELOOP
) {
782 r
= sd_bus_reply_method_errorf(q
->request
, BUS_ERROR_CNAME_LOOP
, "CNAME loop detected, or CNAME resolving disabled on '%s'", dns_question_first_name(bad
->question
));
786 r
= bad
->auxiliary_result
;
790 r
= reply_query_state(bad
);
795 r
= sd_bus_message_new_method_return(q
->request
, &reply
);
799 r
= sd_bus_message_open_container(reply
, 'a', "(qqqsa(iiay)s)");
804 DnsResourceRecord
*rr
;
806 DNS_ANSWER_FOREACH(rr
, q
->answer
) {
807 r
= dns_question_matches_rr(q
->question
, rr
, NULL
);
813 r
= append_srv(q
, reply
, rr
);
816 if (r
== 0) /* not an SRV record */
820 canonical
= dns_resource_record_ref(rr
);
827 r
= sd_bus_reply_method_errorf(q
->request
, BUS_ERROR_NO_SUCH_RR
, "'%s' does not have any RR of the requested type", dns_question_first_name(q
->question
));
831 r
= sd_bus_message_close_container(reply
);
835 r
= sd_bus_message_open_container(reply
, 'a', "ay");
840 DnsResourceRecord
*rr
;
842 DNS_ANSWER_FOREACH(rr
, q
->answer
) {
843 r
= dns_question_matches_rr(q
->question
, rr
, NULL
);
849 r
= append_txt(reply
, rr
);
855 r
= sd_bus_message_close_container(reply
);
860 r
= dns_service_split(DNS_RESOURCE_KEY_NAME(canonical
->key
), &name
, &type
, &domain
);
864 r
= sd_bus_message_append(
868 SD_RESOLVED_FLAGS_MAKE(q
->answer_protocol
, q
->answer_family
, q
->answer_authenticated
));
872 r
= sd_bus_send(q
->manager
->bus
, reply
, NULL
);
876 log_error_errno(r
, "Failed to send service reply: %m");
877 sd_bus_reply_method_errno(q
->request
, r
, NULL
);
883 static void resolve_service_hostname_complete(DnsQuery
*q
) {
887 assert(q
->auxiliary_for
);
889 if (q
->state
!= DNS_TRANSACTION_SUCCESS
) {
890 resolve_service_all_complete(q
->auxiliary_for
);
894 r
= dns_query_process_cname(q
);
895 if (r
> 0) /* This was a cname, and the query was restarted. */
898 /* This auxiliary lookup is finished or failed, let's see if all are finished now. */
899 q
->auxiliary_result
= r
;
900 resolve_service_all_complete(q
->auxiliary_for
);
903 static int resolve_service_hostname(DnsQuery
*q
, DnsResourceRecord
*rr
, int ifindex
) {
904 _cleanup_(dns_question_unrefp
) DnsQuestion
*question
= NULL
;
911 assert(rr
->key
->type
== DNS_TYPE_SRV
);
913 /* OK, we found an SRV record for the service. Let's resolve
914 * the hostname included in it */
916 r
= dns_question_new_address(&question
, q
->request_family
, rr
->srv
.name
);
920 r
= dns_query_new(q
->manager
, &aux
, question
, ifindex
, q
->flags
|SD_RESOLVED_NO_SEARCH
);
924 aux
->request_family
= q
->request_family
;
925 aux
->complete
= resolve_service_hostname_complete
;
927 r
= dns_query_make_auxiliary(aux
, q
);
929 /* Too many auxiliary lookups? If so, don't complain,
930 * let's just not add this one, we already have more
939 /* Note that auxiliary queries do not track the original bus
940 * client, only the primary request does that. */
942 r
= dns_query_go(aux
);
953 static void bus_method_resolve_service_complete(DnsQuery
*q
) {
959 if (q
->state
!= DNS_TRANSACTION_SUCCESS
) {
960 r
= reply_query_state(q
);
964 r
= dns_query_process_cname(q
);
966 r
= sd_bus_reply_method_errorf(q
->request
, BUS_ERROR_CNAME_LOOP
, "CNAME loop detected, or CNAME resolving disabled on '%s'", dns_question_first_name(q
->question
));
971 if (r
> 0) /* This was a cname, and the query was restarted. */
975 DnsResourceRecord
*rr
;
978 DNS_ANSWER_FOREACH_IFINDEX(rr
, ifindex
, q
->answer
) {
979 r
= dns_question_matches_rr(q
->question
, rr
, NULL
);
985 if (rr
->key
->type
!= DNS_TYPE_SRV
)
988 if ((q
->flags
& SD_RESOLVED_NO_ADDRESS
) == 0) {
989 q
->block_all_complete
++;
990 r
= resolve_service_hostname(q
, rr
, ifindex
);
991 q
->block_all_complete
--;
1002 r
= sd_bus_reply_method_errorf(q
->request
, BUS_ERROR_NO_SUCH_RR
, "'%s' does not have any RR of the requested type", dns_question_first_name(q
->question
));
1006 /* Maybe we are already finished? check now... */
1007 resolve_service_all_complete(q
);
1012 log_error_errno(r
, "Failed to send service reply: %m");
1013 sd_bus_reply_method_errno(q
->request
, r
, NULL
);
1019 static int bus_method_resolve_service(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1020 _cleanup_(dns_question_unrefp
) DnsQuestion
*question
= NULL
;
1021 const char *name
, *type
, *domain
, *joined
;
1022 _cleanup_free_
char *n
= NULL
;
1023 Manager
*m
= userdata
;
1024 int family
, ifindex
;
1032 assert_cc(sizeof(int) == sizeof(int32_t));
1034 r
= sd_bus_message_read(message
, "isssit", &ifindex
, &name
, &type
, &domain
, &family
, &flags
);
1038 if (!IN_SET(family
, AF_INET
, AF_INET6
, AF_UNSPEC
))
1039 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Unknown address family %i", family
);
1044 if (!dns_service_name_is_valid(name
))
1045 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid service name '%s'", name
);
1050 else if (!dns_srv_type_is_valid(type
))
1051 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid SRV service type '%s'", type
);
1053 r
= dns_name_is_valid(domain
);
1057 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid domain '%s'", domain
);
1060 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Service name cannot be specified without service type.");
1062 r
= check_ifindex_flags(ifindex
, &flags
, SD_RESOLVED_NO_TXT
|SD_RESOLVED_NO_ADDRESS
, error
);
1067 /* If the type is specified, we generate the full domain name to look up ourselves */
1068 r
= dns_service_join(name
, type
, domain
, &n
);
1074 /* If no type is specified, we assume the domain
1075 * contains the full domain name to lookup already */
1078 r
= dns_question_new_service(&question
, joined
, !(flags
& SD_RESOLVED_NO_TXT
));
1082 r
= dns_query_new(m
, &q
, question
, ifindex
, flags
|SD_RESOLVED_NO_SEARCH
);
1086 q
->request
= sd_bus_message_ref(message
);
1087 q
->request_family
= family
;
1088 q
->complete
= bus_method_resolve_service_complete
;
1090 r
= dns_query_bus_track(q
, message
);
1094 r
= dns_query_go(q
);
1105 static int append_dns_server(sd_bus_message
*reply
, DnsServer
*s
) {
1111 r
= sd_bus_message_open_container(reply
, 'r', "iiay");
1115 r
= sd_bus_message_append(reply
, "ii", s
->link
? s
->link
->ifindex
: 0, s
->family
);
1119 r
= sd_bus_message_append_array(reply
, 'y', &s
->address
, FAMILY_ADDRESS_SIZE(s
->family
));
1123 return sd_bus_message_close_container(reply
);
1126 static int bus_property_get_dns_servers(
1129 const char *interface
,
1130 const char *property
,
1131 sd_bus_message
*reply
,
1133 sd_bus_error
*error
) {
1135 Manager
*m
= userdata
;
1145 r
= sd_bus_message_open_container(reply
, 'a', "(iiay)");
1149 LIST_FOREACH(servers
, s
, m
->dns_servers
) {
1150 r
= append_dns_server(reply
, s
);
1157 HASHMAP_FOREACH(l
, m
->links
, i
) {
1158 LIST_FOREACH(servers
, s
, l
->dns_servers
) {
1159 r
= append_dns_server(reply
, s
);
1167 LIST_FOREACH(servers
, s
, m
->fallback_dns_servers
) {
1168 r
= append_dns_server(reply
, s
);
1174 return sd_bus_message_close_container(reply
);
1177 static int bus_property_get_search_domains(
1180 const char *interface
,
1181 const char *property
,
1182 sd_bus_message
*reply
,
1184 sd_bus_error
*error
) {
1186 Manager
*m
= userdata
;
1195 r
= sd_bus_message_open_container(reply
, 'a', "(is)");
1199 LIST_FOREACH(domains
, d
, m
->search_domains
) {
1200 r
= sd_bus_message_append(reply
, "(is)", 0, d
->name
);
1205 HASHMAP_FOREACH(l
, m
->links
, i
) {
1206 LIST_FOREACH(domains
, d
, l
->search_domains
) {
1207 r
= sd_bus_message_append(reply
, "is", l
->ifindex
, d
->name
);
1213 return sd_bus_message_close_container(reply
);
1216 static const sd_bus_vtable resolve_vtable
[] = {
1217 SD_BUS_VTABLE_START(0),
1218 SD_BUS_PROPERTY("LLMNRHostname", "s", NULL
, offsetof(Manager
, llmnr_hostname
), 0),
1219 SD_BUS_PROPERTY("DNSServers", "a(iiay)", bus_property_get_dns_servers
, 0, 0),
1220 SD_BUS_PROPERTY("SearchDomains", "a(is)", bus_property_get_search_domains
, 0, 0),
1222 SD_BUS_METHOD("ResolveHostname", "isit", "a(iiay)st", bus_method_resolve_hostname
, SD_BUS_VTABLE_UNPRIVILEGED
),
1223 SD_BUS_METHOD("ResolveAddress", "iiayt", "a(is)t", bus_method_resolve_address
, SD_BUS_VTABLE_UNPRIVILEGED
),
1224 SD_BUS_METHOD("ResolveRecord", "isqqt", "a(iqqay)t", bus_method_resolve_record
, SD_BUS_VTABLE_UNPRIVILEGED
),
1225 SD_BUS_METHOD("ResolveService", "isssit", "a(qqqsa(iiay)s)aayssst", bus_method_resolve_service
, SD_BUS_VTABLE_UNPRIVILEGED
),
1229 static int on_bus_retry(sd_event_source
*s
, usec_t usec
, void *userdata
) {
1230 Manager
*m
= userdata
;
1235 m
->bus_retry_event_source
= sd_event_source_unref(m
->bus_retry_event_source
);
1237 manager_connect_bus(m
);
1241 static int match_prepare_for_sleep(sd_bus_message
*message
, void *userdata
, sd_bus_error
*ret_error
) {
1242 Manager
*m
= userdata
;
1248 r
= sd_bus_message_read(message
, "b", &b
);
1250 log_debug_errno(r
, "Failed to parse PrepareForSleep signal: %m");
1257 log_debug("Coming back from suspend, verifying all RRs...");
1259 manager_verify_all(m
);
1263 int manager_connect_bus(Manager
*m
) {
1271 r
= sd_bus_default_system(&m
->bus
);
1273 /* We failed to connect? Yuck, we must be in early
1274 * boot. Let's try in 5s again. As soon as we have
1275 * kdbus we can stop doing this... */
1277 log_debug_errno(r
, "Failed to connect to bus, trying again in 5s: %m");
1279 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
);
1281 return log_error_errno(r
, "Failed to install bus reconnect time event: %m");
1286 r
= sd_bus_add_object_vtable(m
->bus
, NULL
, "/org/freedesktop/resolve1", "org.freedesktop.resolve1.Manager", resolve_vtable
, m
);
1288 return log_error_errno(r
, "Failed to register object: %m");
1290 r
= sd_bus_request_name(m
->bus
, "org.freedesktop.resolve1", 0);
1292 return log_error_errno(r
, "Failed to register name: %m");
1294 r
= sd_bus_attach_event(m
->bus
, m
->event
, 0);
1296 return log_error_errno(r
, "Failed to attach bus to event loop: %m");
1298 r
= sd_bus_add_match(m
->bus
, &m
->prepare_for_sleep_slot
,
1300 "sender='org.freedesktop.login1',"
1301 "interface='org.freedesktop.login1.Manager',"
1302 "member='PrepareForSleep',"
1303 "path='/org/freedesktop/login1'",
1304 match_prepare_for_sleep
,
1307 log_error_errno(r
, "Failed to add match for PrepareForSleep: %m");