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_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_bus_message_unref_ 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
));
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_bus_message_unref_ sd_bus_message
*reply
= NULL
;
290 DnsResourceRecord
*rr
;
296 if (q
->state
!= DNS_TRANSACTION_SUCCESS
) {
297 r
= reply_query_state(q
);
301 /* We don't process CNAME for PTR lookups. */
303 r
= sd_bus_message_new_method_return(q
->request
, &reply
);
307 r
= sd_bus_message_open_container(reply
, 'a', "(is)");
312 DNS_ANSWER_FOREACH_IFINDEX(rr
, ifindex
, q
->answer
) {
313 r
= dns_question_matches_rr(q
->question
, rr
, NULL
);
319 r
= sd_bus_message_append(reply
, "(is)", ifindex
, rr
->ptr
.name
);
328 _cleanup_free_
char *ip
= NULL
;
330 in_addr_to_string(q
->request_family
, &q
->request_address
, &ip
);
331 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
));
335 r
= sd_bus_message_close_container(reply
);
339 r
= sd_bus_message_append(reply
, "t", SD_RESOLVED_FLAGS_MAKE(q
->answer_protocol
, q
->answer_family
));
343 r
= sd_bus_send(q
->manager
->bus
, reply
, NULL
);
347 log_error_errno(r
, "Failed to send address reply: %m");
348 sd_bus_reply_method_errno(q
->request
, r
, NULL
);
354 static int bus_method_resolve_address(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
355 _cleanup_(dns_question_unrefp
) DnsQuestion
*question
= NULL
;
356 Manager
*m
= userdata
;
367 assert_cc(sizeof(int) == sizeof(int32_t));
369 r
= sd_bus_message_read(message
, "ii", &ifindex
, &family
);
373 if (!IN_SET(family
, AF_INET
, AF_INET6
))
374 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Unknown address family %i", family
);
376 r
= sd_bus_message_read_array(message
, 'y', &d
, &sz
);
380 if (sz
!= FAMILY_ADDRESS_SIZE(family
))
381 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid address size");
383 r
= sd_bus_message_read(message
, "t", &flags
);
387 r
= check_ifindex_flags(ifindex
, &flags
, 0, error
);
391 r
= dns_question_new_reverse(&question
, family
, d
);
395 r
= dns_query_new(m
, &q
, question
, ifindex
, flags
|SD_RESOLVED_NO_SEARCH
);
399 q
->request
= sd_bus_message_ref(message
);
400 q
->request_family
= family
;
401 memcpy(&q
->request_address
, d
, sz
);
402 q
->complete
= bus_method_resolve_address_complete
;
404 r
= dns_query_bus_track(q
, message
);
419 static int bus_message_append_rr(sd_bus_message
*m
, DnsResourceRecord
*rr
, int ifindex
) {
420 _cleanup_(dns_packet_unrefp
) DnsPacket
*p
= NULL
;
427 r
= sd_bus_message_open_container(m
, 'r', "iqqay");
431 r
= sd_bus_message_append(m
, "iqq",
438 r
= dns_packet_new(&p
, DNS_PROTOCOL_DNS
, 0);
442 p
->refuse_compression
= true;
444 r
= dns_packet_append_rr(p
, rr
, &start
);
448 r
= sd_bus_message_append_array(m
, 'y', DNS_PACKET_DATA(p
) + start
, p
->size
- start
);
452 return sd_bus_message_close_container(m
);
455 static void bus_method_resolve_record_complete(DnsQuery
*q
) {
456 _cleanup_bus_message_unref_ 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
));
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
));
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
);
1045 r
= dns_srv_type_verify(type
);
1049 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid SRV service type '%s'", type
);
1052 r
= dns_name_is_valid(domain
);
1056 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid domain '%s'", domain
);
1059 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Service name cannot be specified without service type.");
1061 r
= check_ifindex_flags(ifindex
, &flags
, SD_RESOLVED_NO_TXT
|SD_RESOLVED_NO_ADDRESS
, error
);
1066 /* If the type is specified, we generate the full domain name to look up ourselves */
1067 r
= dns_service_join(name
, type
, domain
, &n
);
1073 /* If no type is specified, we assume the domain
1074 * contains the full domain name to lookup already */
1077 r
= dns_question_new_service(&question
, joined
, !(flags
& SD_RESOLVED_NO_TXT
));
1081 r
= dns_query_new(m
, &q
, question
, ifindex
, flags
|SD_RESOLVED_NO_SEARCH
);
1085 q
->request
= sd_bus_message_ref(message
);
1086 q
->request_family
= family
;
1087 q
->complete
= bus_method_resolve_service_complete
;
1089 r
= dns_query_bus_track(q
, message
);
1093 r
= dns_query_go(q
);
1104 static int append_dns_server(sd_bus_message
*reply
, DnsServer
*s
) {
1110 r
= sd_bus_message_open_container(reply
, 'r', "iiay");
1114 r
= sd_bus_message_append(reply
, "ii", s
->link
? s
->link
->ifindex
: 0, s
->family
);
1118 r
= sd_bus_message_append_array(reply
, 'y', &s
->address
, FAMILY_ADDRESS_SIZE(s
->family
));
1122 return sd_bus_message_close_container(reply
);
1125 static int bus_property_get_dns_servers(
1128 const char *interface
,
1129 const char *property
,
1130 sd_bus_message
*reply
,
1132 sd_bus_error
*error
) {
1134 Manager
*m
= userdata
;
1144 r
= sd_bus_message_open_container(reply
, 'a', "(iiay)");
1148 LIST_FOREACH(servers
, s
, m
->dns_servers
) {
1149 r
= append_dns_server(reply
, s
);
1156 HASHMAP_FOREACH(l
, m
->links
, i
) {
1157 LIST_FOREACH(servers
, s
, l
->dns_servers
) {
1158 r
= append_dns_server(reply
, s
);
1166 LIST_FOREACH(servers
, s
, m
->fallback_dns_servers
) {
1167 r
= append_dns_server(reply
, s
);
1173 return sd_bus_message_close_container(reply
);
1176 static int bus_property_get_search_domains(
1179 const char *interface
,
1180 const char *property
,
1181 sd_bus_message
*reply
,
1183 sd_bus_error
*error
) {
1185 Manager
*m
= userdata
;
1194 r
= sd_bus_message_open_container(reply
, 'a', "(is)");
1198 LIST_FOREACH(domains
, d
, m
->search_domains
) {
1199 r
= sd_bus_message_append(reply
, "(is)", 0, d
->name
);
1204 HASHMAP_FOREACH(l
, m
->links
, i
) {
1205 LIST_FOREACH(domains
, d
, l
->search_domains
) {
1206 r
= sd_bus_message_append(reply
, "is", l
->ifindex
, d
->name
);
1212 return sd_bus_message_close_container(reply
);
1215 static const sd_bus_vtable resolve_vtable
[] = {
1216 SD_BUS_VTABLE_START(0),
1217 SD_BUS_PROPERTY("LLMNRHostname", "s", NULL
, offsetof(Manager
, llmnr_hostname
), 0),
1218 SD_BUS_PROPERTY("DNSServers", "a(iiay)", bus_property_get_dns_servers
, 0, 0),
1219 SD_BUS_PROPERTY("SearchDomains", "a(is)", bus_property_get_search_domains
, 0, 0),
1221 SD_BUS_METHOD("ResolveHostname", "isit", "a(iiay)st", bus_method_resolve_hostname
, SD_BUS_VTABLE_UNPRIVILEGED
),
1222 SD_BUS_METHOD("ResolveAddress", "iiayt", "a(is)t", bus_method_resolve_address
, SD_BUS_VTABLE_UNPRIVILEGED
),
1223 SD_BUS_METHOD("ResolveRecord", "isqqt", "a(iqqay)t", bus_method_resolve_record
, SD_BUS_VTABLE_UNPRIVILEGED
),
1224 SD_BUS_METHOD("ResolveService", "isssit", "a(qqqsa(iiay)s)aayssst", bus_method_resolve_service
, SD_BUS_VTABLE_UNPRIVILEGED
),
1228 static int on_bus_retry(sd_event_source
*s
, usec_t usec
, void *userdata
) {
1229 Manager
*m
= userdata
;
1234 m
->bus_retry_event_source
= sd_event_source_unref(m
->bus_retry_event_source
);
1236 manager_connect_bus(m
);
1240 static int match_prepare_for_sleep(sd_bus_message
*message
, void *userdata
, sd_bus_error
*ret_error
) {
1241 Manager
*m
= userdata
;
1247 r
= sd_bus_message_read(message
, "b", &b
);
1249 log_debug_errno(r
, "Failed to parse PrepareForSleep signal: %m");
1256 log_debug("Coming back from suspend, verifying all RRs...");
1258 manager_verify_all(m
);
1262 int manager_connect_bus(Manager
*m
) {
1270 r
= sd_bus_default_system(&m
->bus
);
1272 /* We failed to connect? Yuck, we must be in early
1273 * boot. Let's try in 5s again. As soon as we have
1274 * kdbus we can stop doing this... */
1276 log_debug_errno(r
, "Failed to connect to bus, trying again in 5s: %m");
1278 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
);
1280 return log_error_errno(r
, "Failed to install bus reconnect time event: %m");
1285 r
= sd_bus_add_object_vtable(m
->bus
, NULL
, "/org/freedesktop/resolve1", "org.freedesktop.resolve1.Manager", resolve_vtable
, m
);
1287 return log_error_errno(r
, "Failed to register object: %m");
1289 r
= sd_bus_request_name(m
->bus
, "org.freedesktop.resolve1", 0);
1291 return log_error_errno(r
, "Failed to register name: %m");
1293 r
= sd_bus_attach_event(m
->bus
, m
->event
, 0);
1295 return log_error_errno(r
, "Failed to attach bus to event loop: %m");
1297 r
= sd_bus_add_match(m
->bus
, &m
->prepare_for_sleep_slot
,
1299 "sender='org.freedesktop.login1',"
1300 "interface='org.freedesktop.login1.Manager',"
1301 "member='PrepareForSleep',"
1302 "path='/org/freedesktop/login1'",
1303 match_prepare_for_sleep
,
1306 log_error_errno(r
, "Failed to add match for PrepareForSleep: %m");