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_FAILURE
: {
64 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
66 if (q
->answer_rcode
== DNS_RCODE_NXDOMAIN
)
67 sd_bus_error_setf(&error
, _BUS_ERROR_DNS
"NXDOMAIN", "'%s' not found", name
);
70 char p
[3]; /* the rcode is 4 bits long */
72 rc
= dns_rcode_to_string(q
->answer_rcode
);
74 sprintf(p
, "%i", q
->answer_rcode
);
78 n
= strjoina(_BUS_ERROR_DNS
, rc
);
79 sd_bus_error_setf(&error
, n
, "Could not resolve '%s', server or network returned error %s", name
, rc
);
82 return sd_bus_reply_method_error(q
->request
, &error
);
85 case DNS_TRANSACTION_NULL
:
86 case DNS_TRANSACTION_PENDING
:
87 case DNS_TRANSACTION_SUCCESS
:
89 assert_not_reached("Impossible state");
93 static int append_address(sd_bus_message
*reply
, DnsResourceRecord
*rr
, int ifindex
) {
99 r
= sd_bus_message_open_container(reply
, 'r', "iiay");
103 r
= sd_bus_message_append(reply
, "i", ifindex
);
107 if (rr
->key
->type
== DNS_TYPE_A
) {
108 r
= sd_bus_message_append(reply
, "i", AF_INET
);
112 r
= sd_bus_message_append_array(reply
, 'y', &rr
->a
.in_addr
, sizeof(struct in_addr
));
114 } else if (rr
->key
->type
== DNS_TYPE_AAAA
) {
115 r
= sd_bus_message_append(reply
, "i", AF_INET6
);
119 r
= sd_bus_message_append_array(reply
, 'y', &rr
->aaaa
.in6_addr
, sizeof(struct in6_addr
));
121 return -EAFNOSUPPORT
;
126 r
= sd_bus_message_close_container(reply
);
133 static void bus_method_resolve_hostname_complete(DnsQuery
*q
) {
134 _cleanup_(dns_resource_record_unrefp
) DnsResourceRecord
*canonical
= NULL
;
135 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
141 if (q
->state
!= DNS_TRANSACTION_SUCCESS
) {
142 r
= reply_query_state(q
);
146 r
= dns_query_process_cname(q
);
148 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
));
153 if (r
> 0) /* This was a cname, and the query was restarted. */
156 r
= sd_bus_message_new_method_return(q
->request
, &reply
);
160 r
= sd_bus_message_open_container(reply
, 'a', "(iiay)");
165 DnsResourceRecord
*rr
;
168 DNS_ANSWER_FOREACH_IFINDEX(rr
, ifindex
, q
->answer
) {
169 r
= dns_question_matches_rr(q
->question
, rr
, DNS_SEARCH_DOMAIN_NAME(q
->answer_search_domain
));
175 r
= append_address(reply
, rr
, ifindex
);
180 canonical
= dns_resource_record_ref(rr
);
187 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
));
191 r
= sd_bus_message_close_container(reply
);
195 /* Return the precise spelling and uppercasing and CNAME target reported by the server */
197 r
= sd_bus_message_append(
199 DNS_RESOURCE_KEY_NAME(canonical
->key
),
200 SD_RESOLVED_FLAGS_MAKE(q
->answer_protocol
, q
->answer_family
, q
->answer_authenticated
));
204 r
= sd_bus_send(q
->manager
->bus
, reply
, NULL
);
208 log_error_errno(r
, "Failed to send hostname reply: %m");
209 sd_bus_reply_method_errno(q
->request
, r
, NULL
);
215 static int check_ifindex_flags(int ifindex
, uint64_t *flags
, uint64_t ok
, sd_bus_error
*error
) {
219 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid interface index");
221 if (*flags
& ~(SD_RESOLVED_PROTOCOLS_ALL
|SD_RESOLVED_NO_CNAME
|ok
))
222 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid flags parameter");
224 if ((*flags
& SD_RESOLVED_PROTOCOLS_ALL
) == 0) /* If no protocol is enabled, enable all */
225 *flags
|= SD_RESOLVED_PROTOCOLS_ALL
;
230 static int bus_method_resolve_hostname(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
231 _cleanup_(dns_question_unrefp
) DnsQuestion
*question
= NULL
;
232 Manager
*m
= userdata
;
233 const char *hostname
;
242 assert_cc(sizeof(int) == sizeof(int32_t));
244 r
= sd_bus_message_read(message
, "isit", &ifindex
, &hostname
, &family
, &flags
);
248 if (!IN_SET(family
, AF_INET
, AF_INET6
, AF_UNSPEC
))
249 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Unknown address family %i", family
);
251 r
= dns_name_is_valid(hostname
);
255 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid hostname '%s'", hostname
);
257 r
= check_ifindex_flags(ifindex
, &flags
, SD_RESOLVED_NO_SEARCH
, error
);
261 r
= dns_question_new_address(&question
, family
, hostname
);
265 r
= dns_query_new(m
, &q
, question
, ifindex
, flags
);
269 q
->request
= sd_bus_message_ref(message
);
270 q
->request_family
= family
;
271 q
->complete
= bus_method_resolve_hostname_complete
;
273 r
= dns_query_bus_track(q
, message
);
288 static void bus_method_resolve_address_complete(DnsQuery
*q
) {
289 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
290 DnsResourceRecord
*rr
;
296 if (q
->state
!= DNS_TRANSACTION_SUCCESS
) {
297 r
= reply_query_state(q
);
301 r
= dns_query_process_cname(q
);
303 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
));
308 if (r
> 0) /* This was a cname, and the query was restarted. */
311 r
= sd_bus_message_new_method_return(q
->request
, &reply
);
315 r
= sd_bus_message_open_container(reply
, 'a', "(is)");
320 DNS_ANSWER_FOREACH_IFINDEX(rr
, ifindex
, q
->answer
) {
321 r
= dns_question_matches_rr(q
->question
, rr
, NULL
);
327 r
= sd_bus_message_append(reply
, "(is)", ifindex
, rr
->ptr
.name
);
336 _cleanup_free_
char *ip
= NULL
;
338 in_addr_to_string(q
->request_family
, &q
->request_address
, &ip
);
339 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
));
343 r
= sd_bus_message_close_container(reply
);
347 r
= sd_bus_message_append(reply
, "t", SD_RESOLVED_FLAGS_MAKE(q
->answer_protocol
, q
->answer_family
, q
->answer_authenticated
));
351 r
= sd_bus_send(q
->manager
->bus
, reply
, NULL
);
355 log_error_errno(r
, "Failed to send address reply: %m");
356 sd_bus_reply_method_errno(q
->request
, r
, NULL
);
362 static int bus_method_resolve_address(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
363 _cleanup_(dns_question_unrefp
) DnsQuestion
*question
= NULL
;
364 Manager
*m
= userdata
;
375 assert_cc(sizeof(int) == sizeof(int32_t));
377 r
= sd_bus_message_read(message
, "ii", &ifindex
, &family
);
381 if (!IN_SET(family
, AF_INET
, AF_INET6
))
382 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Unknown address family %i", family
);
384 r
= sd_bus_message_read_array(message
, 'y', &d
, &sz
);
388 if (sz
!= FAMILY_ADDRESS_SIZE(family
))
389 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid address size");
391 r
= sd_bus_message_read(message
, "t", &flags
);
395 r
= check_ifindex_flags(ifindex
, &flags
, 0, error
);
399 r
= dns_question_new_reverse(&question
, family
, d
);
403 r
= dns_query_new(m
, &q
, question
, ifindex
, flags
|SD_RESOLVED_NO_SEARCH
);
407 q
->request
= sd_bus_message_ref(message
);
408 q
->request_family
= family
;
409 memcpy(&q
->request_address
, d
, sz
);
410 q
->complete
= bus_method_resolve_address_complete
;
412 r
= dns_query_bus_track(q
, message
);
427 static int bus_message_append_rr(sd_bus_message
*m
, DnsResourceRecord
*rr
, int ifindex
) {
433 r
= sd_bus_message_open_container(m
, 'r', "iqqay");
437 r
= sd_bus_message_append(m
, "iqq",
444 r
= dns_resource_record_to_wire_format(rr
, false);
448 r
= sd_bus_message_append_array(m
, 'y', rr
->wire_format
, rr
->wire_format_size
);
452 return sd_bus_message_close_container(m
);
455 static void bus_method_resolve_record_complete(DnsQuery
*q
) {
456 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
462 if (q
->state
!= DNS_TRANSACTION_SUCCESS
) {
463 r
= reply_query_state(q
);
467 r
= dns_query_process_cname(q
);
469 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
));
474 if (r
> 0) /* Following a CNAME */
477 r
= sd_bus_message_new_method_return(q
->request
, &reply
);
481 r
= sd_bus_message_open_container(reply
, 'a', "(iqqay)");
486 DnsResourceRecord
*rr
;
489 DNS_ANSWER_FOREACH_IFINDEX(rr
, ifindex
, q
->answer
) {
490 r
= dns_question_matches_rr(q
->question
, rr
, NULL
);
496 r
= bus_message_append_rr(reply
, rr
, ifindex
);
505 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
));
509 r
= sd_bus_message_close_container(reply
);
513 r
= sd_bus_message_append(reply
, "t", SD_RESOLVED_FLAGS_MAKE(q
->answer_protocol
, q
->answer_family
, q
->answer_authenticated
));
517 r
= sd_bus_send(q
->manager
->bus
, reply
, NULL
);
521 log_error_errno(r
, "Failed to send record reply: %m");
522 sd_bus_reply_method_errno(q
->request
, r
, NULL
);
528 static int bus_method_resolve_record(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
529 _cleanup_(dns_resource_key_unrefp
) DnsResourceKey
*key
= NULL
;
530 _cleanup_(dns_question_unrefp
) DnsQuestion
*question
= NULL
;
531 Manager
*m
= userdata
;
532 uint16_t class, type
;
541 assert_cc(sizeof(int) == sizeof(int32_t));
543 r
= sd_bus_message_read(message
, "isqqt", &ifindex
, &name
, &class, &type
, &flags
);
547 r
= dns_name_is_valid(name
);
551 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid name '%s'", name
);
553 r
= check_ifindex_flags(ifindex
, &flags
, 0, error
);
557 question
= dns_question_new(1);
561 key
= dns_resource_key_new(class, type
, name
);
565 r
= dns_question_add(question
, key
);
569 r
= dns_query_new(m
, &q
, question
, ifindex
, flags
|SD_RESOLVED_NO_SEARCH
);
573 q
->request
= sd_bus_message_ref(message
);
574 q
->complete
= bus_method_resolve_record_complete
;
576 r
= dns_query_bus_track(q
, message
);
591 static int append_srv(DnsQuery
*q
, sd_bus_message
*reply
, DnsResourceRecord
*rr
) {
592 _cleanup_(dns_resource_record_unrefp
) DnsResourceRecord
*canonical
= NULL
;
601 if (rr
->key
->type
!= DNS_TYPE_SRV
)
604 if ((q
->flags
& SD_RESOLVED_NO_ADDRESS
) == 0) {
605 /* First, let's see if we could find an appropriate A or AAAA
606 * record for the SRV record */
607 LIST_FOREACH(auxiliary_queries
, aux
, q
->auxiliary_queries
) {
608 DnsResourceRecord
*zz
;
610 if (aux
->state
!= DNS_TRANSACTION_SUCCESS
)
612 if (aux
->auxiliary_result
!= 0)
615 r
= dns_name_equal(dns_question_first_name(aux
->question
), rr
->srv
.name
);
621 DNS_ANSWER_FOREACH(zz
, aux
->answer
) {
623 r
= dns_question_matches_rr(aux
->question
, zz
, NULL
);
629 canonical
= dns_resource_record_ref(zz
);
637 /* Is there are successful A/AAAA lookup for this SRV RR? If not, don't add it */
642 r
= sd_bus_message_open_container(reply
, 'r', "qqqsa(iiay)s");
646 r
= sd_bus_message_append(
649 rr
->srv
.priority
, rr
->srv
.weight
, rr
->srv
.port
, rr
->srv
.name
);
653 r
= sd_bus_message_open_container(reply
, 'a', "(iiay)");
657 if ((q
->flags
& SD_RESOLVED_NO_ADDRESS
) == 0) {
658 LIST_FOREACH(auxiliary_queries
, aux
, q
->auxiliary_queries
) {
659 DnsResourceRecord
*zz
;
662 if (aux
->state
!= DNS_TRANSACTION_SUCCESS
)
664 if (aux
->auxiliary_result
!= 0)
667 r
= dns_name_equal(dns_question_first_name(aux
->question
), rr
->srv
.name
);
673 DNS_ANSWER_FOREACH_IFINDEX(zz
, ifindex
, aux
->answer
) {
675 r
= dns_question_matches_rr(aux
->question
, zz
, NULL
);
681 r
= append_address(reply
, zz
, ifindex
);
688 r
= sd_bus_message_close_container(reply
);
692 /* Note that above we appended the hostname as encoded in the
693 * SRV, and here the canonical hostname this maps to. */
694 r
= sd_bus_message_append(reply
, "s", canonical
? DNS_RESOURCE_KEY_NAME(canonical
->key
) : rr
->srv
.name
);
698 r
= sd_bus_message_close_container(reply
);
705 static int append_txt(sd_bus_message
*reply
, DnsResourceRecord
*rr
) {
713 if (rr
->key
->type
!= DNS_TYPE_TXT
)
716 LIST_FOREACH(items
, i
, rr
->txt
.items
) {
721 r
= sd_bus_message_append_array(reply
, 'y', i
->data
, i
->length
);
729 static void resolve_service_all_complete(DnsQuery
*q
) {
730 _cleanup_(dns_resource_record_unrefp
) DnsResourceRecord
*canonical
= NULL
;
731 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
732 _cleanup_free_
char *name
= NULL
, *type
= NULL
, *domain
= NULL
;
734 unsigned added
= false;
739 if (q
->block_all_complete
> 0)
742 if ((q
->flags
& SD_RESOLVED_NO_ADDRESS
) == 0) {
743 DnsQuery
*bad
= NULL
;
744 bool have_success
= false;
746 LIST_FOREACH(auxiliary_queries
, aux
, q
->auxiliary_queries
) {
748 switch (aux
->state
) {
750 case DNS_TRANSACTION_PENDING
:
751 /* If an auxiliary query is still pending, let's wait */
754 case DNS_TRANSACTION_SUCCESS
:
755 if (aux
->auxiliary_result
== 0)
768 /* We can only return one error, hence pick the last error we encountered */
772 if (bad
->state
== DNS_TRANSACTION_SUCCESS
) {
773 assert(bad
->auxiliary_result
!= 0);
775 if (bad
->auxiliary_result
== -ELOOP
) {
776 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
));
780 r
= bad
->auxiliary_result
;
784 r
= reply_query_state(bad
);
789 r
= sd_bus_message_new_method_return(q
->request
, &reply
);
793 r
= sd_bus_message_open_container(reply
, 'a', "(qqqsa(iiay)s)");
798 DnsResourceRecord
*rr
;
800 DNS_ANSWER_FOREACH(rr
, q
->answer
) {
801 r
= dns_question_matches_rr(q
->question
, rr
, NULL
);
807 r
= append_srv(q
, reply
, rr
);
810 if (r
== 0) /* not an SRV record */
814 canonical
= dns_resource_record_ref(rr
);
821 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
));
825 r
= sd_bus_message_close_container(reply
);
829 r
= sd_bus_message_open_container(reply
, 'a', "ay");
834 DnsResourceRecord
*rr
;
836 DNS_ANSWER_FOREACH(rr
, q
->answer
) {
837 r
= dns_question_matches_rr(q
->question
, rr
, NULL
);
843 r
= append_txt(reply
, rr
);
849 r
= sd_bus_message_close_container(reply
);
854 r
= dns_service_split(DNS_RESOURCE_KEY_NAME(canonical
->key
), &name
, &type
, &domain
);
858 r
= sd_bus_message_append(
862 SD_RESOLVED_FLAGS_MAKE(q
->answer_protocol
, q
->answer_family
, q
->answer_authenticated
));
866 r
= sd_bus_send(q
->manager
->bus
, reply
, NULL
);
870 log_error_errno(r
, "Failed to send service reply: %m");
871 sd_bus_reply_method_errno(q
->request
, r
, NULL
);
877 static void resolve_service_hostname_complete(DnsQuery
*q
) {
881 assert(q
->auxiliary_for
);
883 if (q
->state
!= DNS_TRANSACTION_SUCCESS
) {
884 resolve_service_all_complete(q
->auxiliary_for
);
888 r
= dns_query_process_cname(q
);
889 if (r
> 0) /* This was a cname, and the query was restarted. */
892 /* This auxiliary lookup is finished or failed, let's see if all are finished now. */
893 q
->auxiliary_result
= r
;
894 resolve_service_all_complete(q
->auxiliary_for
);
897 static int resolve_service_hostname(DnsQuery
*q
, DnsResourceRecord
*rr
, int ifindex
) {
898 _cleanup_(dns_question_unrefp
) DnsQuestion
*question
= NULL
;
905 assert(rr
->key
->type
== DNS_TYPE_SRV
);
907 /* OK, we found an SRV record for the service. Let's resolve
908 * the hostname included in it */
910 r
= dns_question_new_address(&question
, q
->request_family
, rr
->srv
.name
);
914 r
= dns_query_new(q
->manager
, &aux
, question
, ifindex
, q
->flags
|SD_RESOLVED_NO_SEARCH
);
918 aux
->request_family
= q
->request_family
;
919 aux
->complete
= resolve_service_hostname_complete
;
921 r
= dns_query_make_auxiliary(aux
, q
);
923 /* Too many auxiliary lookups? If so, don't complain,
924 * let's just not add this one, we already have more
933 /* Note that auxiliary queries do not track the original bus
934 * client, only the primary request does that. */
936 r
= dns_query_go(aux
);
947 static void bus_method_resolve_service_complete(DnsQuery
*q
) {
953 if (q
->state
!= DNS_TRANSACTION_SUCCESS
) {
954 r
= reply_query_state(q
);
958 r
= dns_query_process_cname(q
);
960 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
));
965 if (r
> 0) /* This was a cname, and the query was restarted. */
969 DnsResourceRecord
*rr
;
972 DNS_ANSWER_FOREACH_IFINDEX(rr
, ifindex
, q
->answer
) {
973 r
= dns_question_matches_rr(q
->question
, rr
, NULL
);
979 if (rr
->key
->type
!= DNS_TYPE_SRV
)
982 if ((q
->flags
& SD_RESOLVED_NO_ADDRESS
) == 0) {
983 q
->block_all_complete
++;
984 r
= resolve_service_hostname(q
, rr
, ifindex
);
985 q
->block_all_complete
--;
996 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
));
1000 /* Maybe we are already finished? check now... */
1001 resolve_service_all_complete(q
);
1006 log_error_errno(r
, "Failed to send service reply: %m");
1007 sd_bus_reply_method_errno(q
->request
, r
, NULL
);
1013 static int bus_method_resolve_service(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1014 _cleanup_(dns_question_unrefp
) DnsQuestion
*question
= NULL
;
1015 const char *name
, *type
, *domain
, *joined
;
1016 _cleanup_free_
char *n
= NULL
;
1017 Manager
*m
= userdata
;
1018 int family
, ifindex
;
1026 assert_cc(sizeof(int) == sizeof(int32_t));
1028 r
= sd_bus_message_read(message
, "isssit", &ifindex
, &name
, &type
, &domain
, &family
, &flags
);
1032 if (!IN_SET(family
, AF_INET
, AF_INET6
, AF_UNSPEC
))
1033 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Unknown address family %i", family
);
1038 if (!dns_service_name_is_valid(name
))
1039 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid service name '%s'", name
);
1044 else if (!dns_srv_type_is_valid(type
))
1045 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid SRV service type '%s'", type
);
1047 r
= dns_name_is_valid(domain
);
1051 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid domain '%s'", domain
);
1054 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Service name cannot be specified without service type.");
1056 r
= check_ifindex_flags(ifindex
, &flags
, SD_RESOLVED_NO_TXT
|SD_RESOLVED_NO_ADDRESS
, error
);
1061 /* If the type is specified, we generate the full domain name to look up ourselves */
1062 r
= dns_service_join(name
, type
, domain
, &n
);
1068 /* If no type is specified, we assume the domain
1069 * contains the full domain name to lookup already */
1072 r
= dns_question_new_service(&question
, joined
, !(flags
& SD_RESOLVED_NO_TXT
));
1076 r
= dns_query_new(m
, &q
, question
, ifindex
, flags
|SD_RESOLVED_NO_SEARCH
);
1080 q
->request
= sd_bus_message_ref(message
);
1081 q
->request_family
= family
;
1082 q
->complete
= bus_method_resolve_service_complete
;
1084 r
= dns_query_bus_track(q
, message
);
1088 r
= dns_query_go(q
);
1099 static int append_dns_server(sd_bus_message
*reply
, DnsServer
*s
) {
1105 r
= sd_bus_message_open_container(reply
, 'r', "iiay");
1109 r
= sd_bus_message_append(reply
, "ii", s
->link
? s
->link
->ifindex
: 0, s
->family
);
1113 r
= sd_bus_message_append_array(reply
, 'y', &s
->address
, FAMILY_ADDRESS_SIZE(s
->family
));
1117 return sd_bus_message_close_container(reply
);
1120 static int bus_property_get_dns_servers(
1123 const char *interface
,
1124 const char *property
,
1125 sd_bus_message
*reply
,
1127 sd_bus_error
*error
) {
1129 Manager
*m
= userdata
;
1139 r
= sd_bus_message_open_container(reply
, 'a', "(iiay)");
1143 LIST_FOREACH(servers
, s
, m
->dns_servers
) {
1144 r
= append_dns_server(reply
, s
);
1151 HASHMAP_FOREACH(l
, m
->links
, i
) {
1152 LIST_FOREACH(servers
, s
, l
->dns_servers
) {
1153 r
= append_dns_server(reply
, s
);
1161 LIST_FOREACH(servers
, s
, m
->fallback_dns_servers
) {
1162 r
= append_dns_server(reply
, s
);
1168 return sd_bus_message_close_container(reply
);
1171 static int bus_property_get_search_domains(
1174 const char *interface
,
1175 const char *property
,
1176 sd_bus_message
*reply
,
1178 sd_bus_error
*error
) {
1180 Manager
*m
= userdata
;
1189 r
= sd_bus_message_open_container(reply
, 'a', "(is)");
1193 LIST_FOREACH(domains
, d
, m
->search_domains
) {
1194 r
= sd_bus_message_append(reply
, "(is)", 0, d
->name
);
1199 HASHMAP_FOREACH(l
, m
->links
, i
) {
1200 LIST_FOREACH(domains
, d
, l
->search_domains
) {
1201 r
= sd_bus_message_append(reply
, "is", l
->ifindex
, d
->name
);
1207 return sd_bus_message_close_container(reply
);
1210 static const sd_bus_vtable resolve_vtable
[] = {
1211 SD_BUS_VTABLE_START(0),
1212 SD_BUS_PROPERTY("LLMNRHostname", "s", NULL
, offsetof(Manager
, llmnr_hostname
), 0),
1213 SD_BUS_PROPERTY("DNSServers", "a(iiay)", bus_property_get_dns_servers
, 0, 0),
1214 SD_BUS_PROPERTY("SearchDomains", "a(is)", bus_property_get_search_domains
, 0, 0),
1216 SD_BUS_METHOD("ResolveHostname", "isit", "a(iiay)st", bus_method_resolve_hostname
, SD_BUS_VTABLE_UNPRIVILEGED
),
1217 SD_BUS_METHOD("ResolveAddress", "iiayt", "a(is)t", bus_method_resolve_address
, SD_BUS_VTABLE_UNPRIVILEGED
),
1218 SD_BUS_METHOD("ResolveRecord", "isqqt", "a(iqqay)t", bus_method_resolve_record
, SD_BUS_VTABLE_UNPRIVILEGED
),
1219 SD_BUS_METHOD("ResolveService", "isssit", "a(qqqsa(iiay)s)aayssst", bus_method_resolve_service
, SD_BUS_VTABLE_UNPRIVILEGED
),
1223 static int on_bus_retry(sd_event_source
*s
, usec_t usec
, void *userdata
) {
1224 Manager
*m
= userdata
;
1229 m
->bus_retry_event_source
= sd_event_source_unref(m
->bus_retry_event_source
);
1231 manager_connect_bus(m
);
1235 static int match_prepare_for_sleep(sd_bus_message
*message
, void *userdata
, sd_bus_error
*ret_error
) {
1236 Manager
*m
= userdata
;
1242 r
= sd_bus_message_read(message
, "b", &b
);
1244 log_debug_errno(r
, "Failed to parse PrepareForSleep signal: %m");
1251 log_debug("Coming back from suspend, verifying all RRs...");
1253 manager_verify_all(m
);
1257 int manager_connect_bus(Manager
*m
) {
1265 r
= sd_bus_default_system(&m
->bus
);
1267 /* We failed to connect? Yuck, we must be in early
1268 * boot. Let's try in 5s again. As soon as we have
1269 * kdbus we can stop doing this... */
1271 log_debug_errno(r
, "Failed to connect to bus, trying again in 5s: %m");
1273 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
);
1275 return log_error_errno(r
, "Failed to install bus reconnect time event: %m");
1280 r
= sd_bus_add_object_vtable(m
->bus
, NULL
, "/org/freedesktop/resolve1", "org.freedesktop.resolve1.Manager", resolve_vtable
, m
);
1282 return log_error_errno(r
, "Failed to register object: %m");
1284 r
= sd_bus_request_name(m
->bus
, "org.freedesktop.resolve1", 0);
1286 return log_error_errno(r
, "Failed to register name: %m");
1288 r
= sd_bus_attach_event(m
->bus
, m
->event
, 0);
1290 return log_error_errno(r
, "Failed to attach bus to event loop: %m");
1292 r
= sd_bus_add_match(m
->bus
, &m
->prepare_for_sleep_slot
,
1294 "sender='org.freedesktop.login1',"
1295 "interface='org.freedesktop.login1.Manager',"
1296 "member='PrepareForSleep',"
1297 "path='/org/freedesktop/login1'",
1298 match_prepare_for_sleep
,
1301 log_error_errno(r
, "Failed to add match for PrepareForSleep: %m");