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: %s",
65 dnssec_result_to_string(q
->answer_dnssec_result
));
67 case DNS_TRANSACTION_RCODE_FAILURE
: {
68 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
70 if (q
->answer_rcode
== DNS_RCODE_NXDOMAIN
)
71 sd_bus_error_setf(&error
, _BUS_ERROR_DNS
"NXDOMAIN", "'%s' not found", name
);
74 char p
[3]; /* the rcode is 4 bits long */
76 rc
= dns_rcode_to_string(q
->answer_rcode
);
78 sprintf(p
, "%i", q
->answer_rcode
);
82 n
= strjoina(_BUS_ERROR_DNS
, rc
);
83 sd_bus_error_setf(&error
, n
, "Could not resolve '%s', server or network returned error %s", name
, rc
);
86 return sd_bus_reply_method_error(q
->request
, &error
);
89 case DNS_TRANSACTION_NULL
:
90 case DNS_TRANSACTION_PENDING
:
91 case DNS_TRANSACTION_SUCCESS
:
93 assert_not_reached("Impossible state");
97 static int append_address(sd_bus_message
*reply
, DnsResourceRecord
*rr
, int ifindex
) {
103 r
= sd_bus_message_open_container(reply
, 'r', "iiay");
107 r
= sd_bus_message_append(reply
, "i", ifindex
);
111 if (rr
->key
->type
== DNS_TYPE_A
) {
112 r
= sd_bus_message_append(reply
, "i", AF_INET
);
116 r
= sd_bus_message_append_array(reply
, 'y', &rr
->a
.in_addr
, sizeof(struct in_addr
));
118 } else if (rr
->key
->type
== DNS_TYPE_AAAA
) {
119 r
= sd_bus_message_append(reply
, "i", AF_INET6
);
123 r
= sd_bus_message_append_array(reply
, 'y', &rr
->aaaa
.in6_addr
, sizeof(struct in6_addr
));
125 return -EAFNOSUPPORT
;
130 r
= sd_bus_message_close_container(reply
);
137 static void bus_method_resolve_hostname_complete(DnsQuery
*q
) {
138 _cleanup_(dns_resource_record_unrefp
) DnsResourceRecord
*canonical
= NULL
;
139 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
145 if (q
->state
!= DNS_TRANSACTION_SUCCESS
) {
146 r
= reply_query_state(q
);
150 r
= dns_query_process_cname(q
);
152 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
));
157 if (r
> 0) /* This was a cname, and the query was restarted. */
160 r
= sd_bus_message_new_method_return(q
->request
, &reply
);
164 r
= sd_bus_message_open_container(reply
, 'a', "(iiay)");
169 DnsResourceRecord
*rr
;
172 DNS_ANSWER_FOREACH_IFINDEX(rr
, ifindex
, q
->answer
) {
173 r
= dns_question_matches_rr(q
->question
, rr
, DNS_SEARCH_DOMAIN_NAME(q
->answer_search_domain
));
179 r
= append_address(reply
, rr
, ifindex
);
184 canonical
= dns_resource_record_ref(rr
);
191 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
));
195 r
= sd_bus_message_close_container(reply
);
199 /* Return the precise spelling and uppercasing and CNAME target reported by the server */
201 r
= sd_bus_message_append(
203 DNS_RESOURCE_KEY_NAME(canonical
->key
),
204 SD_RESOLVED_FLAGS_MAKE(q
->answer_protocol
, q
->answer_family
, q
->answer_authenticated
));
208 r
= sd_bus_send(q
->manager
->bus
, reply
, NULL
);
212 log_error_errno(r
, "Failed to send hostname reply: %m");
213 sd_bus_reply_method_errno(q
->request
, r
, NULL
);
219 static int check_ifindex_flags(int ifindex
, uint64_t *flags
, uint64_t ok
, sd_bus_error
*error
) {
223 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid interface index");
225 if (*flags
& ~(SD_RESOLVED_PROTOCOLS_ALL
|SD_RESOLVED_NO_CNAME
|ok
))
226 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid flags parameter");
228 if ((*flags
& SD_RESOLVED_PROTOCOLS_ALL
) == 0) /* If no protocol is enabled, enable all */
229 *flags
|= SD_RESOLVED_PROTOCOLS_ALL
;
234 static int bus_method_resolve_hostname(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
235 _cleanup_(dns_question_unrefp
) DnsQuestion
*question
= NULL
;
236 Manager
*m
= userdata
;
237 const char *hostname
;
246 assert_cc(sizeof(int) == sizeof(int32_t));
248 r
= sd_bus_message_read(message
, "isit", &ifindex
, &hostname
, &family
, &flags
);
252 if (!IN_SET(family
, AF_INET
, AF_INET6
, AF_UNSPEC
))
253 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Unknown address family %i", family
);
255 r
= dns_name_is_valid(hostname
);
259 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid hostname '%s'", hostname
);
261 r
= check_ifindex_flags(ifindex
, &flags
, SD_RESOLVED_NO_SEARCH
, error
);
265 r
= dns_question_new_address(&question
, family
, hostname
);
269 r
= dns_query_new(m
, &q
, question
, ifindex
, flags
);
273 q
->request
= sd_bus_message_ref(message
);
274 q
->request_family
= family
;
275 q
->complete
= bus_method_resolve_hostname_complete
;
277 r
= dns_query_bus_track(q
, message
);
292 static void bus_method_resolve_address_complete(DnsQuery
*q
) {
293 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
294 DnsResourceRecord
*rr
;
300 if (q
->state
!= DNS_TRANSACTION_SUCCESS
) {
301 r
= reply_query_state(q
);
305 r
= dns_query_process_cname(q
);
307 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
));
312 if (r
> 0) /* This was a cname, and the query was restarted. */
315 r
= sd_bus_message_new_method_return(q
->request
, &reply
);
319 r
= sd_bus_message_open_container(reply
, 'a', "(is)");
324 DNS_ANSWER_FOREACH_IFINDEX(rr
, ifindex
, q
->answer
) {
325 r
= dns_question_matches_rr(q
->question
, rr
, NULL
);
331 r
= sd_bus_message_append(reply
, "(is)", ifindex
, rr
->ptr
.name
);
340 _cleanup_free_
char *ip
= NULL
;
342 in_addr_to_string(q
->request_family
, &q
->request_address
, &ip
);
343 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
));
347 r
= sd_bus_message_close_container(reply
);
351 r
= sd_bus_message_append(reply
, "t", SD_RESOLVED_FLAGS_MAKE(q
->answer_protocol
, q
->answer_family
, q
->answer_authenticated
));
355 r
= sd_bus_send(q
->manager
->bus
, reply
, NULL
);
359 log_error_errno(r
, "Failed to send address reply: %m");
360 sd_bus_reply_method_errno(q
->request
, r
, NULL
);
366 static int bus_method_resolve_address(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
367 _cleanup_(dns_question_unrefp
) DnsQuestion
*question
= NULL
;
368 Manager
*m
= userdata
;
379 assert_cc(sizeof(int) == sizeof(int32_t));
381 r
= sd_bus_message_read(message
, "ii", &ifindex
, &family
);
385 if (!IN_SET(family
, AF_INET
, AF_INET6
))
386 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Unknown address family %i", family
);
388 r
= sd_bus_message_read_array(message
, 'y', &d
, &sz
);
392 if (sz
!= FAMILY_ADDRESS_SIZE(family
))
393 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid address size");
395 r
= sd_bus_message_read(message
, "t", &flags
);
399 r
= check_ifindex_flags(ifindex
, &flags
, 0, error
);
403 r
= dns_question_new_reverse(&question
, family
, d
);
407 r
= dns_query_new(m
, &q
, question
, ifindex
, flags
|SD_RESOLVED_NO_SEARCH
);
411 q
->request
= sd_bus_message_ref(message
);
412 q
->request_family
= family
;
413 memcpy(&q
->request_address
, d
, sz
);
414 q
->complete
= bus_method_resolve_address_complete
;
416 r
= dns_query_bus_track(q
, message
);
431 static int bus_message_append_rr(sd_bus_message
*m
, DnsResourceRecord
*rr
, int ifindex
) {
437 r
= sd_bus_message_open_container(m
, 'r', "iqqay");
441 r
= sd_bus_message_append(m
, "iqq",
448 r
= dns_resource_record_to_wire_format(rr
, false);
452 r
= sd_bus_message_append_array(m
, 'y', rr
->wire_format
, rr
->wire_format_size
);
456 return sd_bus_message_close_container(m
);
459 static void bus_method_resolve_record_complete(DnsQuery
*q
) {
460 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
466 if (q
->state
!= DNS_TRANSACTION_SUCCESS
) {
467 r
= reply_query_state(q
);
471 r
= dns_query_process_cname(q
);
473 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
));
478 if (r
> 0) /* Following a CNAME */
481 r
= sd_bus_message_new_method_return(q
->request
, &reply
);
485 r
= sd_bus_message_open_container(reply
, 'a', "(iqqay)");
490 DnsResourceRecord
*rr
;
493 DNS_ANSWER_FOREACH_IFINDEX(rr
, ifindex
, q
->answer
) {
494 r
= dns_question_matches_rr(q
->question
, rr
, NULL
);
500 r
= bus_message_append_rr(reply
, rr
, ifindex
);
509 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
));
513 r
= sd_bus_message_close_container(reply
);
517 r
= sd_bus_message_append(reply
, "t", SD_RESOLVED_FLAGS_MAKE(q
->answer_protocol
, q
->answer_family
, q
->answer_authenticated
));
521 r
= sd_bus_send(q
->manager
->bus
, reply
, NULL
);
525 log_error_errno(r
, "Failed to send record reply: %m");
526 sd_bus_reply_method_errno(q
->request
, r
, NULL
);
532 static int bus_method_resolve_record(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
533 _cleanup_(dns_resource_key_unrefp
) DnsResourceKey
*key
= NULL
;
534 _cleanup_(dns_question_unrefp
) DnsQuestion
*question
= NULL
;
535 Manager
*m
= userdata
;
536 uint16_t class, type
;
545 assert_cc(sizeof(int) == sizeof(int32_t));
547 r
= sd_bus_message_read(message
, "isqqt", &ifindex
, &name
, &class, &type
, &flags
);
551 r
= dns_name_is_valid(name
);
555 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid name '%s'", name
);
557 if (!dns_type_is_valid_query(type
))
558 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid RR type for query %" PRIu16
, type
);
560 r
= check_ifindex_flags(ifindex
, &flags
, 0, error
);
564 question
= dns_question_new(1);
568 key
= dns_resource_key_new(class, type
, name
);
572 r
= dns_question_add(question
, key
);
576 r
= dns_query_new(m
, &q
, question
, ifindex
, flags
|SD_RESOLVED_NO_SEARCH
);
580 q
->request
= sd_bus_message_ref(message
);
581 q
->complete
= bus_method_resolve_record_complete
;
583 r
= dns_query_bus_track(q
, message
);
598 static int append_srv(DnsQuery
*q
, sd_bus_message
*reply
, DnsResourceRecord
*rr
) {
599 _cleanup_(dns_resource_record_unrefp
) DnsResourceRecord
*canonical
= NULL
;
608 if (rr
->key
->type
!= DNS_TYPE_SRV
)
611 if ((q
->flags
& SD_RESOLVED_NO_ADDRESS
) == 0) {
612 /* First, let's see if we could find an appropriate A or AAAA
613 * record for the SRV record */
614 LIST_FOREACH(auxiliary_queries
, aux
, q
->auxiliary_queries
) {
615 DnsResourceRecord
*zz
;
617 if (aux
->state
!= DNS_TRANSACTION_SUCCESS
)
619 if (aux
->auxiliary_result
!= 0)
622 r
= dns_name_equal(dns_question_first_name(aux
->question
), rr
->srv
.name
);
628 DNS_ANSWER_FOREACH(zz
, aux
->answer
) {
630 r
= dns_question_matches_rr(aux
->question
, zz
, NULL
);
636 canonical
= dns_resource_record_ref(zz
);
644 /* Is there are successful A/AAAA lookup for this SRV RR? If not, don't add it */
649 r
= sd_bus_message_open_container(reply
, 'r', "qqqsa(iiay)s");
653 r
= sd_bus_message_append(
656 rr
->srv
.priority
, rr
->srv
.weight
, rr
->srv
.port
, rr
->srv
.name
);
660 r
= sd_bus_message_open_container(reply
, 'a', "(iiay)");
664 if ((q
->flags
& SD_RESOLVED_NO_ADDRESS
) == 0) {
665 LIST_FOREACH(auxiliary_queries
, aux
, q
->auxiliary_queries
) {
666 DnsResourceRecord
*zz
;
669 if (aux
->state
!= DNS_TRANSACTION_SUCCESS
)
671 if (aux
->auxiliary_result
!= 0)
674 r
= dns_name_equal(dns_question_first_name(aux
->question
), rr
->srv
.name
);
680 DNS_ANSWER_FOREACH_IFINDEX(zz
, ifindex
, aux
->answer
) {
682 r
= dns_question_matches_rr(aux
->question
, zz
, NULL
);
688 r
= append_address(reply
, zz
, ifindex
);
695 r
= sd_bus_message_close_container(reply
);
699 /* Note that above we appended the hostname as encoded in the
700 * SRV, and here the canonical hostname this maps to. */
701 r
= sd_bus_message_append(reply
, "s", canonical
? DNS_RESOURCE_KEY_NAME(canonical
->key
) : rr
->srv
.name
);
705 r
= sd_bus_message_close_container(reply
);
712 static int append_txt(sd_bus_message
*reply
, DnsResourceRecord
*rr
) {
720 if (rr
->key
->type
!= DNS_TYPE_TXT
)
723 LIST_FOREACH(items
, i
, rr
->txt
.items
) {
728 r
= sd_bus_message_append_array(reply
, 'y', i
->data
, i
->length
);
736 static void resolve_service_all_complete(DnsQuery
*q
) {
737 _cleanup_(dns_resource_record_unrefp
) DnsResourceRecord
*canonical
= NULL
;
738 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
739 _cleanup_free_
char *name
= NULL
, *type
= NULL
, *domain
= NULL
;
741 unsigned added
= false;
746 if (q
->block_all_complete
> 0)
749 if ((q
->flags
& SD_RESOLVED_NO_ADDRESS
) == 0) {
750 DnsQuery
*bad
= NULL
;
751 bool have_success
= false;
753 LIST_FOREACH(auxiliary_queries
, aux
, q
->auxiliary_queries
) {
755 switch (aux
->state
) {
757 case DNS_TRANSACTION_PENDING
:
758 /* If an auxiliary query is still pending, let's wait */
761 case DNS_TRANSACTION_SUCCESS
:
762 if (aux
->auxiliary_result
== 0)
775 /* We can only return one error, hence pick the last error we encountered */
779 if (bad
->state
== DNS_TRANSACTION_SUCCESS
) {
780 assert(bad
->auxiliary_result
!= 0);
782 if (bad
->auxiliary_result
== -ELOOP
) {
783 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
));
787 r
= bad
->auxiliary_result
;
791 r
= reply_query_state(bad
);
796 r
= sd_bus_message_new_method_return(q
->request
, &reply
);
800 r
= sd_bus_message_open_container(reply
, 'a', "(qqqsa(iiay)s)");
805 DnsResourceRecord
*rr
;
807 DNS_ANSWER_FOREACH(rr
, q
->answer
) {
808 r
= dns_question_matches_rr(q
->question
, rr
, NULL
);
814 r
= append_srv(q
, reply
, rr
);
817 if (r
== 0) /* not an SRV record */
821 canonical
= dns_resource_record_ref(rr
);
828 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
));
832 r
= sd_bus_message_close_container(reply
);
836 r
= sd_bus_message_open_container(reply
, 'a', "ay");
841 DnsResourceRecord
*rr
;
843 DNS_ANSWER_FOREACH(rr
, q
->answer
) {
844 r
= dns_question_matches_rr(q
->question
, rr
, NULL
);
850 r
= append_txt(reply
, rr
);
856 r
= sd_bus_message_close_container(reply
);
861 r
= dns_service_split(DNS_RESOURCE_KEY_NAME(canonical
->key
), &name
, &type
, &domain
);
865 r
= sd_bus_message_append(
869 SD_RESOLVED_FLAGS_MAKE(q
->answer_protocol
, q
->answer_family
, q
->answer_authenticated
));
873 r
= sd_bus_send(q
->manager
->bus
, reply
, NULL
);
877 log_error_errno(r
, "Failed to send service reply: %m");
878 sd_bus_reply_method_errno(q
->request
, r
, NULL
);
884 static void resolve_service_hostname_complete(DnsQuery
*q
) {
888 assert(q
->auxiliary_for
);
890 if (q
->state
!= DNS_TRANSACTION_SUCCESS
) {
891 resolve_service_all_complete(q
->auxiliary_for
);
895 r
= dns_query_process_cname(q
);
896 if (r
> 0) /* This was a cname, and the query was restarted. */
899 /* This auxiliary lookup is finished or failed, let's see if all are finished now. */
900 q
->auxiliary_result
= r
;
901 resolve_service_all_complete(q
->auxiliary_for
);
904 static int resolve_service_hostname(DnsQuery
*q
, DnsResourceRecord
*rr
, int ifindex
) {
905 _cleanup_(dns_question_unrefp
) DnsQuestion
*question
= NULL
;
912 assert(rr
->key
->type
== DNS_TYPE_SRV
);
914 /* OK, we found an SRV record for the service. Let's resolve
915 * the hostname included in it */
917 r
= dns_question_new_address(&question
, q
->request_family
, rr
->srv
.name
);
921 r
= dns_query_new(q
->manager
, &aux
, question
, ifindex
, q
->flags
|SD_RESOLVED_NO_SEARCH
);
925 aux
->request_family
= q
->request_family
;
926 aux
->complete
= resolve_service_hostname_complete
;
928 r
= dns_query_make_auxiliary(aux
, q
);
930 /* Too many auxiliary lookups? If so, don't complain,
931 * let's just not add this one, we already have more
940 /* Note that auxiliary queries do not track the original bus
941 * client, only the primary request does that. */
943 r
= dns_query_go(aux
);
954 static void bus_method_resolve_service_complete(DnsQuery
*q
) {
960 if (q
->state
!= DNS_TRANSACTION_SUCCESS
) {
961 r
= reply_query_state(q
);
965 r
= dns_query_process_cname(q
);
967 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
));
972 if (r
> 0) /* This was a cname, and the query was restarted. */
976 DnsResourceRecord
*rr
;
979 DNS_ANSWER_FOREACH_IFINDEX(rr
, ifindex
, q
->answer
) {
980 r
= dns_question_matches_rr(q
->question
, rr
, NULL
);
986 if (rr
->key
->type
!= DNS_TYPE_SRV
)
989 if ((q
->flags
& SD_RESOLVED_NO_ADDRESS
) == 0) {
990 q
->block_all_complete
++;
991 r
= resolve_service_hostname(q
, rr
, ifindex
);
992 q
->block_all_complete
--;
1003 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
));
1007 /* Maybe we are already finished? check now... */
1008 resolve_service_all_complete(q
);
1013 log_error_errno(r
, "Failed to send service reply: %m");
1014 sd_bus_reply_method_errno(q
->request
, r
, NULL
);
1020 static int bus_method_resolve_service(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1021 _cleanup_(dns_question_unrefp
) DnsQuestion
*question
= NULL
;
1022 const char *name
, *type
, *domain
, *joined
;
1023 _cleanup_free_
char *n
= NULL
;
1024 Manager
*m
= userdata
;
1025 int family
, ifindex
;
1033 assert_cc(sizeof(int) == sizeof(int32_t));
1035 r
= sd_bus_message_read(message
, "isssit", &ifindex
, &name
, &type
, &domain
, &family
, &flags
);
1039 if (!IN_SET(family
, AF_INET
, AF_INET6
, AF_UNSPEC
))
1040 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Unknown address family %i", family
);
1045 if (!dns_service_name_is_valid(name
))
1046 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid service name '%s'", name
);
1051 else if (!dns_srv_type_is_valid(type
))
1052 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid SRV service type '%s'", type
);
1054 r
= dns_name_is_valid(domain
);
1058 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid domain '%s'", domain
);
1061 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Service name cannot be specified without service type.");
1063 r
= check_ifindex_flags(ifindex
, &flags
, SD_RESOLVED_NO_TXT
|SD_RESOLVED_NO_ADDRESS
, error
);
1068 /* If the type is specified, we generate the full domain name to look up ourselves */
1069 r
= dns_service_join(name
, type
, domain
, &n
);
1075 /* If no type is specified, we assume the domain
1076 * contains the full domain name to lookup already */
1079 r
= dns_question_new_service(&question
, joined
, !(flags
& SD_RESOLVED_NO_TXT
));
1083 r
= dns_query_new(m
, &q
, question
, ifindex
, flags
|SD_RESOLVED_NO_SEARCH
);
1087 q
->request
= sd_bus_message_ref(message
);
1088 q
->request_family
= family
;
1089 q
->complete
= bus_method_resolve_service_complete
;
1091 r
= dns_query_bus_track(q
, message
);
1095 r
= dns_query_go(q
);
1106 static int append_dns_server(sd_bus_message
*reply
, DnsServer
*s
) {
1112 r
= sd_bus_message_open_container(reply
, 'r', "iiay");
1116 r
= sd_bus_message_append(reply
, "ii", s
->link
? s
->link
->ifindex
: 0, s
->family
);
1120 r
= sd_bus_message_append_array(reply
, 'y', &s
->address
, FAMILY_ADDRESS_SIZE(s
->family
));
1124 return sd_bus_message_close_container(reply
);
1127 static int bus_property_get_dns_servers(
1130 const char *interface
,
1131 const char *property
,
1132 sd_bus_message
*reply
,
1134 sd_bus_error
*error
) {
1136 Manager
*m
= userdata
;
1146 r
= sd_bus_message_open_container(reply
, 'a', "(iiay)");
1150 LIST_FOREACH(servers
, s
, m
->dns_servers
) {
1151 r
= append_dns_server(reply
, s
);
1158 HASHMAP_FOREACH(l
, m
->links
, i
) {
1159 LIST_FOREACH(servers
, s
, l
->dns_servers
) {
1160 r
= append_dns_server(reply
, s
);
1168 LIST_FOREACH(servers
, s
, m
->fallback_dns_servers
) {
1169 r
= append_dns_server(reply
, s
);
1175 return sd_bus_message_close_container(reply
);
1178 static int bus_property_get_search_domains(
1181 const char *interface
,
1182 const char *property
,
1183 sd_bus_message
*reply
,
1185 sd_bus_error
*error
) {
1187 Manager
*m
= userdata
;
1196 r
= sd_bus_message_open_container(reply
, 'a', "(is)");
1200 LIST_FOREACH(domains
, d
, m
->search_domains
) {
1201 r
= sd_bus_message_append(reply
, "(is)", 0, d
->name
);
1206 HASHMAP_FOREACH(l
, m
->links
, i
) {
1207 LIST_FOREACH(domains
, d
, l
->search_domains
) {
1208 r
= sd_bus_message_append(reply
, "is", l
->ifindex
, d
->name
);
1214 return sd_bus_message_close_container(reply
);
1217 static int bus_property_get_transaction_statistics(
1220 const char *interface
,
1221 const char *property
,
1222 sd_bus_message
*reply
,
1224 sd_bus_error
*error
) {
1226 Manager
*m
= userdata
;
1231 return sd_bus_message_append(reply
, "(tt)",
1232 (uint64_t) hashmap_size(m
->dns_transactions
),
1233 (uint64_t) m
->n_transactions_total
);
1236 static int bus_property_get_cache_statistics(
1239 const char *interface
,
1240 const char *property
,
1241 sd_bus_message
*reply
,
1243 sd_bus_error
*error
) {
1245 uint64_t size
= 0, hit
= 0, miss
= 0;
1246 Manager
*m
= userdata
;
1252 LIST_FOREACH(scopes
, s
, m
->dns_scopes
) {
1253 size
+= dns_cache_size(&s
->cache
);
1254 hit
+= s
->cache
.n_hit
;
1255 miss
+= s
->cache
.n_miss
;
1258 return sd_bus_message_append(reply
, "(ttt)", size
, hit
, miss
);
1261 static int bus_property_get_dnssec_statistics(
1264 const char *interface
,
1265 const char *property
,
1266 sd_bus_message
*reply
,
1268 sd_bus_error
*error
) {
1270 Manager
*m
= userdata
;
1275 return sd_bus_message_append(reply
, "(tttt)",
1276 (uint64_t) m
->n_dnssec_secure
,
1277 (uint64_t) m
->n_dnssec_insecure
,
1278 (uint64_t) m
->n_dnssec_bogus
,
1279 (uint64_t) m
->n_dnssec_indeterminate
);
1282 static int bus_method_reset_statistics(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1283 Manager
*m
= userdata
;
1289 LIST_FOREACH(scopes
, s
, m
->dns_scopes
)
1290 s
->cache
.n_hit
= s
->cache
.n_miss
= 0;
1292 m
->n_transactions_total
= 0;
1293 m
->n_dnssec_secure
= m
->n_dnssec_insecure
= m
->n_dnssec_bogus
= m
->n_dnssec_indeterminate
= 0;
1295 return sd_bus_reply_method_return(message
, NULL
);
1298 static const sd_bus_vtable resolve_vtable
[] = {
1299 SD_BUS_VTABLE_START(0),
1300 SD_BUS_PROPERTY("LLMNRHostname", "s", NULL
, offsetof(Manager
, llmnr_hostname
), 0),
1301 SD_BUS_PROPERTY("DNSServers", "a(iiay)", bus_property_get_dns_servers
, 0, 0),
1302 SD_BUS_PROPERTY("SearchDomains", "a(is)", bus_property_get_search_domains
, 0, 0),
1303 SD_BUS_PROPERTY("TransactionStatistics", "(tt)", bus_property_get_transaction_statistics
, 0, 0),
1304 SD_BUS_PROPERTY("CacheStatistics", "(ttt)", bus_property_get_cache_statistics
, 0, 0),
1305 SD_BUS_PROPERTY("DNSSECStatistics", "(tttt)", bus_property_get_dnssec_statistics
, 0, 0),
1307 SD_BUS_METHOD("ResolveHostname", "isit", "a(iiay)st", bus_method_resolve_hostname
, SD_BUS_VTABLE_UNPRIVILEGED
),
1308 SD_BUS_METHOD("ResolveAddress", "iiayt", "a(is)t", bus_method_resolve_address
, SD_BUS_VTABLE_UNPRIVILEGED
),
1309 SD_BUS_METHOD("ResolveRecord", "isqqt", "a(iqqay)t", bus_method_resolve_record
, SD_BUS_VTABLE_UNPRIVILEGED
),
1310 SD_BUS_METHOD("ResolveService", "isssit", "a(qqqsa(iiay)s)aayssst", bus_method_resolve_service
, SD_BUS_VTABLE_UNPRIVILEGED
),
1311 SD_BUS_METHOD("ResetStatistics", NULL
, NULL
, bus_method_reset_statistics
, 0),
1315 static int on_bus_retry(sd_event_source
*s
, usec_t usec
, void *userdata
) {
1316 Manager
*m
= userdata
;
1321 m
->bus_retry_event_source
= sd_event_source_unref(m
->bus_retry_event_source
);
1323 manager_connect_bus(m
);
1327 static int match_prepare_for_sleep(sd_bus_message
*message
, void *userdata
, sd_bus_error
*ret_error
) {
1328 Manager
*m
= userdata
;
1334 r
= sd_bus_message_read(message
, "b", &b
);
1336 log_debug_errno(r
, "Failed to parse PrepareForSleep signal: %m");
1343 log_debug("Coming back from suspend, verifying all RRs...");
1345 manager_verify_all(m
);
1349 int manager_connect_bus(Manager
*m
) {
1357 r
= sd_bus_default_system(&m
->bus
);
1359 /* We failed to connect? Yuck, we must be in early
1360 * boot. Let's try in 5s again. As soon as we have
1361 * kdbus we can stop doing this... */
1363 log_debug_errno(r
, "Failed to connect to bus, trying again in 5s: %m");
1365 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
);
1367 return log_error_errno(r
, "Failed to install bus reconnect time event: %m");
1372 r
= sd_bus_add_object_vtable(m
->bus
, NULL
, "/org/freedesktop/resolve1", "org.freedesktop.resolve1.Manager", resolve_vtable
, m
);
1374 return log_error_errno(r
, "Failed to register object: %m");
1376 r
= sd_bus_request_name(m
->bus
, "org.freedesktop.resolve1", 0);
1378 return log_error_errno(r
, "Failed to register name: %m");
1380 r
= sd_bus_attach_event(m
->bus
, m
->event
, 0);
1382 return log_error_errno(r
, "Failed to attach bus to event loop: %m");
1384 r
= sd_bus_add_match(m
->bus
, &m
->prepare_for_sleep_slot
,
1386 "sender='org.freedesktop.login1',"
1387 "interface='org.freedesktop.login1.Manager',"
1388 "member='PrepareForSleep',"
1389 "path='/org/freedesktop/login1'",
1390 match_prepare_for_sleep
,
1393 log_error_errno(r
, "Failed to add match for PrepareForSleep: %m");