1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
5 #include "alloc-util.h"
6 #include "bus-common-errors.h"
7 #include "bus-get-properties.h"
8 #include "bus-locator.h"
9 #include "bus-log-control-api.h"
10 #include "bus-message-util.h"
11 #include "bus-object.h"
12 #include "bus-polkit.h"
14 #include "dns-domain.h"
15 #include "format-util.h"
16 #include "path-util.h"
17 #include "resolve-util.h"
18 #include "resolved-bus.h"
19 #include "resolved-def.h"
20 #include "resolved-dns-answer.h"
21 #include "resolved-dns-delegate.h"
22 #include "resolved-dns-delegate-bus.h"
23 #include "resolved-dns-dnssec.h"
24 #include "resolved-dns-packet.h"
25 #include "resolved-dns-query.h"
26 #include "resolved-dns-question.h"
27 #include "resolved-dns-rr.h"
28 #include "resolved-dns-scope.h"
29 #include "resolved-dns-search-domain.h"
30 #include "resolved-dns-server.h"
31 #include "resolved-dns-stream.h"
32 #include "resolved-dns-stub.h"
33 #include "resolved-dns-synthesize.h"
34 #include "resolved-dns-transaction.h"
35 #include "resolved-dnssd.h"
36 #include "resolved-dnssd-bus.h"
37 #include "resolved-link.h"
38 #include "resolved-link-bus.h"
39 #include "resolved-manager.h"
40 #include "resolved-resolv-conf.h"
42 #include "socket-netlink.h"
43 #include "string-util.h"
46 BUS_DEFINE_PROPERTY_GET_ENUM(bus_property_get_resolve_support
, resolve_support
, ResolveSupport
);
48 static int dns_query_new_for_bus(
51 DnsQuestion
*question_utf8
,
52 DnsQuestion
*question_idna
,
53 DnsPacket
*question_bypass
,
56 sd_bus_error
*error
) {
60 r
= dns_query_new(m
, ret
, question_utf8
, question_idna
, question_bypass
, ifindex
, flags
);
62 return sd_bus_error_set(error
, BUS_ERROR_DNS_REFUSED
, "DNS query type refused.");
66 static int query_on_bus_track(sd_bus_track
*t
, void *userdata
) {
67 DnsQuery
*q
= ASSERT_PTR(userdata
);
71 if (!DNS_TRANSACTION_IS_LIVE(q
->state
))
74 log_debug("Client of active query vanished, aborting query.");
75 dns_query_complete(q
, DNS_TRANSACTION_ABORTED
);
79 static int dns_query_bus_track(DnsQuery
*q
, sd_bus_message
*m
) {
86 r
= sd_bus_track_new(sd_bus_message_get_bus(m
), &q
->bus_track
, query_on_bus_track
, q
);
91 r
= sd_bus_track_add_sender(q
->bus_track
, m
);
98 static sd_bus_message
*dns_query_steal_request(DnsQuery
*q
) {
101 /* Find the main query, it's the one that owns the message */
102 while (q
->auxiliary_for
)
103 q
= q
->auxiliary_for
;
105 /* Let's take the request message out of the DnsQuery object, so that we never send requests twice */
106 return TAKE_PTR(q
->bus_request
);
109 _sd_printf_(3, 4) static int reply_method_errorf(
111 const char *error_name
,
115 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*req
= NULL
;
122 req
= dns_query_steal_request(query
);
123 if (!req
) /* No bus message set anymore? then we already replied already, let's not answer a second time */
126 va_start(ap
, format
);
127 r
= sd_bus_reply_method_errorfv(req
, error_name
, format
, ap
);
133 _sd_printf_(3, 4) static int reply_method_errnof(
139 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*req
= NULL
;
144 req
= dns_query_steal_request(query
);
145 if (!req
) /* No bus message set anymore? then we already replied already, let's not answer a second time */
151 va_start(ap
, format
);
152 r
= sd_bus_reply_method_errnofv(req
, err
, format
, ap
);
155 r
= sd_bus_reply_method_errno(req
, err
, NULL
);
160 static int reply_query_state(DnsQuery
*q
) {
165 case DNS_TRANSACTION_NO_SERVERS
:
166 return reply_method_errorf(q
, BUS_ERROR_NO_NAME_SERVERS
, "No appropriate name servers or networks for name found");
168 case DNS_TRANSACTION_TIMEOUT
:
169 return reply_method_errorf(q
, SD_BUS_ERROR_TIMEOUT
, "Query timed out");
171 case DNS_TRANSACTION_ATTEMPTS_MAX_REACHED
:
172 return reply_method_errorf(q
, SD_BUS_ERROR_TIMEOUT
, "All attempts to contact name servers or networks failed");
174 case DNS_TRANSACTION_INVALID_REPLY
:
175 return reply_method_errorf(q
, BUS_ERROR_INVALID_REPLY
, "Received invalid reply");
177 case DNS_TRANSACTION_ERRNO
:
178 return reply_method_errnof(q
, q
->answer_errno
, "Lookup failed due to system error: %m");
180 case DNS_TRANSACTION_ABORTED
:
181 return reply_method_errorf(q
, BUS_ERROR_ABORTED
, "Query aborted");
183 case DNS_TRANSACTION_DNSSEC_FAILED
:
184 return reply_method_errorf(q
, BUS_ERROR_DNSSEC_FAILED
, "DNSSEC validation failed: %s%s%s%s%s%s",
185 dnssec_result_to_string(q
->answer_dnssec_result
),
186 q
->answer_ede_rcode
>= 0 ? " (" : "",
187 q
->answer_ede_rcode
>= 0 ? FORMAT_DNS_EDE_RCODE(q
->answer_ede_rcode
) : "",
188 (q
->answer_ede_rcode
>= 0 && !isempty(q
->answer_ede_msg
)) ? ": " : "",
189 q
->answer_ede_rcode
>= 0 ? strempty(q
->answer_ede_msg
) : "",
190 q
->answer_ede_rcode
>= 0 ? ")" : "");
192 case DNS_TRANSACTION_NO_TRUST_ANCHOR
:
193 return reply_method_errorf(q
, BUS_ERROR_NO_TRUST_ANCHOR
, "No suitable trust anchor known");
195 case DNS_TRANSACTION_RR_TYPE_UNSUPPORTED
:
196 return reply_method_errorf(q
, BUS_ERROR_RR_TYPE_UNSUPPORTED
, "Server does not support requested resource record type");
198 case DNS_TRANSACTION_NETWORK_DOWN
:
199 return reply_method_errorf(q
, BUS_ERROR_NETWORK_DOWN
, "Network is down");
201 case DNS_TRANSACTION_NOT_FOUND
:
202 /* We return this as NXDOMAIN. This is only generated when a host doesn't implement LLMNR/TCP, and we
203 * thus quickly know that we cannot resolve an in-addr.arpa or ip6.arpa address. */
204 return reply_method_errorf(q
, BUS_ERROR_DNS_NXDOMAIN
, "'%s' not found", dns_query_string(q
));
206 case DNS_TRANSACTION_NO_SOURCE
:
207 return reply_method_errorf(q
, BUS_ERROR_NO_SOURCE
, "All suitable resolution sources turned off");
209 case DNS_TRANSACTION_STUB_LOOP
:
210 return reply_method_errorf(q
, BUS_ERROR_STUB_LOOP
, "Configured DNS server loops back to us");
212 case DNS_TRANSACTION_RCODE_FAILURE
: {
213 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
214 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*req
= NULL
;
216 req
= dns_query_steal_request(q
);
217 if (!req
) /* No bus message set anymore? then we already replied already, let's not answer a second time */
220 if (q
->answer_rcode
== DNS_RCODE_NXDOMAIN
)
221 sd_bus_error_setf(&error
, BUS_ERROR_DNS_NXDOMAIN
, "Name '%s' not found", dns_query_string(q
));
225 rc
= FORMAT_DNS_RCODE(q
->answer_rcode
);
226 n
= strjoina(_BUS_ERROR_DNS
, rc
);
227 sd_bus_error_setf(&error
, n
, "Could not resolve '%s', server or network returned error: %s%s%s%s%s%s",
228 dns_query_string(q
), rc
,
229 q
->answer_ede_rcode
>= 0 ? " (" : "",
230 q
->answer_ede_rcode
>= 0 ? FORMAT_DNS_EDE_RCODE(q
->answer_ede_rcode
) : "",
231 (q
->answer_ede_rcode
>= 0 && !isempty(q
->answer_ede_msg
)) ? ": " : "",
232 q
->answer_ede_rcode
>= 0 ? strempty(q
->answer_ede_msg
) : "",
233 q
->answer_ede_rcode
>= 0 ? ")" : "");
236 return sd_bus_reply_method_error(req
, &error
);
239 case DNS_TRANSACTION_NULL
:
240 case DNS_TRANSACTION_PENDING
:
241 case DNS_TRANSACTION_VALIDATING
:
242 case DNS_TRANSACTION_SUCCESS
:
244 assert_not_reached();
248 static int append_address(sd_bus_message
*reply
, DnsResourceRecord
*rr
, int ifindex
) {
254 r
= sd_bus_message_open_container(reply
, 'r', "iiay");
258 r
= sd_bus_message_append(reply
, "i", ifindex
);
262 if (rr
->key
->type
== DNS_TYPE_A
) {
263 r
= sd_bus_message_append(reply
, "i", AF_INET
);
267 r
= sd_bus_message_append_array(reply
, 'y', &rr
->a
.in_addr
, sizeof(struct in_addr
));
269 } else if (rr
->key
->type
== DNS_TYPE_AAAA
) {
270 r
= sd_bus_message_append(reply
, "i", AF_INET6
);
274 r
= sd_bus_message_append_array(reply
, 'y', &rr
->aaaa
.in6_addr
, sizeof(struct in6_addr
));
276 return -EAFNOSUPPORT
;
281 r
= sd_bus_message_close_container(reply
);
288 static void bus_method_resolve_hostname_complete(DnsQuery
*query
) {
289 _cleanup_(dns_resource_record_unrefp
) DnsResourceRecord
*canonical
= NULL
;
290 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
291 _cleanup_(dns_query_freep
) DnsQuery
*q
= query
;
292 _cleanup_free_
char *normalized
= NULL
;
293 DnsQuestion
*question
;
294 DnsResourceRecord
*rr
;
300 if (q
->state
!= DNS_TRANSACTION_SUCCESS
) {
301 r
= reply_query_state(q
);
305 r
= dns_query_process_cname_many(q
);
307 r
= reply_method_errorf(q
, BUS_ERROR_CNAME_LOOP
, "CNAME loop detected, or CNAME resolving disabled on '%s'", dns_query_string(q
));
312 if (r
== DNS_QUERY_CNAME
) {
313 /* This was a cname, and the query was restarted. */
318 r
= sd_bus_message_new_method_return(q
->bus_request
, &reply
);
322 r
= sd_bus_message_open_container(reply
, 'a', "(iiay)");
326 question
= dns_query_question_for_protocol(q
, q
->answer_protocol
);
328 DNS_ANSWER_FOREACH_IFINDEX(rr
, ifindex
, q
->answer
) {
330 r
= dns_question_matches_rr(question
, rr
, DNS_SEARCH_DOMAIN_NAME(q
->answer_search_domain
));
336 r
= append_address(reply
, rr
, ifindex
);
341 canonical
= dns_resource_record_ref(rr
);
347 r
= reply_method_errorf(q
, BUS_ERROR_NO_SUCH_RR
, "'%s' does not have any RR of the requested type", dns_query_string(q
));
351 r
= sd_bus_message_close_container(reply
);
355 /* The key names are not necessarily normalized, make sure that they are when we return them to our
358 r
= dns_name_normalize(dns_resource_key_name(canonical
->key
), 0, &normalized
);
362 /* Return the precise spelling and uppercasing and CNAME target reported by the server */
363 r
= sd_bus_message_append(
366 dns_query_reply_flags_make(q
));
370 q
->bus_request
= sd_bus_message_unref(q
->bus_request
);
371 r
= sd_bus_send(q
->manager
->bus
, reply
, NULL
);
375 log_error_errno(r
, "Failed to send hostname reply: %m");
376 (void) reply_method_errnof(q
, r
, NULL
);
380 static int parse_as_address(sd_bus_message
*m
, int ifindex
, const char *hostname
, int family
, uint64_t flags
) {
381 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
382 _cleanup_free_
char *canonical
= NULL
;
383 union in_addr_union parsed
;
384 int r
, ff
, parsed_ifindex
= 0;
386 /* Check if the hostname is actually already an IP address formatted as string. In that case just parse it,
387 * let's not attempt to look it up. */
389 r
= in_addr_ifindex_from_string_auto(hostname
, &ff
, &parsed
, &parsed_ifindex
);
390 if (r
< 0) /* not an address */
393 if (family
!= AF_UNSPEC
&& ff
!= family
)
394 return sd_bus_reply_method_errorf(m
, BUS_ERROR_NO_SUCH_RR
, "The specified address is not of the requested family.");
395 if (ifindex
> 0 && parsed_ifindex
> 0 && parsed_ifindex
!= ifindex
)
396 return sd_bus_reply_method_errorf(m
, BUS_ERROR_NO_SUCH_RR
, "The specified address interface index does not match requested interface.");
398 if (parsed_ifindex
> 0)
399 ifindex
= parsed_ifindex
;
401 r
= sd_bus_message_new_method_return(m
, &reply
);
405 r
= sd_bus_message_open_container(reply
, 'a', "(iiay)");
409 r
= sd_bus_message_open_container(reply
, 'r', "iiay");
413 r
= sd_bus_message_append(reply
, "ii", ifindex
, ff
);
417 r
= sd_bus_message_append_array(reply
, 'y', &parsed
, FAMILY_ADDRESS_SIZE(ff
));
421 r
= sd_bus_message_close_container(reply
);
425 r
= sd_bus_message_close_container(reply
);
429 /* When an IP address is specified we just return it as canonical name, in order to avoid a DNS
430 * look-up. However, we reformat it to make sure it's in a truly canonical form (i.e. on IPv6 the inner
431 * omissions are always done the same way). */
432 r
= in_addr_ifindex_to_string(ff
, &parsed
, ifindex
, &canonical
);
436 r
= sd_bus_message_append(reply
, "st", canonical
,
437 SD_RESOLVED_FLAGS_MAKE(dns_synthesize_protocol(flags
), ff
, true, true) |
438 SD_RESOLVED_SYNTHETIC
);
442 return sd_bus_send(sd_bus_message_get_bus(m
), reply
, NULL
);
445 void bus_client_log(sd_bus_message
*m
, const char *what
) {
446 _cleanup_(sd_bus_creds_unrefp
) sd_bus_creds
*creds
= NULL
;
447 const char *comm
= NULL
;
448 uid_t uid
= UID_INVALID
;
458 r
= sd_bus_query_sender_creds(m
, SD_BUS_CREDS_PID
|SD_BUS_CREDS_UID
|SD_BUS_CREDS_COMM
|SD_BUS_CREDS_AUGMENT
, &creds
);
460 return (void) log_debug_errno(r
, "Failed to query client credentials, ignoring: %m");
462 (void) sd_bus_creds_get_uid(creds
, &uid
);
463 (void) sd_bus_creds_get_pid(creds
, &pid
);
464 (void) sd_bus_creds_get_comm(creds
, &comm
);
466 log_debug("D-Bus %s request from client PID " PID_FMT
" (%s) with UID " UID_FMT
,
467 what
, pid
, strna(comm
), uid
);
470 static int bus_method_resolve_hostname(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
471 _cleanup_(dns_question_unrefp
) DnsQuestion
*question_idna
= NULL
, *question_utf8
= NULL
;
472 _cleanup_(dns_query_freep
) DnsQuery
*q
= NULL
;
473 Manager
*m
= ASSERT_PTR(userdata
);
474 const char *hostname
;
481 assert_cc(sizeof(int) == sizeof(int32_t));
483 r
= sd_bus_message_read(message
, "isit", &ifindex
, &hostname
, &family
, &flags
);
488 return sd_bus_error_set(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid interface index");
490 if (!IN_SET(family
, AF_INET
, AF_INET6
, AF_UNSPEC
))
491 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Unknown address family %i", family
);
493 if (validate_and_mangle_query_flags(m
, &flags
, hostname
, SD_RESOLVED_NO_SEARCH
) < 0)
494 return sd_bus_error_set(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid flags parameter");
496 r
= parse_as_address(message
, ifindex
, hostname
, family
, flags
);
500 r
= dns_name_is_valid(hostname
);
504 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid hostname '%s'", hostname
);
506 r
= dns_question_new_address(&question_utf8
, family
, hostname
, false);
510 r
= dns_question_new_address(&question_idna
, family
, hostname
, true);
511 if (r
< 0 && r
!= -EALREADY
)
514 bus_client_log(message
, "hostname resolution");
516 r
= dns_query_new_for_bus(m
, &q
, question_utf8
, question_idna
?: question_utf8
, NULL
, ifindex
, flags
, error
);
520 q
->bus_request
= sd_bus_message_ref(message
);
521 q
->request_family
= family
;
522 q
->complete
= bus_method_resolve_hostname_complete
;
524 r
= dns_query_bus_track(q
, message
);
536 static void bus_method_resolve_address_complete(DnsQuery
*query
) {
537 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
538 _cleanup_(dns_query_freep
) DnsQuery
*q
= query
;
539 DnsQuestion
*question
;
540 DnsResourceRecord
*rr
;
546 if (q
->state
!= DNS_TRANSACTION_SUCCESS
) {
547 r
= reply_query_state(q
);
551 r
= dns_query_process_cname_many(q
);
553 r
= reply_method_errorf(q
, BUS_ERROR_CNAME_LOOP
, "CNAME loop detected, or CNAME resolving disabled on '%s'", dns_query_string(q
));
558 if (r
== DNS_QUERY_CNAME
) {
559 /* This was a cname, and the query was restarted. */
564 r
= sd_bus_message_new_method_return(q
->bus_request
, &reply
);
568 r
= sd_bus_message_open_container(reply
, 'a', "(is)");
572 question
= dns_query_question_for_protocol(q
, q
->answer_protocol
);
574 DNS_ANSWER_FOREACH_IFINDEX(rr
, ifindex
, q
->answer
) {
575 _cleanup_free_
char *normalized
= NULL
;
577 r
= dns_question_matches_rr(question
, rr
, NULL
);
583 r
= dns_name_normalize(rr
->ptr
.name
, 0, &normalized
);
587 r
= sd_bus_message_append(reply
, "(is)", ifindex
, normalized
);
595 r
= reply_method_errorf(q
, BUS_ERROR_NO_SUCH_RR
,
596 "Address %s does not have any RR of requested type",
597 IN_ADDR_TO_STRING(q
->request_family
, &q
->request_address
));
601 r
= sd_bus_message_close_container(reply
);
605 r
= sd_bus_message_append(reply
, "t", dns_query_reply_flags_make(q
));
609 q
->bus_request
= sd_bus_message_unref(q
->bus_request
);
610 r
= sd_bus_send(q
->manager
->bus
, reply
, NULL
);
614 log_error_errno(r
, "Failed to send address reply: %m");
615 (void) reply_method_errnof(q
, r
, NULL
);
619 static int bus_method_resolve_address(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
620 _cleanup_(dns_question_unrefp
) DnsQuestion
*question
= NULL
;
621 _cleanup_(dns_query_freep
) DnsQuery
*q
= NULL
;
622 Manager
*m
= ASSERT_PTR(userdata
);
623 union in_addr_union a
;
630 assert_cc(sizeof(int) == sizeof(int32_t));
632 r
= sd_bus_message_read(message
, "i", &ifindex
);
636 r
= bus_message_read_in_addr_auto(message
, error
, &family
, &a
);
640 r
= sd_bus_message_read(message
, "t", &flags
);
645 return sd_bus_error_set(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid interface index");
647 if (validate_and_mangle_query_flags(m
, &flags
, /* name = */ NULL
, /* ok = */ 0) < 0)
648 return sd_bus_error_set(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid flags parameter");
650 r
= dns_question_new_reverse(&question
, family
, &a
);
654 bus_client_log(message
, "address resolution");
656 r
= dns_query_new_for_bus(m
, &q
, question
, question
, NULL
, ifindex
, flags
|SD_RESOLVED_NO_SEARCH
, error
);
660 q
->bus_request
= sd_bus_message_ref(message
);
661 q
->request_family
= family
;
662 q
->request_address
= a
;
663 q
->complete
= bus_method_resolve_address_complete
;
665 r
= dns_query_bus_track(q
, message
);
677 static int bus_message_append_rr(sd_bus_message
*m
, DnsResourceRecord
*rr
, int ifindex
) {
683 r
= sd_bus_message_open_container(m
, 'r', "iqqay");
687 r
= sd_bus_message_append(m
, "iqq",
694 r
= dns_resource_record_to_wire_format(rr
, false);
698 r
= sd_bus_message_append_array(m
, 'y', rr
->wire_format
, rr
->wire_format_size
);
702 return sd_bus_message_close_container(m
);
705 static void bus_method_resolve_record_complete(DnsQuery
*query
) {
706 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
707 _cleanup_(dns_query_freep
) DnsQuery
*q
= query
;
708 DnsResourceRecord
*rr
;
709 DnsQuestion
*question
;
716 if (q
->state
!= DNS_TRANSACTION_SUCCESS
) {
717 r
= reply_query_state(q
);
721 r
= dns_query_process_cname_many(q
);
723 r
= reply_method_errorf(q
, BUS_ERROR_CNAME_LOOP
, "CNAME loop detected, or CNAME resolving disabled on '%s'", dns_query_string(q
));
728 if (r
== DNS_QUERY_CNAME
) {
729 /* This was a cname, and the query was restarted. */
734 r
= sd_bus_message_new_method_return(q
->bus_request
, &reply
);
738 r
= sd_bus_message_open_container(reply
, 'a', "(iqqay)");
742 question
= dns_query_question_for_protocol(q
, q
->answer_protocol
);
744 DNS_ANSWER_FOREACH_IFINDEX(rr
, ifindex
, q
->answer
) {
745 r
= dns_question_matches_rr(question
, rr
, NULL
);
751 r
= bus_message_append_rr(reply
, rr
, ifindex
);
759 r
= reply_method_errorf(q
, BUS_ERROR_NO_SUCH_RR
, "Name '%s' does not have any RR of the requested type", dns_query_string(q
));
763 r
= sd_bus_message_close_container(reply
);
767 r
= sd_bus_message_append(reply
, "t", dns_query_reply_flags_make(q
));
771 q
->bus_request
= sd_bus_message_unref(q
->bus_request
);
772 r
= sd_bus_send(q
->manager
->bus
, reply
, NULL
);
776 log_error_errno(r
, "Failed to send record reply: %m");
777 (void) reply_method_errnof(q
, r
, NULL
);
781 static int bus_method_resolve_record(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
782 _cleanup_(dns_resource_key_unrefp
) DnsResourceKey
*key
= NULL
;
783 _cleanup_(dns_question_unrefp
) DnsQuestion
*question
= NULL
;
784 _cleanup_(dns_query_freep
) DnsQuery
*q
= NULL
;
785 Manager
*m
= ASSERT_PTR(userdata
);
786 uint16_t class, type
;
793 assert_cc(sizeof(int) == sizeof(int32_t));
795 r
= sd_bus_message_read(message
, "isqqt", &ifindex
, &name
, &class, &type
, &flags
);
800 return sd_bus_error_set(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid interface index");
802 r
= dns_name_is_valid(name
);
806 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid name '%s'", name
);
808 if (!dns_type_is_valid_query(type
))
809 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Specified resource record type %" PRIu16
" may not be used in a query.", type
);
810 if (dns_type_is_zone_transfer(type
))
811 return sd_bus_error_set(error
, SD_BUS_ERROR_NOT_SUPPORTED
, "Zone transfers not permitted via this programming interface.");
812 if (dns_type_is_obsolete(type
))
813 return sd_bus_error_setf(error
, SD_BUS_ERROR_NOT_SUPPORTED
, "Specified DNS resource record type %" PRIu16
" is obsolete.", type
);
815 if (validate_and_mangle_query_flags(m
, &flags
, name
, SD_RESOLVED_NO_SEARCH
) < 0)
816 return sd_bus_error_set(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid flags parameter");
818 question
= dns_question_new(1);
822 key
= dns_resource_key_new(class, type
, name
);
826 r
= dns_question_add(question
, key
, 0);
830 bus_client_log(message
, "resource record resolution");
832 /* Setting SD_RESOLVED_CLAMP_TTL: let's request that the TTL is fixed up for locally cached entries,
833 * after all we return it in the wire format blob. */
834 r
= dns_query_new_for_bus(m
, &q
, question
, question
, NULL
, ifindex
, flags
|SD_RESOLVED_NO_SEARCH
|SD_RESOLVED_CLAMP_TTL
, error
);
838 q
->bus_request
= sd_bus_message_ref(message
);
839 q
->complete
= bus_method_resolve_record_complete
;
841 r
= dns_query_bus_track(q
, message
);
853 static int append_srv(DnsQuery
*q
, sd_bus_message
*reply
, DnsResourceRecord
*rr
) {
854 _cleanup_(dns_resource_record_unrefp
) DnsResourceRecord
*canonical
= NULL
;
855 _cleanup_free_
char *normalized
= NULL
;
863 if (rr
->key
->type
!= DNS_TYPE_SRV
)
866 if ((q
->flags
& SD_RESOLVED_NO_ADDRESS
) == 0) {
867 /* First, let's see if we could find an appropriate A or AAAA
868 * record for the SRV record */
869 LIST_FOREACH(auxiliary_queries
, aux
, q
->auxiliary_queries
) {
870 DnsResourceRecord
*zz
;
871 DnsQuestion
*question
;
873 if (aux
->state
!= DNS_TRANSACTION_SUCCESS
)
875 if (aux
->auxiliary_result
!= 0)
878 question
= dns_query_question_for_protocol(aux
, aux
->answer_protocol
);
880 r
= dns_name_equal(dns_question_first_name(question
), rr
->srv
.name
);
886 DNS_ANSWER_FOREACH(zz
, aux
->answer
) {
888 r
= dns_question_matches_rr(question
, zz
, NULL
);
894 canonical
= dns_resource_record_ref(zz
);
902 /* Is there are successful A/AAAA lookup for this SRV RR? If not, don't add it */
907 r
= sd_bus_message_open_container(reply
, 'r', "qqqsa(iiay)s");
911 r
= dns_name_normalize(rr
->srv
.name
, 0, &normalized
);
915 r
= sd_bus_message_append(
918 rr
->srv
.priority
, rr
->srv
.weight
, rr
->srv
.port
, normalized
);
922 r
= sd_bus_message_open_container(reply
, 'a', "(iiay)");
926 if ((q
->flags
& SD_RESOLVED_NO_ADDRESS
) == 0) {
927 LIST_FOREACH(auxiliary_queries
, aux
, q
->auxiliary_queries
) {
928 DnsResourceRecord
*zz
;
929 DnsQuestion
*question
;
932 if (aux
->state
!= DNS_TRANSACTION_SUCCESS
)
934 if (aux
->auxiliary_result
!= 0)
937 question
= dns_query_question_for_protocol(aux
, aux
->answer_protocol
);
939 r
= dns_name_equal(dns_question_first_name(question
), rr
->srv
.name
);
945 DNS_ANSWER_FOREACH_IFINDEX(zz
, ifindex
, aux
->answer
) {
947 r
= dns_question_matches_rr(question
, zz
, NULL
);
953 r
= append_address(reply
, zz
, ifindex
);
960 r
= sd_bus_message_close_container(reply
);
965 normalized
= mfree(normalized
);
967 r
= dns_name_normalize(dns_resource_key_name(canonical
->key
), 0, &normalized
);
972 /* Note that above we appended the hostname as encoded in the
973 * SRV, and here the canonical hostname this maps to. */
974 r
= sd_bus_message_append(reply
, "s", normalized
);
978 r
= sd_bus_message_close_container(reply
);
985 static int append_txt(sd_bus_message
*reply
, DnsResourceRecord
*rr
) {
992 if (rr
->key
->type
!= DNS_TYPE_TXT
)
995 LIST_FOREACH(items
, i
, rr
->txt
.items
) {
1000 r
= sd_bus_message_append_array(reply
, 'y', i
->data
, i
->length
);
1008 static void resolve_service_all_complete(DnsQuery
*query
) {
1009 _cleanup_(dns_resource_record_unrefp
) DnsResourceRecord
*canonical
= NULL
;
1010 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
1011 _cleanup_free_
char *name
= NULL
, *type
= NULL
, *domain
= NULL
;
1012 _cleanup_(dns_query_freep
) DnsQuery
*q
= query
;
1013 DnsQuestion
*question
;
1014 DnsResourceRecord
*rr
;
1020 if (q
->block_all_complete
> 0) {
1025 if ((q
->flags
& SD_RESOLVED_NO_ADDRESS
) == 0) {
1026 DnsQuery
*bad
= NULL
;
1027 bool have_success
= false;
1029 LIST_FOREACH(auxiliary_queries
, aux
, q
->auxiliary_queries
) {
1031 switch (aux
->state
) {
1033 case DNS_TRANSACTION_PENDING
:
1034 /* If an auxiliary query is still pending, let's wait */
1038 case DNS_TRANSACTION_SUCCESS
:
1039 if (aux
->auxiliary_result
== 0)
1040 have_success
= true;
1050 if (!have_success
) {
1051 /* We can only return one error, hence pick the last error we encountered */
1055 if (bad
->state
== DNS_TRANSACTION_SUCCESS
) {
1056 assert(bad
->auxiliary_result
!= 0);
1058 if (bad
->auxiliary_result
== -ELOOP
) {
1059 r
= reply_method_errorf(q
, BUS_ERROR_CNAME_LOOP
, "CNAME loop detected, or CNAME resolving disabled on '%s'", dns_query_string(bad
));
1063 assert(bad
->auxiliary_result
< 0);
1064 r
= bad
->auxiliary_result
;
1068 r
= reply_query_state(bad
);
1073 r
= sd_bus_message_new_method_return(q
->bus_request
, &reply
);
1077 r
= sd_bus_message_open_container(reply
, 'a', "(qqqsa(iiay)s)");
1081 question
= dns_query_question_for_protocol(q
, q
->answer_protocol
);
1083 DNS_ANSWER_FOREACH(rr
, q
->answer
) {
1084 r
= dns_question_matches_rr(question
, rr
, NULL
);
1090 r
= append_srv(q
, reply
, rr
);
1093 if (r
== 0) /* not an SRV record */
1097 canonical
= dns_resource_record_ref(rr
);
1103 r
= reply_method_errorf(q
, BUS_ERROR_NO_SUCH_RR
, "'%s' does not have any RR of the requested type", dns_query_string(q
));
1107 r
= sd_bus_message_close_container(reply
);
1111 r
= sd_bus_message_open_container(reply
, 'a', "ay");
1115 DNS_ANSWER_FOREACH(rr
, q
->answer
) {
1116 r
= dns_question_matches_rr(question
, rr
, NULL
);
1122 r
= append_txt(reply
, rr
);
1127 r
= sd_bus_message_close_container(reply
);
1132 r
= dns_service_split(dns_resource_key_name(canonical
->key
), &name
, &type
, &domain
);
1136 if (isempty(type
)) {
1137 r
= reply_method_errorf(q
, BUS_ERROR_INCONSISTENT_SERVICE_RECORDS
, "'%s' does not provide a consistent set of service resource records", dns_query_string(q
));
1141 r
= sd_bus_message_append(
1145 dns_query_reply_flags_make(q
));
1149 q
->bus_request
= sd_bus_message_unref(q
->bus_request
);
1150 r
= sd_bus_send(q
->manager
->bus
, reply
, NULL
);
1154 log_error_errno(r
, "Failed to send service reply: %m");
1155 (void) reply_method_errnof(q
, r
, NULL
);
1159 static void resolve_service_hostname_complete(DnsQuery
*q
) {
1163 assert(q
->auxiliary_for
);
1165 if (q
->state
!= DNS_TRANSACTION_SUCCESS
) {
1166 resolve_service_all_complete(q
->auxiliary_for
);
1170 r
= dns_query_process_cname_many(q
);
1171 if (r
== DNS_QUERY_CNAME
) /* This was a cname, and the query was restarted. */
1174 /* This auxiliary lookup is finished or failed, let's see if all are finished now. */
1175 q
->auxiliary_result
= r
< 0 ? r
: 0;
1176 resolve_service_all_complete(q
->auxiliary_for
);
1179 static int resolve_service_hostname(DnsQuery
*q
, DnsResourceRecord
*rr
, int ifindex
) {
1180 _cleanup_(dns_question_unrefp
) DnsQuestion
*question
= NULL
;
1181 _cleanup_(dns_query_freep
) DnsQuery
*aux
= NULL
;
1187 assert(rr
->key
->type
== DNS_TYPE_SRV
);
1189 /* OK, we found an SRV record for the service. Let's resolve
1190 * the hostname included in it */
1192 r
= dns_question_new_address(&question
, q
->request_family
, rr
->srv
.name
, false);
1196 r
= dns_query_new(q
->manager
, &aux
, question
, question
, NULL
, ifindex
, q
->flags
|SD_RESOLVED_NO_SEARCH
);
1198 return reply_method_errorf(q
, BUS_ERROR_DNS_REFUSED
, "DNS query type refused.");
1202 aux
->request_family
= q
->request_family
;
1203 aux
->complete
= resolve_service_hostname_complete
;
1205 r
= dns_query_make_auxiliary(aux
, q
);
1207 /* Too many auxiliary lookups? If so, don't complain,
1208 * let's just not add this one, we already have more
1214 /* Note that auxiliary queries do not track the original bus
1215 * client, only the primary request does that. */
1217 r
= dns_query_go(aux
);
1225 static void bus_method_resolve_service_complete(DnsQuery
*query
) {
1226 _cleanup_(dns_query_freep
) DnsQuery
*q
= query
;
1227 bool has_root_domain
= false;
1228 DnsResourceRecord
*rr
;
1229 DnsQuestion
*question
;
1235 if (q
->state
!= DNS_TRANSACTION_SUCCESS
) {
1236 r
= reply_query_state(q
);
1240 r
= dns_query_process_cname_many(q
);
1242 r
= reply_method_errorf(q
, BUS_ERROR_CNAME_LOOP
, "CNAME loop detected, or CNAME resolving disabled on '%s'", dns_query_string(q
));
1247 if (r
== DNS_QUERY_CNAME
) {
1248 /* This was a cname, and the query was restarted. */
1253 question
= dns_query_question_for_protocol(q
, q
->answer_protocol
);
1255 DNS_ANSWER_FOREACH_IFINDEX(rr
, ifindex
, q
->answer
) {
1256 r
= dns_question_matches_rr(question
, rr
, NULL
);
1262 if (rr
->key
->type
!= DNS_TYPE_SRV
)
1265 if (dns_name_is_root(rr
->srv
.name
)) {
1266 has_root_domain
= true;
1270 if ((q
->flags
& SD_RESOLVED_NO_ADDRESS
) == 0) {
1271 q
->block_all_complete
++;
1272 r
= resolve_service_hostname(q
, rr
, ifindex
);
1273 q
->block_all_complete
--;
1282 if (has_root_domain
&& found
<= 0) {
1283 /* If there's exactly one SRV RR and it uses the root domain as hostname, then the service is
1284 * explicitly not offered on the domain. Report this as a recognizable error. See RFC 2782,
1285 * Section "Usage Rules". */
1286 r
= reply_method_errorf(q
, BUS_ERROR_NO_SUCH_SERVICE
, "'%s' does not provide the requested service", dns_query_string(q
));
1291 r
= reply_method_errorf(q
, BUS_ERROR_NO_SUCH_RR
, "'%s' does not have any RR of the requested type", dns_query_string(q
));
1295 /* Maybe we are already finished? check now... */
1296 resolve_service_all_complete(TAKE_PTR(q
));
1301 log_error_errno(r
, "Failed to send service reply: %m");
1302 (void) reply_method_errnof(q
, r
, NULL
);
1306 static int bus_method_resolve_service(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1307 _cleanup_(dns_question_unrefp
) DnsQuestion
*question_idna
= NULL
, *question_utf8
= NULL
;
1308 _cleanup_(dns_query_freep
) DnsQuery
*q
= NULL
;
1309 const char *name
, *type
, *domain
;
1310 Manager
*m
= ASSERT_PTR(userdata
);
1311 int family
, ifindex
;
1317 assert_cc(sizeof(int) == sizeof(int32_t));
1319 r
= sd_bus_message_read(message
, "isssit", &ifindex
, &name
, &type
, &domain
, &family
, &flags
);
1324 return sd_bus_error_set(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid interface index");
1326 if (!IN_SET(family
, AF_INET
, AF_INET6
, AF_UNSPEC
))
1327 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Unknown address family %i", family
);
1331 else if (!dns_service_name_is_valid(name
))
1332 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid service name '%s'", name
);
1336 else if (!dns_srv_type_is_valid(type
))
1337 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid SRV service type '%s'", type
);
1339 r
= dns_name_is_valid(domain
);
1343 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid domain '%s'", domain
);
1346 return sd_bus_error_set(error
, SD_BUS_ERROR_INVALID_ARGS
, "Service name cannot be specified without service type.");
1348 if (validate_and_mangle_query_flags(m
, &flags
, name
, SD_RESOLVED_NO_TXT
|SD_RESOLVED_NO_ADDRESS
) < 0)
1349 return sd_bus_error_set(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid flags parameter");
1351 /* Refuse the method if SRV is filtered. */
1352 if (set_contains(m
->refuse_record_types
, INT_TO_PTR(DNS_TYPE_SRV
)))
1353 return sd_bus_error_set(error
, BUS_ERROR_DNS_REFUSED
, "DNS query type refused.");
1355 r
= dns_question_new_service(&question_utf8
, name
, type
, domain
, !(flags
& SD_RESOLVED_NO_TXT
), false);
1359 r
= dns_question_new_service(&question_idna
, name
, type
, domain
, !(flags
& SD_RESOLVED_NO_TXT
), true);
1363 bus_client_log(message
, "service resolution");
1365 r
= dns_query_new_for_bus(m
, &q
, question_utf8
, question_idna
, NULL
, ifindex
, flags
|SD_RESOLVED_NO_SEARCH
, error
);
1369 q
->bus_request
= sd_bus_message_ref(message
);
1370 q
->request_family
= family
;
1371 q
->complete
= bus_method_resolve_service_complete
;
1373 r
= dns_query_bus_track(q
, message
);
1377 r
= dns_query_go(q
);
1385 int bus_dns_server_append(
1386 sd_bus_message
*reply
,
1388 bool with_ifindex
, /* include "ifindex" field */
1389 bool extended
) { /* also include port number and server name */
1397 return sd_bus_message_append(reply
, "(iiayqs)", 0, AF_UNSPEC
, 0, 0, NULL
);
1399 return sd_bus_message_append(reply
, "(iiay)", 0, AF_UNSPEC
, 0);
1402 return sd_bus_message_append(reply
, "(iayqs)", AF_UNSPEC
, 0, 0, NULL
);
1404 return sd_bus_message_append(reply
, "(iay)", AF_UNSPEC
, 0);
1408 r
= sd_bus_message_open_container(
1411 with_ifindex
? (extended
? "iiayqs" : "iiay") :
1412 (extended
? "iayqs" : "iay"));
1417 r
= sd_bus_message_append(reply
, "i", dns_server_ifindex(s
));
1422 r
= sd_bus_message_append(reply
, "i", s
->family
);
1426 r
= sd_bus_message_append_array(reply
, 'y', &s
->address
, FAMILY_ADDRESS_SIZE(s
->family
));
1431 r
= sd_bus_message_append(reply
, "q", s
->port
);
1435 r
= sd_bus_message_append(reply
, "s", s
->server_name
);
1440 return sd_bus_message_close_container(reply
);
1443 static int bus_property_get_dns_servers_internal(
1446 const char *interface
,
1447 const char *property
,
1448 sd_bus_message
*reply
,
1450 sd_bus_error
*error
,
1453 Manager
*m
= ASSERT_PTR(userdata
);
1459 r
= sd_bus_message_open_container(reply
, 'a', extended
? "(iiayqs)" : "(iiay)");
1463 LIST_FOREACH(servers
, s
, m
->dns_servers
) {
1464 r
= bus_dns_server_append(reply
, s
, true, extended
);
1469 HASHMAP_FOREACH(l
, m
->links
)
1470 LIST_FOREACH(servers
, s
, l
->dns_servers
) {
1471 r
= bus_dns_server_append(reply
, s
, true, extended
);
1476 return sd_bus_message_close_container(reply
);
1479 static int bus_property_get_dns_servers(
1482 const char *interface
,
1483 const char *property
,
1484 sd_bus_message
*reply
,
1486 sd_bus_error
*error
) {
1487 return bus_property_get_dns_servers_internal(bus
, path
, interface
, property
, reply
, userdata
, error
, false);
1490 static int bus_property_get_dns_servers_ex(
1493 const char *interface
,
1494 const char *property
,
1495 sd_bus_message
*reply
,
1497 sd_bus_error
*error
) {
1498 return bus_property_get_dns_servers_internal(bus
, path
, interface
, property
, reply
, userdata
, error
, true);
1501 static int bus_property_get_fallback_dns_servers_internal(
1504 const char *interface
,
1505 const char *property
,
1506 sd_bus_message
*reply
,
1508 sd_bus_error
*error
,
1511 DnsServer
**f
= ASSERT_PTR(userdata
);
1516 r
= sd_bus_message_open_container(reply
, 'a', extended
? "(iiayqs)" : "(iiay)");
1520 LIST_FOREACH(servers
, s
, *f
) {
1521 r
= bus_dns_server_append(reply
, s
, true, extended
);
1526 return sd_bus_message_close_container(reply
);
1529 static int bus_property_get_fallback_dns_servers(
1532 const char *interface
,
1533 const char *property
,
1534 sd_bus_message
*reply
,
1536 sd_bus_error
*error
) {
1537 return bus_property_get_fallback_dns_servers_internal(bus
, path
, interface
, property
, reply
, userdata
, error
, false);
1540 static int bus_property_get_fallback_dns_servers_ex(
1543 const char *interface
,
1544 const char *property
,
1545 sd_bus_message
*reply
,
1547 sd_bus_error
*error
) {
1548 return bus_property_get_fallback_dns_servers_internal(bus
, path
, interface
, property
, reply
, userdata
, error
, true);
1551 static int bus_property_get_current_dns_server_internal(
1554 const char *interface
,
1555 const char *property
,
1556 sd_bus_message
*reply
,
1558 sd_bus_error
*error
,
1566 s
= *(DnsServer
**) userdata
;
1568 return bus_dns_server_append(reply
, s
, true, extended
);
1571 static int bus_property_get_current_dns_server(
1574 const char *interface
,
1575 const char *property
,
1576 sd_bus_message
*reply
,
1578 sd_bus_error
*error
) {
1579 return bus_property_get_current_dns_server_internal(bus
, path
, interface
, property
, reply
, userdata
, error
, false);
1582 static int bus_property_get_current_dns_server_ex(
1585 const char *interface
,
1586 const char *property
,
1587 sd_bus_message
*reply
,
1589 sd_bus_error
*error
) {
1590 return bus_property_get_current_dns_server_internal(bus
, path
, interface
, property
, reply
, userdata
, error
, true);
1593 static int bus_property_get_domains(
1596 const char *interface
,
1597 const char *property
,
1598 sd_bus_message
*reply
,
1600 sd_bus_error
*error
) {
1602 Manager
*m
= ASSERT_PTR(userdata
);
1608 r
= sd_bus_message_open_container(reply
, 'a', "(isb)");
1612 LIST_FOREACH(domains
, d
, m
->search_domains
) {
1613 r
= sd_bus_message_append(reply
, "(isb)", 0, d
->name
, d
->route_only
);
1618 HASHMAP_FOREACH(l
, m
->links
) {
1619 LIST_FOREACH(domains
, d
, l
->search_domains
) {
1620 r
= sd_bus_message_append(reply
, "(isb)", l
->ifindex
, d
->name
, d
->route_only
);
1626 return sd_bus_message_close_container(reply
);
1629 static int bus_property_get_transaction_statistics(
1632 const char *interface
,
1633 const char *property
,
1634 sd_bus_message
*reply
,
1636 sd_bus_error
*error
) {
1638 Manager
*m
= ASSERT_PTR(userdata
);
1642 return sd_bus_message_append(reply
, "(tt)",
1643 (uint64_t) hashmap_size(m
->dns_transactions
),
1644 (uint64_t) m
->n_transactions_total
);
1647 static int bus_property_get_cache_statistics(
1650 const char *interface
,
1651 const char *property
,
1652 sd_bus_message
*reply
,
1654 sd_bus_error
*error
) {
1656 uint64_t size
= 0, hit
= 0, miss
= 0;
1657 Manager
*m
= ASSERT_PTR(userdata
);
1661 LIST_FOREACH(scopes
, s
, m
->dns_scopes
) {
1662 size
+= dns_cache_size(&s
->cache
);
1663 hit
+= s
->cache
.n_hit
;
1664 miss
+= s
->cache
.n_miss
;
1667 return sd_bus_message_append(reply
, "(ttt)", size
, hit
, miss
);
1670 static int bus_property_get_dnssec_statistics(
1673 const char *interface
,
1674 const char *property
,
1675 sd_bus_message
*reply
,
1677 sd_bus_error
*error
) {
1679 Manager
*m
= ASSERT_PTR(userdata
);
1683 return sd_bus_message_append(reply
, "(tttt)",
1684 (uint64_t) m
->n_dnssec_verdict
[DNSSEC_SECURE
],
1685 (uint64_t) m
->n_dnssec_verdict
[DNSSEC_INSECURE
],
1686 (uint64_t) m
->n_dnssec_verdict
[DNSSEC_BOGUS
],
1687 (uint64_t) m
->n_dnssec_verdict
[DNSSEC_INDETERMINATE
]);
1690 static BUS_DEFINE_PROPERTY_GET_ENUM(bus_property_get_dns_stub_listener_mode
, dns_stub_listener_mode
, DnsStubListenerMode
);
1691 static BUS_DEFINE_PROPERTY_GET(bus_property_get_dnssec_supported
, "b", Manager
, manager_dnssec_supported
);
1692 static BUS_DEFINE_PROPERTY_GET2(bus_property_get_dnssec_mode
, "s", Manager
, manager_get_dnssec_mode
, dnssec_mode_to_string
);
1693 static BUS_DEFINE_PROPERTY_GET2(bus_property_get_dns_over_tls_mode
, "s", Manager
, manager_get_dns_over_tls_mode
, dns_over_tls_mode_to_string
);
1695 static int bus_property_get_resolv_conf_mode(
1698 const char *interface
,
1699 const char *property
,
1700 sd_bus_message
*reply
,
1702 sd_bus_error
*error
) {
1708 r
= resolv_conf_mode();
1710 log_warning_errno(r
, "Failed to test /etc/resolv.conf mode, ignoring: %m");
1711 return sd_bus_message_append(reply
, "s", NULL
);
1714 return sd_bus_message_append(reply
, "s", resolv_conf_mode_to_string(r
));
1717 static int bus_method_reset_statistics(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1718 Manager
*m
= ASSERT_PTR(userdata
);
1722 bus_client_log(message
, "statistics reset");
1724 dns_manager_reset_statistics(m
);
1726 return sd_bus_reply_method_return(message
, NULL
);
1729 static int get_any_link(Manager
*m
, int ifindex
, Link
**ret
, sd_bus_error
*error
) {
1735 l
= hashmap_get(m
->links
, INT_TO_PTR(ifindex
));
1737 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_LINK
, "Link %i not known", ifindex
);
1743 static int call_link_method(Manager
*m
, sd_bus_message
*message
, sd_bus_message_handler_t handler
, sd_bus_error
*error
) {
1745 Link
*l
= NULL
; /* avoid false maybe-uninitialized warning */
1751 r
= bus_message_read_ifindex(message
, error
, &ifindex
);
1755 r
= get_any_link(m
, ifindex
, &l
, error
);
1759 return handler(message
, l
, error
);
1762 static int bus_method_set_link_dns_servers(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1763 return call_link_method(userdata
, message
, bus_link_method_set_dns_servers
, error
);
1766 static int bus_method_set_link_dns_servers_ex(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1767 return call_link_method(userdata
, message
, bus_link_method_set_dns_servers_ex
, error
);
1770 static int bus_method_set_link_domains(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1771 return call_link_method(userdata
, message
, bus_link_method_set_domains
, error
);
1774 static int bus_method_set_link_default_route(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1775 return call_link_method(userdata
, message
, bus_link_method_set_default_route
, error
);
1778 static int bus_method_set_link_llmnr(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1779 return call_link_method(userdata
, message
, bus_link_method_set_llmnr
, error
);
1782 static int bus_method_set_link_mdns(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1783 return call_link_method(userdata
, message
, bus_link_method_set_mdns
, error
);
1786 static int bus_method_set_link_dns_over_tls(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1787 return call_link_method(userdata
, message
, bus_link_method_set_dns_over_tls
, error
);
1790 static int bus_method_set_link_dnssec(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1791 return call_link_method(userdata
, message
, bus_link_method_set_dnssec
, error
);
1794 static int bus_method_set_link_dnssec_negative_trust_anchors(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1795 return call_link_method(userdata
, message
, bus_link_method_set_dnssec_negative_trust_anchors
, error
);
1798 static int bus_method_revert_link(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1799 return call_link_method(userdata
, message
, bus_link_method_revert
, error
);
1802 static int bus_method_get_link(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1803 _cleanup_free_
char *p
= NULL
;
1804 Manager
*m
= ASSERT_PTR(userdata
);
1806 Link
*l
= NULL
; /* avoid false maybe-uninitialized warning */
1810 r
= bus_message_read_ifindex(message
, error
, &ifindex
);
1814 r
= get_any_link(m
, ifindex
, &l
, error
);
1818 p
= link_bus_path(l
);
1822 return sd_bus_reply_method_return(message
, "o", p
);
1825 static int bus_method_flush_caches(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1826 Manager
*m
= ASSERT_PTR(userdata
);
1830 bus_client_log(message
, "cache flush");
1832 manager_flush_caches(m
, LOG_INFO
);
1834 return sd_bus_reply_method_return(message
, NULL
);
1837 static int bus_method_reset_server_features(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1838 Manager
*m
= ASSERT_PTR(userdata
);
1842 bus_client_log(message
, "server feature reset");
1844 (void) dns_stream_disconnect_all(m
);
1845 manager_reset_server_features(m
);
1847 return sd_bus_reply_method_return(message
, NULL
);
1850 static int dnssd_service_on_bus_track(sd_bus_track
*t
, void *userdata
) {
1851 DnssdService
*s
= ASSERT_PTR(userdata
);
1855 log_debug("Client of active request vanished, destroying DNS-SD service.");
1856 dnssd_service_free(s
);
1861 static int bus_method_register_service(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1862 _cleanup_(sd_bus_creds_unrefp
) sd_bus_creds
*creds
= NULL
;
1863 _cleanup_(dnssd_service_freep
) DnssdService
*service
= NULL
;
1864 _cleanup_(sd_bus_track_unrefp
) sd_bus_track
*bus_track
= NULL
;
1865 const char *id
, *name_template
, *type
;
1866 _cleanup_free_
char *path
= NULL
;
1867 DnssdService
*s
= NULL
;
1868 Manager
*m
= ASSERT_PTR(userdata
);
1874 if (m
->mdns_support
!= RESOLVE_SUPPORT_YES
)
1875 return sd_bus_error_set(error
, SD_BUS_ERROR_NOT_SUPPORTED
, "Support for MulticastDNS is disabled");
1877 service
= new0(DnssdService
, 1);
1881 r
= sd_bus_query_sender_creds(message
, SD_BUS_CREDS_EUID
, &creds
);
1885 r
= sd_bus_creds_get_euid(creds
, &euid
);
1888 service
->originator
= euid
;
1889 service
->config_source
= RESOLVE_CONFIG_SOURCE_DBUS
;
1891 r
= sd_bus_message_read(message
, "sssqqq", &id
, &name_template
, &type
,
1892 &service
->port
, &service
->priority
,
1897 if (!filename_part_is_valid(id
))
1898 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "DNS-SD service identifier '%s' is invalid", id
);
1900 if (!dnssd_srv_type_is_valid(type
))
1901 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "DNS-SD service type '%s' is invalid", type
);
1903 s
= hashmap_get(m
->dnssd_services
, id
);
1905 return sd_bus_error_setf(error
, BUS_ERROR_DNSSD_SERVICE_EXISTS
, "DNS-SD service '%s' exists already", id
);
1907 service
->id
= strdup(id
);
1911 service
->name_template
= strdup(name_template
);
1912 if (!service
->name_template
)
1915 service
->type
= strdup(type
);
1919 r
= dnssd_render_instance_name(m
, service
, NULL
);
1923 r
= sd_bus_message_enter_container(message
, SD_BUS_TYPE_ARRAY
, "a{say}");
1927 while ((r
= sd_bus_message_enter_container(message
, SD_BUS_TYPE_ARRAY
, "{say}")) > 0) {
1928 _cleanup_(dnssd_txtdata_freep
) DnssdTxtData
*txt_data
= NULL
;
1929 DnsTxtItem
*last
= NULL
;
1931 txt_data
= new0(DnssdTxtData
, 1);
1935 while ((r
= sd_bus_message_enter_container(message
, SD_BUS_TYPE_DICT_ENTRY
, "say")) > 0) {
1941 r
= sd_bus_message_read(message
, "s", &key
);
1946 return sd_bus_error_set(error
, SD_BUS_ERROR_INVALID_ARGS
, "Keys in DNS-SD TXT RRs can't be empty");
1948 if (!ascii_is_valid(key
))
1949 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "TXT key '%s' contains non-ASCII symbols", key
);
1951 r
= sd_bus_message_read_array(message
, 'y', &value
, &size
);
1955 r
= dnssd_txt_item_new_from_data(key
, value
, size
, &i
);
1959 LIST_INSERT_AFTER(items
, txt_data
->txts
, last
, i
);
1962 r
= sd_bus_message_exit_container(message
);
1970 r
= sd_bus_message_exit_container(message
);
1974 if (txt_data
->txts
) {
1975 LIST_PREPEND(items
, service
->txt_data_items
, txt_data
);
1982 r
= sd_bus_message_exit_container(message
);
1986 if (!service
->txt_data_items
) {
1987 _cleanup_(dnssd_txtdata_freep
) DnssdTxtData
*txt_data
= NULL
;
1989 txt_data
= new0(DnssdTxtData
, 1);
1993 r
= dns_txt_item_new_empty(&txt_data
->txts
);
1997 LIST_PREPEND(items
, service
->txt_data_items
, txt_data
);
2001 r
= sd_bus_path_encode("/org/freedesktop/resolve1/dnssd", service
->id
, &path
);
2005 r
= bus_verify_polkit_async(
2007 "org.freedesktop.resolve1.register-service",
2008 /* details= */ NULL
,
2009 &m
->polkit_registry
,
2014 return 1; /* Polkit will call us back */
2016 r
= hashmap_ensure_put(&m
->dnssd_services
, &string_hash_ops
, service
->id
, service
);
2020 r
= sd_bus_track_new(sd_bus_message_get_bus(message
), &bus_track
, dnssd_service_on_bus_track
, service
);
2024 r
= sd_bus_track_add_sender(bus_track
, message
);
2028 service
->manager
= m
;
2032 manager_refresh_rrs(m
);
2034 return sd_bus_reply_method_return(message
, "o", path
);
2037 static int call_dnssd_method(Manager
*m
, sd_bus_message
*message
, sd_bus_message_handler_t handler
, sd_bus_error
*error
) {
2038 _cleanup_free_
char *name
= NULL
;
2039 DnssdService
*s
= NULL
;
2047 r
= sd_bus_message_read(message
, "o", &path
);
2051 r
= sd_bus_path_decode(path
, "/org/freedesktop/resolve1/dnssd", &name
);
2053 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_DNSSD_SERVICE
, "DNS-SD service with object path '%s' does not exist", path
);
2057 s
= hashmap_get(m
->dnssd_services
, name
);
2059 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_DNSSD_SERVICE
, "DNS-SD service '%s' not known", name
);
2061 return handler(message
, s
, error
);
2064 static int bus_method_unregister_service(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
2065 Manager
*m
= ASSERT_PTR(userdata
);
2069 return call_dnssd_method(m
, message
, bus_dnssd_method_unregister
, error
);
2072 static int bus_method_get_delegate(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
2073 _cleanup_free_
char *p
= NULL
;
2074 Manager
*m
= ASSERT_PTR(userdata
);
2080 r
= sd_bus_message_read(message
, "s", &id
);
2084 DnsDelegate
*d
= hashmap_get(m
->delegates
, id
);
2086 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_DELEGATE
, "Delegate '%s' not known", id
);
2088 p
= dns_delegate_bus_path(d
);
2092 return sd_bus_reply_method_return(message
, "o", p
);
2095 static int bus_method_list_delegates(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
2096 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
2097 Manager
*m
= ASSERT_PTR(userdata
);
2102 r
= sd_bus_message_new_method_return(message
, &reply
);
2106 r
= sd_bus_message_open_container(reply
, 'a', "(so)");
2111 HASHMAP_FOREACH(d
, m
->delegates
) {
2112 _cleanup_free_
char *p
= NULL
;
2114 p
= dns_delegate_bus_path(d
);
2118 r
= sd_bus_message_append(reply
, "(so)", d
->id
, p
);
2123 r
= sd_bus_message_close_container(reply
);
2127 return sd_bus_message_send(reply
);
2130 static const sd_bus_vtable resolve_vtable
[] = {
2131 SD_BUS_VTABLE_START(0),
2132 SD_BUS_PROPERTY("LLMNRHostname", "s", NULL
, offsetof(Manager
, llmnr_hostname
), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
2133 SD_BUS_PROPERTY("LLMNR", "s", bus_property_get_resolve_support
, offsetof(Manager
, llmnr_support
), 0),
2134 SD_BUS_PROPERTY("MulticastDNS", "s", bus_property_get_resolve_support
, offsetof(Manager
, mdns_support
), 0),
2135 SD_BUS_PROPERTY("DNSOverTLS", "s", bus_property_get_dns_over_tls_mode
, 0, 0),
2136 SD_BUS_PROPERTY("DNS", "a(iiay)", bus_property_get_dns_servers
, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
2137 SD_BUS_PROPERTY("DNSEx", "a(iiayqs)", bus_property_get_dns_servers_ex
, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
2138 SD_BUS_PROPERTY("FallbackDNS", "a(iiay)", bus_property_get_fallback_dns_servers
, offsetof(Manager
, fallback_dns_servers
), SD_BUS_VTABLE_PROPERTY_CONST
),
2139 SD_BUS_PROPERTY("FallbackDNSEx", "a(iiayqs)", bus_property_get_fallback_dns_servers_ex
, offsetof(Manager
, fallback_dns_servers
), SD_BUS_VTABLE_PROPERTY_CONST
),
2140 SD_BUS_PROPERTY("CurrentDNSServer", "(iiay)", bus_property_get_current_dns_server
, offsetof(Manager
, current_dns_server
), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
2141 SD_BUS_PROPERTY("CurrentDNSServerEx", "(iiayqs)", bus_property_get_current_dns_server_ex
, offsetof(Manager
, current_dns_server
), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
2142 SD_BUS_PROPERTY("Domains", "a(isb)", bus_property_get_domains
, 0, 0),
2143 SD_BUS_PROPERTY("TransactionStatistics", "(tt)", bus_property_get_transaction_statistics
, 0, 0),
2144 SD_BUS_PROPERTY("CacheStatistics", "(ttt)", bus_property_get_cache_statistics
, 0, 0),
2145 SD_BUS_PROPERTY("DNSSEC", "s", bus_property_get_dnssec_mode
, 0, 0),
2146 SD_BUS_PROPERTY("DNSSECStatistics", "(tttt)", bus_property_get_dnssec_statistics
, 0, 0),
2147 SD_BUS_PROPERTY("DNSSECSupported", "b", bus_property_get_dnssec_supported
, 0, 0),
2148 SD_BUS_PROPERTY("DNSSECNegativeTrustAnchors", "as", bus_property_get_string_set
, offsetof(Manager
, trust_anchor
.negative_by_name
), 0),
2149 SD_BUS_PROPERTY("DNSStubListener", "s", bus_property_get_dns_stub_listener_mode
, offsetof(Manager
, dns_stub_listener_mode
), 0),
2150 SD_BUS_PROPERTY("ResolvConfMode", "s", bus_property_get_resolv_conf_mode
, 0, 0),
2152 SD_BUS_METHOD_WITH_ARGS("ResolveHostname",
2153 SD_BUS_ARGS("i", ifindex
, "s", name
, "i", family
, "t", flags
),
2154 SD_BUS_RESULT("a(iiay)", addresses
, "s", canonical
, "t", flags
),
2155 bus_method_resolve_hostname
,
2156 SD_BUS_VTABLE_UNPRIVILEGED
),
2157 SD_BUS_METHOD_WITH_ARGS("ResolveAddress",
2158 SD_BUS_ARGS("i", ifindex
, "i", family
, "ay", address
, "t", flags
),
2159 SD_BUS_RESULT("a(is)", names
, "t", flags
),
2160 bus_method_resolve_address
,
2161 SD_BUS_VTABLE_UNPRIVILEGED
),
2162 SD_BUS_METHOD_WITH_ARGS("ResolveRecord",
2163 SD_BUS_ARGS("i", ifindex
, "s", name
, "q", class, "q", type
, "t", flags
),
2164 SD_BUS_RESULT("a(iqqay)", records
, "t", flags
),
2165 bus_method_resolve_record
,
2166 SD_BUS_VTABLE_UNPRIVILEGED
),
2167 SD_BUS_METHOD_WITH_ARGS("ResolveService",
2168 SD_BUS_ARGS("i", ifindex
,
2174 SD_BUS_RESULT("a(qqqsa(iiay)s)", srv_data
,
2176 "s", canonical_name
,
2177 "s", canonical_type
,
2178 "s", canonical_domain
,
2180 bus_method_resolve_service
,
2181 SD_BUS_VTABLE_UNPRIVILEGED
),
2182 SD_BUS_METHOD_WITH_ARGS("GetLink",
2183 SD_BUS_ARGS("i", ifindex
),
2184 SD_BUS_RESULT("o", path
),
2185 bus_method_get_link
,
2186 SD_BUS_VTABLE_UNPRIVILEGED
),
2187 SD_BUS_METHOD_WITH_ARGS("SetLinkDNS",
2188 SD_BUS_ARGS("i", ifindex
, "a(iay)", addresses
),
2190 bus_method_set_link_dns_servers
,
2191 SD_BUS_VTABLE_UNPRIVILEGED
),
2192 SD_BUS_METHOD_WITH_ARGS("SetLinkDNSEx",
2193 SD_BUS_ARGS("i", ifindex
, "a(iayqs)", addresses
),
2195 bus_method_set_link_dns_servers_ex
,
2196 SD_BUS_VTABLE_UNPRIVILEGED
),
2197 SD_BUS_METHOD_WITH_ARGS("SetLinkDomains",
2198 SD_BUS_ARGS("i", ifindex
, "a(sb)", domains
),
2200 bus_method_set_link_domains
,
2201 SD_BUS_VTABLE_UNPRIVILEGED
),
2202 SD_BUS_METHOD_WITH_ARGS("SetLinkDefaultRoute",
2203 SD_BUS_ARGS("i", ifindex
, "b", enable
),
2205 bus_method_set_link_default_route
,
2206 SD_BUS_VTABLE_UNPRIVILEGED
),
2207 SD_BUS_METHOD_WITH_ARGS("SetLinkLLMNR",
2208 SD_BUS_ARGS("i", ifindex
, "s", mode
),
2210 bus_method_set_link_llmnr
,
2211 SD_BUS_VTABLE_UNPRIVILEGED
),
2212 SD_BUS_METHOD_WITH_ARGS("SetLinkMulticastDNS",
2213 SD_BUS_ARGS("i", ifindex
, "s", mode
),
2215 bus_method_set_link_mdns
,
2216 SD_BUS_VTABLE_UNPRIVILEGED
),
2217 SD_BUS_METHOD_WITH_ARGS("SetLinkDNSOverTLS",
2218 SD_BUS_ARGS("i", ifindex
, "s", mode
),
2220 bus_method_set_link_dns_over_tls
,
2221 SD_BUS_VTABLE_UNPRIVILEGED
),
2222 SD_BUS_METHOD_WITH_ARGS("SetLinkDNSSEC",
2223 SD_BUS_ARGS("i", ifindex
, "s", mode
),
2225 bus_method_set_link_dnssec
,
2226 SD_BUS_VTABLE_UNPRIVILEGED
),
2227 SD_BUS_METHOD_WITH_ARGS("SetLinkDNSSECNegativeTrustAnchors",
2228 SD_BUS_ARGS("i", ifindex
, "as", names
),
2230 bus_method_set_link_dnssec_negative_trust_anchors
,
2231 SD_BUS_VTABLE_UNPRIVILEGED
),
2232 SD_BUS_METHOD_WITH_ARGS("RevertLink",
2233 SD_BUS_ARGS("i", ifindex
),
2235 bus_method_revert_link
,
2236 SD_BUS_VTABLE_UNPRIVILEGED
),
2237 SD_BUS_METHOD_WITH_ARGS("RegisterService",
2238 SD_BUS_ARGS("s", id
,
2242 "q", service_priority
,
2243 "q", service_weight
,
2244 "aa{say}", txt_datas
),
2245 SD_BUS_RESULT("o", service_path
),
2246 bus_method_register_service
,
2247 SD_BUS_VTABLE_UNPRIVILEGED
),
2248 SD_BUS_METHOD_WITH_ARGS("UnregisterService",
2249 SD_BUS_ARGS("o", service_path
),
2251 bus_method_unregister_service
,
2252 SD_BUS_VTABLE_UNPRIVILEGED
),
2253 SD_BUS_METHOD_WITH_ARGS("ResetStatistics",
2256 bus_method_reset_statistics
,
2257 SD_BUS_VTABLE_UNPRIVILEGED
),
2258 SD_BUS_METHOD_WITH_ARGS("FlushCaches",
2261 bus_method_flush_caches
,
2262 SD_BUS_VTABLE_UNPRIVILEGED
),
2263 SD_BUS_METHOD_WITH_ARGS("ResetServerFeatures",
2266 bus_method_reset_server_features
,
2267 SD_BUS_VTABLE_UNPRIVILEGED
),
2268 SD_BUS_METHOD_WITH_ARGS("GetDelegate",
2269 SD_BUS_ARGS("s", id
),
2270 SD_BUS_RESULT("o", path
),
2271 bus_method_get_delegate
,
2272 SD_BUS_VTABLE_UNPRIVILEGED
),
2273 SD_BUS_METHOD_WITH_ARGS("ListDelegates",
2275 SD_BUS_RESULT("a(so)", delegates
),
2276 bus_method_list_delegates
,
2277 SD_BUS_VTABLE_UNPRIVILEGED
),
2282 const BusObjectImplementation manager_object
= {
2283 "/org/freedesktop/resolve1",
2284 "org.freedesktop.resolve1.Manager",
2285 .vtables
= BUS_VTABLES(resolve_vtable
),
2286 .children
= BUS_IMPLEMENTATIONS(&link_object
,
2288 &dns_delegate_object
),
2291 static int match_prepare_for_sleep(sd_bus_message
*message
, void *userdata
, sd_bus_error
*ret_error
) {
2292 Manager
*m
= ASSERT_PTR(userdata
);
2297 r
= sd_bus_message_read(message
, "b", &b
);
2299 bus_log_parse_error(r
);
2306 log_debug("Coming back from suspend, closing all TCP connections...");
2307 (void) dns_stream_disconnect_all(m
);
2309 log_debug("Coming back from suspend, resetting all probed server features...");
2310 manager_reset_server_features(m
);
2312 log_debug("Coming back from suspend, verifying all RRs...");
2313 manager_verify_all(m
);
2318 int manager_connect_bus(Manager
*m
) {
2326 r
= bus_open_system_watch_bind_with_description(&m
->bus
, "bus-api-resolve");
2328 return log_error_errno(r
, "Failed to connect to system bus: %m");
2330 r
= bus_add_implementation(m
->bus
, &manager_object
, m
);
2334 r
= bus_log_control_api_register(m
->bus
);
2338 r
= sd_bus_request_name_async(m
->bus
, NULL
, "org.freedesktop.resolve1", 0, NULL
, NULL
);
2340 return log_error_errno(r
, "Failed to request name: %m");
2342 r
= sd_bus_attach_event(m
->bus
, m
->event
, 0);
2344 return log_error_errno(r
, "Failed to attach bus to event loop: %m");
2346 r
= bus_match_signal_async(
2351 match_prepare_for_sleep
,
2355 log_warning_errno(r
, "Failed to request match for PrepareForSleep, ignoring: %m");
2360 int manager_send_changed_strv(Manager
*manager
, char **properties
) {
2363 if (sd_bus_is_ready(manager
->bus
) <= 0)
2366 int r
= sd_bus_emit_properties_changed_strv(
2368 "/org/freedesktop/resolve1",
2369 "org.freedesktop.resolve1.Manager",
2372 log_notice_errno(r
, "Failed to emit notification about changed properties: %m");