1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 #include "alloc-util.h"
4 #include "bus-common-errors.h"
5 #include "bus-get-properties.h"
6 #include "bus-log-control-api.h"
7 #include "bus-message-util.h"
8 #include "bus-polkit.h"
9 #include "dns-domain.h"
10 #include "memory-util.h"
11 #include "missing_capability.h"
12 #include "resolved-bus.h"
13 #include "resolved-def.h"
14 #include "resolved-dns-synthesize.h"
15 #include "resolved-dnssd-bus.h"
16 #include "resolved-dnssd.h"
17 #include "resolved-link-bus.h"
18 #include "socket-netlink.h"
19 #include "stdio-util.h"
21 #include "syslog-util.h"
22 #include "user-util.h"
25 BUS_DEFINE_PROPERTY_GET_ENUM(bus_property_get_resolve_support
, resolve_support
, ResolveSupport
);
27 static int query_on_bus_track(sd_bus_track
*t
, void *userdata
) {
28 DnsQuery
*q
= userdata
;
33 if (!DNS_TRANSACTION_IS_LIVE(q
->state
))
36 log_debug("Client of active query vanished, aborting query.");
37 dns_query_complete(q
, DNS_TRANSACTION_ABORTED
);
41 static int dns_query_bus_track(DnsQuery
*q
, sd_bus_message
*m
) {
48 r
= sd_bus_track_new(sd_bus_message_get_bus(m
), &q
->bus_track
, query_on_bus_track
, q
);
53 r
= sd_bus_track_add_sender(q
->bus_track
, m
);
60 static int reply_query_state(DnsQuery
*q
) {
63 assert(q
->bus_request
);
67 case DNS_TRANSACTION_NO_SERVERS
:
68 return sd_bus_reply_method_errorf(q
->bus_request
, BUS_ERROR_NO_NAME_SERVERS
, "No appropriate name servers or networks for name found");
70 case DNS_TRANSACTION_TIMEOUT
:
71 return sd_bus_reply_method_errorf(q
->bus_request
, SD_BUS_ERROR_TIMEOUT
, "Query timed out");
73 case DNS_TRANSACTION_ATTEMPTS_MAX_REACHED
:
74 return sd_bus_reply_method_errorf(q
->bus_request
, SD_BUS_ERROR_TIMEOUT
, "All attempts to contact name servers or networks failed");
76 case DNS_TRANSACTION_INVALID_REPLY
:
77 return sd_bus_reply_method_errorf(q
->bus_request
, BUS_ERROR_INVALID_REPLY
, "Received invalid reply");
79 case DNS_TRANSACTION_ERRNO
:
80 return sd_bus_reply_method_errnof(q
->bus_request
, q
->answer_errno
, "Lookup failed due to system error: %m");
82 case DNS_TRANSACTION_ABORTED
:
83 return sd_bus_reply_method_errorf(q
->bus_request
, BUS_ERROR_ABORTED
, "Query aborted");
85 case DNS_TRANSACTION_DNSSEC_FAILED
:
86 return sd_bus_reply_method_errorf(q
->bus_request
, BUS_ERROR_DNSSEC_FAILED
, "DNSSEC validation failed: %s",
87 dnssec_result_to_string(q
->answer_dnssec_result
));
89 case DNS_TRANSACTION_NO_TRUST_ANCHOR
:
90 return sd_bus_reply_method_errorf(q
->bus_request
, BUS_ERROR_NO_TRUST_ANCHOR
, "No suitable trust anchor known");
92 case DNS_TRANSACTION_RR_TYPE_UNSUPPORTED
:
93 return sd_bus_reply_method_errorf(q
->bus_request
, BUS_ERROR_RR_TYPE_UNSUPPORTED
, "Server does not support requested resource record type");
95 case DNS_TRANSACTION_NETWORK_DOWN
:
96 return sd_bus_reply_method_errorf(q
->bus_request
, BUS_ERROR_NETWORK_DOWN
, "Network is down");
98 case DNS_TRANSACTION_NOT_FOUND
:
99 /* We return this as NXDOMAIN. This is only generated when a host doesn't implement LLMNR/TCP, and we
100 * thus quickly know that we cannot resolve an in-addr.arpa or ip6.arpa address. */
101 return sd_bus_reply_method_errorf(q
->bus_request
, _BUS_ERROR_DNS
"NXDOMAIN", "'%s' not found", dns_query_string(q
));
103 case DNS_TRANSACTION_RCODE_FAILURE
: {
104 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
106 if (q
->answer_rcode
== DNS_RCODE_NXDOMAIN
)
107 sd_bus_error_setf(&error
, _BUS_ERROR_DNS
"NXDOMAIN", "'%s' not found", dns_query_string(q
));
110 char p
[DECIMAL_STR_MAX(q
->answer_rcode
)];
112 rc
= dns_rcode_to_string(q
->answer_rcode
);
114 xsprintf(p
, "%i", q
->answer_rcode
);
118 n
= strjoina(_BUS_ERROR_DNS
, rc
);
119 sd_bus_error_setf(&error
, n
, "Could not resolve '%s', server or network returned error %s", dns_query_string(q
), rc
);
122 return sd_bus_reply_method_error(q
->bus_request
, &error
);
125 case DNS_TRANSACTION_NULL
:
126 case DNS_TRANSACTION_PENDING
:
127 case DNS_TRANSACTION_VALIDATING
:
128 case DNS_TRANSACTION_SUCCESS
:
130 assert_not_reached("Impossible state");
134 static int append_address(sd_bus_message
*reply
, DnsResourceRecord
*rr
, int ifindex
) {
140 r
= sd_bus_message_open_container(reply
, 'r', "iiay");
144 r
= sd_bus_message_append(reply
, "i", ifindex
);
148 if (rr
->key
->type
== DNS_TYPE_A
) {
149 r
= sd_bus_message_append(reply
, "i", AF_INET
);
153 r
= sd_bus_message_append_array(reply
, 'y', &rr
->a
.in_addr
, sizeof(struct in_addr
));
155 } else if (rr
->key
->type
== DNS_TYPE_AAAA
) {
156 r
= sd_bus_message_append(reply
, "i", AF_INET6
);
160 r
= sd_bus_message_append_array(reply
, 'y', &rr
->aaaa
.in6_addr
, sizeof(struct in6_addr
));
162 return -EAFNOSUPPORT
;
167 r
= sd_bus_message_close_container(reply
);
174 static void bus_method_resolve_hostname_complete(DnsQuery
*q
) {
175 _cleanup_(dns_resource_record_unrefp
) DnsResourceRecord
*canonical
= NULL
;
176 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
177 _cleanup_free_
char *normalized
= NULL
;
178 DnsQuestion
*question
;
179 DnsResourceRecord
*rr
;
185 if (q
->state
!= DNS_TRANSACTION_SUCCESS
) {
186 r
= reply_query_state(q
);
190 r
= dns_query_process_cname(q
);
192 r
= sd_bus_reply_method_errorf(q
->bus_request
, BUS_ERROR_CNAME_LOOP
, "CNAME loop detected, or CNAME resolving disabled on '%s'", dns_query_string(q
));
197 if (r
== DNS_QUERY_RESTARTED
) /* This was a cname, and the query was restarted. */
200 r
= sd_bus_message_new_method_return(q
->bus_request
, &reply
);
204 r
= sd_bus_message_open_container(reply
, 'a', "(iiay)");
208 question
= dns_query_question_for_protocol(q
, q
->answer_protocol
);
210 DNS_ANSWER_FOREACH_IFINDEX(rr
, ifindex
, q
->answer
) {
212 r
= dns_question_matches_rr(question
, rr
, DNS_SEARCH_DOMAIN_NAME(q
->answer_search_domain
));
218 r
= append_address(reply
, rr
, ifindex
);
223 canonical
= dns_resource_record_ref(rr
);
229 r
= sd_bus_reply_method_errorf(q
->bus_request
, BUS_ERROR_NO_SUCH_RR
, "'%s' does not have any RR of the requested type", dns_query_string(q
));
233 r
= sd_bus_message_close_container(reply
);
237 /* The key names are not necessarily normalized, make sure that they are when we return them to our
240 r
= dns_name_normalize(dns_resource_key_name(canonical
->key
), 0, &normalized
);
244 /* Return the precise spelling and uppercasing and CNAME target reported by the server */
245 r
= sd_bus_message_append(
248 SD_RESOLVED_FLAGS_MAKE(q
->answer_protocol
, q
->answer_family
, dns_query_fully_authenticated(q
)));
252 r
= sd_bus_send(q
->manager
->bus
, reply
, NULL
);
256 log_error_errno(r
, "Failed to send hostname reply: %m");
257 sd_bus_reply_method_errno(q
->bus_request
, r
, NULL
);
263 static int validate_and_mangle_ifindex_and_flags(int ifindex
, uint64_t *flags
, uint64_t ok
, sd_bus_error
*error
) {
266 /* Checks that the client supplied interface index and flags parameter actually are valid and make
267 * sense in our method call context. Specifically:
269 * 1. Checks that the interface index is either 0 (meaning *all* interfaces) or positive
271 * 2. Only the protocols flags and the NO_CNAME flag are set, at most. Plus additional flags specific
272 * to our method, passed in the "ok" parameter.
274 * 3. If zero protocol flags are specified it is automatically turned into *all* protocols. This way
275 * clients can simply pass 0 as flags and all will work as it should. They can also use this so
276 * that clients don't have to know all the protocols resolved implements, but can just specify 0
277 * to mean "all supported protocols".
281 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid interface index");
283 if (*flags
& ~(SD_RESOLVED_PROTOCOLS_ALL
|SD_RESOLVED_NO_CNAME
|ok
))
284 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid flags parameter");
286 if ((*flags
& SD_RESOLVED_PROTOCOLS_ALL
) == 0) /* If no protocol is enabled, enable all */
287 *flags
|= SD_RESOLVED_PROTOCOLS_ALL
;
292 static int parse_as_address(sd_bus_message
*m
, int ifindex
, const char *hostname
, int family
, uint64_t flags
) {
293 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
294 _cleanup_free_
char *canonical
= NULL
;
295 union in_addr_union parsed
;
296 int r
, ff
, parsed_ifindex
= 0;
298 /* Check if the hostname is actually already an IP address formatted as string. In that case just parse it,
299 * let's not attempt to look it up. */
301 r
= in_addr_ifindex_from_string_auto(hostname
, &ff
, &parsed
, &parsed_ifindex
);
302 if (r
< 0) /* not an address */
305 if (family
!= AF_UNSPEC
&& ff
!= family
)
306 return sd_bus_reply_method_errorf(m
, BUS_ERROR_NO_SUCH_RR
, "The specified address is not of the requested family.");
307 if (ifindex
> 0 && parsed_ifindex
> 0 && parsed_ifindex
!= ifindex
)
308 return sd_bus_reply_method_errorf(m
, BUS_ERROR_NO_SUCH_RR
, "The specified address interface index does not match requested interface.");
310 if (parsed_ifindex
> 0)
311 ifindex
= parsed_ifindex
;
313 r
= sd_bus_message_new_method_return(m
, &reply
);
317 r
= sd_bus_message_open_container(reply
, 'a', "(iiay)");
321 r
= sd_bus_message_open_container(reply
, 'r', "iiay");
325 r
= sd_bus_message_append(reply
, "ii", ifindex
, ff
);
329 r
= sd_bus_message_append_array(reply
, 'y', &parsed
, FAMILY_ADDRESS_SIZE(ff
));
333 r
= sd_bus_message_close_container(reply
);
337 r
= sd_bus_message_close_container(reply
);
341 /* When an IP address is specified we just return it as canonical name, in order to avoid a DNS
342 * look-up. However, we reformat it to make sure it's in a truly canonical form (i.e. on IPv6 the inner
343 * omissions are always done the same way). */
344 r
= in_addr_ifindex_to_string(ff
, &parsed
, ifindex
, &canonical
);
348 r
= sd_bus_message_append(reply
, "st", canonical
,
349 SD_RESOLVED_FLAGS_MAKE(dns_synthesize_protocol(flags
), ff
, true));
353 return sd_bus_send(sd_bus_message_get_bus(m
), reply
, NULL
);
356 static int bus_method_resolve_hostname(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
357 _cleanup_(dns_question_unrefp
) DnsQuestion
*question_idna
= NULL
, *question_utf8
= NULL
;
358 Manager
*m
= userdata
;
359 const char *hostname
;
368 assert_cc(sizeof(int) == sizeof(int32_t));
370 r
= sd_bus_message_read(message
, "isit", &ifindex
, &hostname
, &family
, &flags
);
374 if (!IN_SET(family
, AF_INET
, AF_INET6
, AF_UNSPEC
))
375 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Unknown address family %i", family
);
377 r
= validate_and_mangle_ifindex_and_flags(ifindex
, &flags
, SD_RESOLVED_NO_SEARCH
, error
);
381 r
= parse_as_address(message
, ifindex
, hostname
, family
, flags
);
385 r
= dns_name_is_valid(hostname
);
389 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid hostname '%s'", hostname
);
391 r
= dns_question_new_address(&question_utf8
, family
, hostname
, false);
395 r
= dns_question_new_address(&question_idna
, family
, hostname
, true);
396 if (r
< 0 && r
!= -EALREADY
)
399 r
= dns_query_new(m
, &q
, question_utf8
, question_idna
?: question_utf8
, ifindex
, flags
);
403 q
->bus_request
= sd_bus_message_ref(message
);
404 q
->request_family
= family
;
405 q
->complete
= bus_method_resolve_hostname_complete
;
407 r
= dns_query_bus_track(q
, message
);
422 static void bus_method_resolve_address_complete(DnsQuery
*q
) {
423 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
424 DnsQuestion
*question
;
425 DnsResourceRecord
*rr
;
431 if (q
->state
!= DNS_TRANSACTION_SUCCESS
) {
432 r
= reply_query_state(q
);
436 r
= dns_query_process_cname(q
);
438 r
= sd_bus_reply_method_errorf(q
->bus_request
, BUS_ERROR_CNAME_LOOP
, "CNAME loop detected, or CNAME resolving disabled on '%s'", dns_query_string(q
));
443 if (r
== DNS_QUERY_RESTARTED
) /* This was a cname, and the query was restarted. */
446 r
= sd_bus_message_new_method_return(q
->bus_request
, &reply
);
450 r
= sd_bus_message_open_container(reply
, 'a', "(is)");
454 question
= dns_query_question_for_protocol(q
, q
->answer_protocol
);
456 DNS_ANSWER_FOREACH_IFINDEX(rr
, ifindex
, q
->answer
) {
457 _cleanup_free_
char *normalized
= NULL
;
459 r
= dns_question_matches_rr(question
, rr
, NULL
);
465 r
= dns_name_normalize(rr
->ptr
.name
, 0, &normalized
);
469 r
= sd_bus_message_append(reply
, "(is)", ifindex
, normalized
);
477 _cleanup_free_
char *ip
= NULL
;
479 (void) in_addr_to_string(q
->request_family
, &q
->request_address
, &ip
);
480 r
= sd_bus_reply_method_errorf(q
->bus_request
, BUS_ERROR_NO_SUCH_RR
,
481 "Address '%s' does not have any RR of requested type", strnull(ip
));
485 r
= sd_bus_message_close_container(reply
);
489 r
= sd_bus_message_append(reply
, "t", SD_RESOLVED_FLAGS_MAKE(q
->answer_protocol
, q
->answer_family
, dns_query_fully_authenticated(q
)));
493 r
= sd_bus_send(q
->manager
->bus
, reply
, NULL
);
497 log_error_errno(r
, "Failed to send address reply: %m");
498 sd_bus_reply_method_errno(q
->bus_request
, r
, NULL
);
504 static int bus_method_resolve_address(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
505 _cleanup_(dns_question_unrefp
) DnsQuestion
*question
= NULL
;
506 Manager
*m
= userdata
;
507 union in_addr_union a
;
516 assert_cc(sizeof(int) == sizeof(int32_t));
518 r
= sd_bus_message_read(message
, "i", &ifindex
);
522 r
= bus_message_read_in_addr_auto(message
, error
, &family
, &a
);
526 r
= sd_bus_message_read(message
, "t", &flags
);
530 r
= validate_and_mangle_ifindex_and_flags(ifindex
, &flags
, 0, error
);
534 r
= dns_question_new_reverse(&question
, family
, &a
);
538 r
= dns_query_new(m
, &q
, question
, question
, ifindex
, flags
|SD_RESOLVED_NO_SEARCH
);
542 q
->bus_request
= sd_bus_message_ref(message
);
543 q
->request_family
= family
;
544 q
->request_address
= a
;
545 q
->complete
= bus_method_resolve_address_complete
;
547 r
= dns_query_bus_track(q
, message
);
562 static int bus_message_append_rr(sd_bus_message
*m
, DnsResourceRecord
*rr
, int ifindex
) {
568 r
= sd_bus_message_open_container(m
, 'r', "iqqay");
572 r
= sd_bus_message_append(m
, "iqq",
579 r
= dns_resource_record_to_wire_format(rr
, false);
583 r
= sd_bus_message_append_array(m
, 'y', rr
->wire_format
, rr
->wire_format_size
);
587 return sd_bus_message_close_container(m
);
590 static void bus_method_resolve_record_complete(DnsQuery
*q
) {
591 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
592 DnsResourceRecord
*rr
;
593 DnsQuestion
*question
;
600 if (q
->state
!= DNS_TRANSACTION_SUCCESS
) {
601 r
= reply_query_state(q
);
605 r
= dns_query_process_cname(q
);
607 r
= sd_bus_reply_method_errorf(q
->bus_request
, BUS_ERROR_CNAME_LOOP
, "CNAME loop detected, or CNAME resolving disabled on '%s'", dns_query_string(q
));
612 if (r
== DNS_QUERY_RESTARTED
) /* This was a cname, and the query was restarted. */
615 r
= sd_bus_message_new_method_return(q
->bus_request
, &reply
);
619 r
= sd_bus_message_open_container(reply
, 'a', "(iqqay)");
623 question
= dns_query_question_for_protocol(q
, q
->answer_protocol
);
625 DNS_ANSWER_FOREACH_IFINDEX(rr
, ifindex
, q
->answer
) {
626 r
= dns_question_matches_rr(question
, rr
, NULL
);
632 r
= bus_message_append_rr(reply
, rr
, ifindex
);
640 r
= sd_bus_reply_method_errorf(q
->bus_request
, BUS_ERROR_NO_SUCH_RR
, "Name '%s' does not have any RR of the requested type", dns_query_string(q
));
644 r
= sd_bus_message_close_container(reply
);
648 r
= sd_bus_message_append(reply
, "t", SD_RESOLVED_FLAGS_MAKE(q
->answer_protocol
, q
->answer_family
, dns_query_fully_authenticated(q
)));
652 r
= sd_bus_send(q
->manager
->bus
, reply
, NULL
);
656 log_error_errno(r
, "Failed to send record reply: %m");
657 sd_bus_reply_method_errno(q
->bus_request
, r
, NULL
);
663 static int bus_method_resolve_record(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
664 _cleanup_(dns_resource_key_unrefp
) DnsResourceKey
*key
= NULL
;
665 _cleanup_(dns_question_unrefp
) DnsQuestion
*question
= NULL
;
666 Manager
*m
= userdata
;
667 uint16_t class, type
;
676 assert_cc(sizeof(int) == sizeof(int32_t));
678 r
= sd_bus_message_read(message
, "isqqt", &ifindex
, &name
, &class, &type
, &flags
);
682 r
= dns_name_is_valid(name
);
686 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid name '%s'", name
);
688 if (!dns_type_is_valid_query(type
))
689 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Specified resource record type %" PRIu16
" may not be used in a query.", type
);
690 if (dns_type_is_zone_transer(type
))
691 return sd_bus_error_setf(error
, SD_BUS_ERROR_NOT_SUPPORTED
, "Zone transfers not permitted via this programming interface.");
692 if (dns_type_is_obsolete(type
))
693 return sd_bus_error_setf(error
, SD_BUS_ERROR_NOT_SUPPORTED
, "Specified DNS resource record type %" PRIu16
" is obsolete.", type
);
695 r
= validate_and_mangle_ifindex_and_flags(ifindex
, &flags
, 0, error
);
699 question
= dns_question_new(1);
703 key
= dns_resource_key_new(class, type
, name
);
707 r
= dns_question_add(question
, key
);
711 r
= dns_query_new(m
, &q
, question
, question
, ifindex
, flags
|SD_RESOLVED_NO_SEARCH
);
715 /* Let's request that the TTL is fixed up for locally cached entries, after all we return it in the wire format
719 q
->bus_request
= sd_bus_message_ref(message
);
720 q
->complete
= bus_method_resolve_record_complete
;
722 r
= dns_query_bus_track(q
, message
);
737 static int append_srv(DnsQuery
*q
, sd_bus_message
*reply
, DnsResourceRecord
*rr
) {
738 _cleanup_(dns_resource_record_unrefp
) DnsResourceRecord
*canonical
= NULL
;
739 _cleanup_free_
char *normalized
= NULL
;
748 if (rr
->key
->type
!= DNS_TYPE_SRV
)
751 if ((q
->flags
& SD_RESOLVED_NO_ADDRESS
) == 0) {
752 /* First, let's see if we could find an appropriate A or AAAA
753 * record for the SRV record */
754 LIST_FOREACH(auxiliary_queries
, aux
, q
->auxiliary_queries
) {
755 DnsResourceRecord
*zz
;
756 DnsQuestion
*question
;
758 if (aux
->state
!= DNS_TRANSACTION_SUCCESS
)
760 if (aux
->auxiliary_result
!= 0)
763 question
= dns_query_question_for_protocol(aux
, aux
->answer_protocol
);
765 r
= dns_name_equal(dns_question_first_name(question
), rr
->srv
.name
);
771 DNS_ANSWER_FOREACH(zz
, aux
->answer
) {
773 r
= dns_question_matches_rr(question
, zz
, NULL
);
779 canonical
= dns_resource_record_ref(zz
);
787 /* Is there are successful A/AAAA lookup for this SRV RR? If not, don't add it */
792 r
= sd_bus_message_open_container(reply
, 'r', "qqqsa(iiay)s");
796 r
= dns_name_normalize(rr
->srv
.name
, 0, &normalized
);
800 r
= sd_bus_message_append(
803 rr
->srv
.priority
, rr
->srv
.weight
, rr
->srv
.port
, normalized
);
807 r
= sd_bus_message_open_container(reply
, 'a', "(iiay)");
811 if ((q
->flags
& SD_RESOLVED_NO_ADDRESS
) == 0) {
812 LIST_FOREACH(auxiliary_queries
, aux
, q
->auxiliary_queries
) {
813 DnsResourceRecord
*zz
;
814 DnsQuestion
*question
;
817 if (aux
->state
!= DNS_TRANSACTION_SUCCESS
)
819 if (aux
->auxiliary_result
!= 0)
822 question
= dns_query_question_for_protocol(aux
, aux
->answer_protocol
);
824 r
= dns_name_equal(dns_question_first_name(question
), rr
->srv
.name
);
830 DNS_ANSWER_FOREACH_IFINDEX(zz
, ifindex
, aux
->answer
) {
832 r
= dns_question_matches_rr(question
, zz
, NULL
);
838 r
= append_address(reply
, zz
, ifindex
);
845 r
= sd_bus_message_close_container(reply
);
850 normalized
= mfree(normalized
);
852 r
= dns_name_normalize(dns_resource_key_name(canonical
->key
), 0, &normalized
);
857 /* Note that above we appended the hostname as encoded in the
858 * SRV, and here the canonical hostname this maps to. */
859 r
= sd_bus_message_append(reply
, "s", normalized
);
863 r
= sd_bus_message_close_container(reply
);
870 static int append_txt(sd_bus_message
*reply
, DnsResourceRecord
*rr
) {
878 if (rr
->key
->type
!= DNS_TYPE_TXT
)
881 LIST_FOREACH(items
, i
, rr
->txt
.items
) {
886 r
= sd_bus_message_append_array(reply
, 'y', i
->data
, i
->length
);
894 static void resolve_service_all_complete(DnsQuery
*q
) {
895 _cleanup_(dns_resource_record_unrefp
) DnsResourceRecord
*canonical
= NULL
;
896 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
897 _cleanup_free_
char *name
= NULL
, *type
= NULL
, *domain
= NULL
;
898 DnsQuestion
*question
;
899 DnsResourceRecord
*rr
;
906 if (q
->block_all_complete
> 0)
909 if ((q
->flags
& SD_RESOLVED_NO_ADDRESS
) == 0) {
910 DnsQuery
*bad
= NULL
;
911 bool have_success
= false;
913 LIST_FOREACH(auxiliary_queries
, aux
, q
->auxiliary_queries
) {
915 switch (aux
->state
) {
917 case DNS_TRANSACTION_PENDING
:
918 /* If an auxiliary query is still pending, let's wait */
921 case DNS_TRANSACTION_SUCCESS
:
922 if (aux
->auxiliary_result
== 0)
935 /* We can only return one error, hence pick the last error we encountered */
939 if (bad
->state
== DNS_TRANSACTION_SUCCESS
) {
940 assert(bad
->auxiliary_result
!= 0);
942 if (bad
->auxiliary_result
== -ELOOP
) {
943 r
= sd_bus_reply_method_errorf(q
->bus_request
, BUS_ERROR_CNAME_LOOP
, "CNAME loop detected, or CNAME resolving disabled on '%s'", dns_query_string(bad
));
947 r
= bad
->auxiliary_result
;
951 r
= reply_query_state(bad
);
956 r
= sd_bus_message_new_method_return(q
->bus_request
, &reply
);
960 r
= sd_bus_message_open_container(reply
, 'a', "(qqqsa(iiay)s)");
964 question
= dns_query_question_for_protocol(q
, q
->answer_protocol
);
966 DNS_ANSWER_FOREACH(rr
, q
->answer
) {
967 r
= dns_question_matches_rr(question
, rr
, NULL
);
973 r
= append_srv(q
, reply
, rr
);
976 if (r
== 0) /* not an SRV record */
980 canonical
= dns_resource_record_ref(rr
);
986 r
= sd_bus_reply_method_errorf(q
->bus_request
, BUS_ERROR_NO_SUCH_RR
, "'%s' does not have any RR of the requested type", dns_query_string(q
));
990 r
= sd_bus_message_close_container(reply
);
994 r
= sd_bus_message_open_container(reply
, 'a', "ay");
998 DNS_ANSWER_FOREACH(rr
, q
->answer
) {
999 r
= dns_question_matches_rr(question
, rr
, NULL
);
1005 r
= append_txt(reply
, rr
);
1010 r
= sd_bus_message_close_container(reply
);
1015 r
= dns_service_split(dns_resource_key_name(canonical
->key
), &name
, &type
, &domain
);
1019 r
= sd_bus_message_append(
1023 SD_RESOLVED_FLAGS_MAKE(q
->answer_protocol
, q
->answer_family
, dns_query_fully_authenticated(q
)));
1027 r
= sd_bus_send(q
->manager
->bus
, reply
, NULL
);
1031 log_error_errno(r
, "Failed to send service reply: %m");
1032 sd_bus_reply_method_errno(q
->bus_request
, r
, NULL
);
1038 static void resolve_service_hostname_complete(DnsQuery
*q
) {
1042 assert(q
->auxiliary_for
);
1044 if (q
->state
!= DNS_TRANSACTION_SUCCESS
) {
1045 resolve_service_all_complete(q
->auxiliary_for
);
1049 r
= dns_query_process_cname(q
);
1050 if (r
== DNS_QUERY_RESTARTED
) /* This was a cname, and the query was restarted. */
1053 /* This auxiliary lookup is finished or failed, let's see if all are finished now. */
1054 q
->auxiliary_result
= r
;
1055 resolve_service_all_complete(q
->auxiliary_for
);
1058 static int resolve_service_hostname(DnsQuery
*q
, DnsResourceRecord
*rr
, int ifindex
) {
1059 _cleanup_(dns_question_unrefp
) DnsQuestion
*question
= NULL
;
1066 assert(rr
->key
->type
== DNS_TYPE_SRV
);
1068 /* OK, we found an SRV record for the service. Let's resolve
1069 * the hostname included in it */
1071 r
= dns_question_new_address(&question
, q
->request_family
, rr
->srv
.name
, false);
1075 r
= dns_query_new(q
->manager
, &aux
, question
, question
, ifindex
, q
->flags
|SD_RESOLVED_NO_SEARCH
);
1079 aux
->request_family
= q
->request_family
;
1080 aux
->complete
= resolve_service_hostname_complete
;
1082 r
= dns_query_make_auxiliary(aux
, q
);
1084 /* Too many auxiliary lookups? If so, don't complain,
1085 * let's just not add this one, we already have more
1088 dns_query_free(aux
);
1094 /* Note that auxiliary queries do not track the original bus
1095 * client, only the primary request does that. */
1097 r
= dns_query_go(aux
);
1104 dns_query_free(aux
);
1108 static void bus_method_resolve_service_complete(DnsQuery
*q
) {
1109 bool has_root_domain
= false;
1110 DnsResourceRecord
*rr
;
1111 DnsQuestion
*question
;
1117 if (q
->state
!= DNS_TRANSACTION_SUCCESS
) {
1118 r
= reply_query_state(q
);
1122 r
= dns_query_process_cname(q
);
1124 r
= sd_bus_reply_method_errorf(q
->bus_request
, BUS_ERROR_CNAME_LOOP
, "CNAME loop detected, or CNAME resolving disabled on '%s'", dns_query_string(q
));
1129 if (r
== DNS_QUERY_RESTARTED
) /* This was a cname, and the query was restarted. */
1132 question
= dns_query_question_for_protocol(q
, q
->answer_protocol
);
1134 DNS_ANSWER_FOREACH_IFINDEX(rr
, ifindex
, q
->answer
) {
1135 r
= dns_question_matches_rr(question
, rr
, NULL
);
1141 if (rr
->key
->type
!= DNS_TYPE_SRV
)
1144 if (dns_name_is_root(rr
->srv
.name
)) {
1145 has_root_domain
= true;
1149 if ((q
->flags
& SD_RESOLVED_NO_ADDRESS
) == 0) {
1150 q
->block_all_complete
++;
1151 r
= resolve_service_hostname(q
, rr
, ifindex
);
1152 q
->block_all_complete
--;
1161 if (has_root_domain
&& found
<= 0) {
1162 /* If there's exactly one SRV RR and it uses
1163 * the root domain as hostname, then the
1164 * service is explicitly not offered on the
1165 * domain. Report this as a recognizable
1166 * error. See RFC 2782, Section "Usage
1168 r
= sd_bus_reply_method_errorf(q
->bus_request
, BUS_ERROR_NO_SUCH_SERVICE
, "'%s' does not provide the requested service", dns_query_string(q
));
1173 r
= sd_bus_reply_method_errorf(q
->bus_request
, BUS_ERROR_NO_SUCH_RR
, "'%s' does not have any RR of the requested type", dns_query_string(q
));
1177 /* Maybe we are already finished? check now... */
1178 resolve_service_all_complete(q
);
1183 log_error_errno(r
, "Failed to send service reply: %m");
1184 sd_bus_reply_method_errno(q
->bus_request
, r
, NULL
);
1190 static int bus_method_resolve_service(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1191 _cleanup_(dns_question_unrefp
) DnsQuestion
*question_idna
= NULL
, *question_utf8
= NULL
;
1192 const char *name
, *type
, *domain
;
1193 Manager
*m
= userdata
;
1194 int family
, ifindex
;
1202 assert_cc(sizeof(int) == sizeof(int32_t));
1204 r
= sd_bus_message_read(message
, "isssit", &ifindex
, &name
, &type
, &domain
, &family
, &flags
);
1208 if (!IN_SET(family
, AF_INET
, AF_INET6
, AF_UNSPEC
))
1209 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Unknown address family %i", family
);
1213 else if (!dns_service_name_is_valid(name
))
1214 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid service name '%s'", name
);
1218 else if (!dns_srv_type_is_valid(type
))
1219 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid SRV service type '%s'", type
);
1221 r
= dns_name_is_valid(domain
);
1225 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid domain '%s'", domain
);
1228 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Service name cannot be specified without service type.");
1230 r
= validate_and_mangle_ifindex_and_flags(ifindex
, &flags
, SD_RESOLVED_NO_TXT
|SD_RESOLVED_NO_ADDRESS
, error
);
1234 r
= dns_question_new_service(&question_utf8
, name
, type
, domain
, !(flags
& SD_RESOLVED_NO_TXT
), false);
1238 r
= dns_question_new_service(&question_idna
, name
, type
, domain
, !(flags
& SD_RESOLVED_NO_TXT
), true);
1242 r
= dns_query_new(m
, &q
, question_utf8
, question_idna
, ifindex
, flags
|SD_RESOLVED_NO_SEARCH
);
1246 q
->bus_request
= sd_bus_message_ref(message
);
1247 q
->request_family
= family
;
1248 q
->complete
= bus_method_resolve_service_complete
;
1250 r
= dns_query_bus_track(q
, message
);
1254 r
= dns_query_go(q
);
1265 int bus_dns_server_append(sd_bus_message
*reply
, DnsServer
*s
, bool with_ifindex
, bool extended
) {
1273 return sd_bus_message_append(reply
, "(iiayqs)", 0, AF_UNSPEC
, 0, 0, NULL
);
1275 return sd_bus_message_append(reply
, "(iiay)", 0, AF_UNSPEC
, 0);
1278 return sd_bus_message_append(reply
, "(iayqs)", AF_UNSPEC
, 0, 0, NULL
);
1280 return sd_bus_message_append(reply
, "(iay)", AF_UNSPEC
, 0);
1284 r
= sd_bus_message_open_container(reply
, 'r', with_ifindex
? (extended
? "iiayqs" : "iiay") : (extended
? "iayqs" : "iay"));
1289 r
= sd_bus_message_append(reply
, "i", dns_server_ifindex(s
));
1294 r
= sd_bus_message_append(reply
, "i", s
->family
);
1298 r
= sd_bus_message_append_array(reply
, 'y', &s
->address
, FAMILY_ADDRESS_SIZE(s
->family
));
1303 r
= sd_bus_message_append(reply
, "q", s
->port
);
1307 r
= sd_bus_message_append(reply
, "s", s
->server_name
);
1312 return sd_bus_message_close_container(reply
);
1315 static int bus_property_get_dns_servers_internal(
1318 const char *interface
,
1319 const char *property
,
1320 sd_bus_message
*reply
,
1322 sd_bus_error
*error
,
1325 Manager
*m
= userdata
;
1333 r
= sd_bus_message_open_container(reply
, 'a', extended
? "(iiayqs)" : "(iiay)");
1337 LIST_FOREACH(servers
, s
, m
->dns_servers
) {
1338 r
= bus_dns_server_append(reply
, s
, true, extended
);
1343 HASHMAP_FOREACH(l
, m
->links
)
1344 LIST_FOREACH(servers
, s
, l
->dns_servers
) {
1345 r
= bus_dns_server_append(reply
, s
, true, extended
);
1350 return sd_bus_message_close_container(reply
);
1353 static int bus_property_get_dns_servers(
1356 const char *interface
,
1357 const char *property
,
1358 sd_bus_message
*reply
,
1360 sd_bus_error
*error
) {
1361 return bus_property_get_dns_servers_internal(bus
, path
, interface
, property
, reply
, userdata
, error
, false);
1364 static int bus_property_get_dns_servers_ex(
1367 const char *interface
,
1368 const char *property
,
1369 sd_bus_message
*reply
,
1371 sd_bus_error
*error
) {
1372 return bus_property_get_dns_servers_internal(bus
, path
, interface
, property
, reply
, userdata
, error
, true);
1375 static int bus_property_get_fallback_dns_servers_internal(
1378 const char *interface
,
1379 const char *property
,
1380 sd_bus_message
*reply
,
1382 sd_bus_error
*error
,
1385 DnsServer
*s
, **f
= userdata
;
1391 r
= sd_bus_message_open_container(reply
, 'a', extended
? "(iiayqs)" : "(iiay)");
1395 LIST_FOREACH(servers
, s
, *f
) {
1396 r
= bus_dns_server_append(reply
, s
, true, extended
);
1401 return sd_bus_message_close_container(reply
);
1404 static int bus_property_get_fallback_dns_servers(
1407 const char *interface
,
1408 const char *property
,
1409 sd_bus_message
*reply
,
1411 sd_bus_error
*error
) {
1412 return bus_property_get_fallback_dns_servers_internal(bus
, path
, interface
, property
, reply
, userdata
, error
, false);
1415 static int bus_property_get_fallback_dns_servers_ex(
1418 const char *interface
,
1419 const char *property
,
1420 sd_bus_message
*reply
,
1422 sd_bus_error
*error
) {
1423 return bus_property_get_fallback_dns_servers_internal(bus
, path
, interface
, property
, reply
, userdata
, error
, true);
1426 static int bus_property_get_current_dns_server_internal(
1429 const char *interface
,
1430 const char *property
,
1431 sd_bus_message
*reply
,
1433 sd_bus_error
*error
,
1441 s
= *(DnsServer
**) userdata
;
1443 return bus_dns_server_append(reply
, s
, true, extended
);
1446 static int bus_property_get_current_dns_server(
1449 const char *interface
,
1450 const char *property
,
1451 sd_bus_message
*reply
,
1453 sd_bus_error
*error
) {
1454 return bus_property_get_current_dns_server_internal(bus
, path
, interface
, property
, reply
, userdata
, error
, false);
1457 static int bus_property_get_current_dns_server_ex(
1460 const char *interface
,
1461 const char *property
,
1462 sd_bus_message
*reply
,
1464 sd_bus_error
*error
) {
1465 return bus_property_get_current_dns_server_internal(bus
, path
, interface
, property
, reply
, userdata
, error
, true);
1468 static int bus_property_get_domains(
1471 const char *interface
,
1472 const char *property
,
1473 sd_bus_message
*reply
,
1475 sd_bus_error
*error
) {
1477 Manager
*m
= userdata
;
1485 r
= sd_bus_message_open_container(reply
, 'a', "(isb)");
1489 LIST_FOREACH(domains
, d
, m
->search_domains
) {
1490 r
= sd_bus_message_append(reply
, "(isb)", 0, d
->name
, d
->route_only
);
1495 HASHMAP_FOREACH(l
, m
->links
) {
1496 LIST_FOREACH(domains
, d
, l
->search_domains
) {
1497 r
= sd_bus_message_append(reply
, "(isb)", l
->ifindex
, d
->name
, d
->route_only
);
1503 return sd_bus_message_close_container(reply
);
1506 static int bus_property_get_transaction_statistics(
1509 const char *interface
,
1510 const char *property
,
1511 sd_bus_message
*reply
,
1513 sd_bus_error
*error
) {
1515 Manager
*m
= userdata
;
1520 return sd_bus_message_append(reply
, "(tt)",
1521 (uint64_t) hashmap_size(m
->dns_transactions
),
1522 (uint64_t) m
->n_transactions_total
);
1525 static int bus_property_get_cache_statistics(
1528 const char *interface
,
1529 const char *property
,
1530 sd_bus_message
*reply
,
1532 sd_bus_error
*error
) {
1534 uint64_t size
= 0, hit
= 0, miss
= 0;
1535 Manager
*m
= userdata
;
1541 LIST_FOREACH(scopes
, s
, m
->dns_scopes
) {
1542 size
+= dns_cache_size(&s
->cache
);
1543 hit
+= s
->cache
.n_hit
;
1544 miss
+= s
->cache
.n_miss
;
1547 return sd_bus_message_append(reply
, "(ttt)", size
, hit
, miss
);
1550 static int bus_property_get_dnssec_statistics(
1553 const char *interface
,
1554 const char *property
,
1555 sd_bus_message
*reply
,
1557 sd_bus_error
*error
) {
1559 Manager
*m
= userdata
;
1564 return sd_bus_message_append(reply
, "(tttt)",
1565 (uint64_t) m
->n_dnssec_verdict
[DNSSEC_SECURE
],
1566 (uint64_t) m
->n_dnssec_verdict
[DNSSEC_INSECURE
],
1567 (uint64_t) m
->n_dnssec_verdict
[DNSSEC_BOGUS
],
1568 (uint64_t) m
->n_dnssec_verdict
[DNSSEC_INDETERMINATE
]);
1571 static int bus_property_get_ntas(
1574 const char *interface
,
1575 const char *property
,
1576 sd_bus_message
*reply
,
1578 sd_bus_error
*error
) {
1580 Manager
*m
= userdata
;
1587 r
= sd_bus_message_open_container(reply
, 'a', "s");
1591 SET_FOREACH(domain
, m
->trust_anchor
.negative_by_name
) {
1592 r
= sd_bus_message_append(reply
, "s", domain
);
1597 return sd_bus_message_close_container(reply
);
1600 static BUS_DEFINE_PROPERTY_GET_ENUM(bus_property_get_dns_stub_listener_mode
, dns_stub_listener_mode
, DnsStubListenerMode
);
1601 static BUS_DEFINE_PROPERTY_GET(bus_property_get_dnssec_supported
, "b", Manager
, manager_dnssec_supported
);
1602 static BUS_DEFINE_PROPERTY_GET2(bus_property_get_dnssec_mode
, "s", Manager
, manager_get_dnssec_mode
, dnssec_mode_to_string
);
1603 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
);
1605 static int bus_method_reset_statistics(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1606 Manager
*m
= userdata
;
1612 LIST_FOREACH(scopes
, s
, m
->dns_scopes
)
1613 s
->cache
.n_hit
= s
->cache
.n_miss
= 0;
1615 m
->n_transactions_total
= 0;
1616 zero(m
->n_dnssec_verdict
);
1618 return sd_bus_reply_method_return(message
, NULL
);
1621 static int get_any_link(Manager
*m
, int ifindex
, Link
**ret
, sd_bus_error
*error
) {
1627 l
= hashmap_get(m
->links
, INT_TO_PTR(ifindex
));
1629 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_LINK
, "Link %i not known", ifindex
);
1635 static int call_link_method(Manager
*m
, sd_bus_message
*message
, sd_bus_message_handler_t handler
, sd_bus_error
*error
) {
1643 r
= bus_message_read_ifindex(message
, error
, &ifindex
);
1647 r
= get_any_link(m
, ifindex
, &l
, error
);
1651 return handler(message
, l
, error
);
1654 static int bus_method_set_link_dns_servers(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1655 return call_link_method(userdata
, message
, bus_link_method_set_dns_servers
, error
);
1658 static int bus_method_set_link_dns_servers_ex(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1659 return call_link_method(userdata
, message
, bus_link_method_set_dns_servers_ex
, error
);
1662 static int bus_method_set_link_domains(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1663 return call_link_method(userdata
, message
, bus_link_method_set_domains
, error
);
1666 static int bus_method_set_link_default_route(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1667 return call_link_method(userdata
, message
, bus_link_method_set_default_route
, error
);
1670 static int bus_method_set_link_llmnr(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1671 return call_link_method(userdata
, message
, bus_link_method_set_llmnr
, error
);
1674 static int bus_method_set_link_mdns(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1675 return call_link_method(userdata
, message
, bus_link_method_set_mdns
, error
);
1678 static int bus_method_set_link_dns_over_tls(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1679 return call_link_method(userdata
, message
, bus_link_method_set_dns_over_tls
, error
);
1682 static int bus_method_set_link_dnssec(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1683 return call_link_method(userdata
, message
, bus_link_method_set_dnssec
, error
);
1686 static int bus_method_set_link_dnssec_negative_trust_anchors(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1687 return call_link_method(userdata
, message
, bus_link_method_set_dnssec_negative_trust_anchors
, error
);
1690 static int bus_method_revert_link(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1691 return call_link_method(userdata
, message
, bus_link_method_revert
, error
);
1694 static int bus_method_get_link(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1695 _cleanup_free_
char *p
= NULL
;
1696 Manager
*m
= userdata
;
1703 r
= bus_message_read_ifindex(message
, error
, &ifindex
);
1707 r
= get_any_link(m
, ifindex
, &l
, error
);
1711 p
= link_bus_path(l
);
1715 return sd_bus_reply_method_return(message
, "o", p
);
1718 static int bus_method_flush_caches(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1719 Manager
*m
= userdata
;
1724 manager_flush_caches(m
);
1726 return sd_bus_reply_method_return(message
, NULL
);
1729 static int bus_method_reset_server_features(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1730 Manager
*m
= userdata
;
1735 manager_reset_server_features(m
);
1737 return sd_bus_reply_method_return(message
, NULL
);
1740 static int dnssd_service_on_bus_track(sd_bus_track
*t
, void *userdata
) {
1741 DnssdService
*s
= userdata
;
1746 log_debug("Client of active request vanished, destroying DNS-SD service.");
1747 dnssd_service_free(s
);
1752 static int bus_method_register_service(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1753 _cleanup_(sd_bus_creds_unrefp
) sd_bus_creds
*creds
= NULL
;
1754 _cleanup_(dnssd_service_freep
) DnssdService
*service
= NULL
;
1755 _cleanup_(sd_bus_track_unrefp
) sd_bus_track
*bus_track
= NULL
;
1756 _cleanup_free_
char *path
= NULL
;
1757 Manager
*m
= userdata
;
1758 DnssdService
*s
= NULL
;
1760 const char *name_template
;
1768 if (m
->mdns_support
!= RESOLVE_SUPPORT_YES
)
1769 return sd_bus_error_setf(error
, SD_BUS_ERROR_NOT_SUPPORTED
, "Support for MulticastDNS is disabled");
1771 service
= new0(DnssdService
, 1);
1775 r
= sd_bus_query_sender_creds(message
, SD_BUS_CREDS_EUID
, &creds
);
1779 r
= sd_bus_creds_get_euid(creds
, &euid
);
1782 service
->originator
= euid
;
1784 r
= sd_bus_message_read(message
, "sssqqq", &name
, &name_template
, &type
,
1785 &service
->port
, &service
->priority
,
1790 s
= hashmap_get(m
->dnssd_services
, name
);
1792 return sd_bus_error_setf(error
, BUS_ERROR_DNSSD_SERVICE_EXISTS
, "DNS-SD service '%s' exists already", name
);
1794 if (!dnssd_srv_type_is_valid(type
))
1795 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "DNS-SD service type '%s' is invalid", type
);
1797 r
= dnssd_render_instance_name(name_template
, NULL
);
1799 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "DNS-SD service name '%s' is invalid", name_template
);
1801 service
->name
= strdup(name
);
1805 service
->name_template
= strdup(name_template
);
1806 if (!service
->name_template
)
1809 service
->type
= strdup(type
);
1813 r
= sd_bus_message_enter_container(message
, SD_BUS_TYPE_ARRAY
, "a{say}");
1817 while ((r
= sd_bus_message_enter_container(message
, SD_BUS_TYPE_ARRAY
, "{say}")) > 0) {
1818 _cleanup_(dnssd_txtdata_freep
) DnssdTxtData
*txt_data
= NULL
;
1819 DnsTxtItem
*last
= NULL
;
1821 txt_data
= new0(DnssdTxtData
, 1);
1825 while ((r
= sd_bus_message_enter_container(message
, SD_BUS_TYPE_DICT_ENTRY
, "say")) > 0) {
1831 r
= sd_bus_message_read(message
, "s", &key
);
1836 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Keys in DNS-SD TXT RRs can't be empty");
1838 if (!ascii_is_valid(key
))
1839 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "TXT key '%s' contains non-ASCII symbols", key
);
1841 r
= sd_bus_message_read_array(message
, 'y', &value
, &size
);
1845 r
= dnssd_txt_item_new_from_data(key
, value
, size
, &i
);
1849 LIST_INSERT_AFTER(items
, txt_data
->txt
, last
, i
);
1852 r
= sd_bus_message_exit_container(message
);
1860 r
= sd_bus_message_exit_container(message
);
1864 if (txt_data
->txt
) {
1865 LIST_PREPEND(items
, service
->txt_data_items
, txt_data
);
1872 r
= sd_bus_message_exit_container(message
);
1876 if (!service
->txt_data_items
) {
1877 _cleanup_(dnssd_txtdata_freep
) DnssdTxtData
*txt_data
= NULL
;
1879 txt_data
= new0(DnssdTxtData
, 1);
1883 r
= dns_txt_item_new_empty(&txt_data
->txt
);
1887 LIST_PREPEND(items
, service
->txt_data_items
, txt_data
);
1891 r
= sd_bus_path_encode("/org/freedesktop/resolve1/dnssd", service
->name
, &path
);
1895 r
= bus_verify_polkit_async(message
, CAP_SYS_ADMIN
,
1896 "org.freedesktop.resolve1.register-service",
1897 NULL
, false, UID_INVALID
,
1898 &m
->polkit_registry
, error
);
1902 return 1; /* Polkit will call us back */
1904 r
= hashmap_ensure_allocated(&m
->dnssd_services
, &string_hash_ops
);
1908 r
= hashmap_put(m
->dnssd_services
, service
->name
, service
);
1912 r
= sd_bus_track_new(sd_bus_message_get_bus(message
), &bus_track
, dnssd_service_on_bus_track
, service
);
1916 r
= sd_bus_track_add_sender(bus_track
, message
);
1920 service
->manager
= m
;
1924 manager_refresh_rrs(m
);
1926 return sd_bus_reply_method_return(message
, "o", path
);
1929 static int call_dnssd_method(Manager
*m
, sd_bus_message
*message
, sd_bus_message_handler_t handler
, sd_bus_error
*error
) {
1930 _cleanup_free_
char *name
= NULL
;
1931 DnssdService
*s
= NULL
;
1939 r
= sd_bus_message_read(message
, "o", &path
);
1943 r
= sd_bus_path_decode(path
, "/org/freedesktop/resolve1/dnssd", &name
);
1945 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_DNSSD_SERVICE
, "DNS-SD service with object path '%s' does not exist", path
);
1949 s
= hashmap_get(m
->dnssd_services
, name
);
1951 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_DNSSD_SERVICE
, "DNS-SD service '%s' not known", name
);
1953 return handler(message
, s
, error
);
1956 static int bus_method_unregister_service(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1957 Manager
*m
= userdata
;
1962 return call_dnssd_method(m
, message
, bus_dnssd_method_unregister
, error
);
1965 static const sd_bus_vtable resolve_vtable
[] = {
1966 SD_BUS_VTABLE_START(0),
1967 SD_BUS_PROPERTY("LLMNRHostname", "s", NULL
, offsetof(Manager
, llmnr_hostname
), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
1968 SD_BUS_PROPERTY("LLMNR", "s", bus_property_get_resolve_support
, offsetof(Manager
, llmnr_support
), 0),
1969 SD_BUS_PROPERTY("MulticastDNS", "s", bus_property_get_resolve_support
, offsetof(Manager
, mdns_support
), 0),
1970 SD_BUS_PROPERTY("DNSOverTLS", "s", bus_property_get_dns_over_tls_mode
, 0, 0),
1971 SD_BUS_PROPERTY("DNS", "a(iiay)", bus_property_get_dns_servers
, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
1972 SD_BUS_PROPERTY("DNSEx", "a(iiayqs)", bus_property_get_dns_servers_ex
, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
1973 SD_BUS_PROPERTY("FallbackDNS", "a(iiay)", bus_property_get_fallback_dns_servers
, offsetof(Manager
, fallback_dns_servers
), SD_BUS_VTABLE_PROPERTY_CONST
),
1974 SD_BUS_PROPERTY("FallbackDNSEx", "a(iiayqs)", bus_property_get_fallback_dns_servers_ex
, offsetof(Manager
, fallback_dns_servers
), SD_BUS_VTABLE_PROPERTY_CONST
),
1975 SD_BUS_PROPERTY("CurrentDNSServer", "(iiay)", bus_property_get_current_dns_server
, offsetof(Manager
, current_dns_server
), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
1976 SD_BUS_PROPERTY("CurrentDNSServerEx", "(iiayqs)", bus_property_get_current_dns_server_ex
, offsetof(Manager
, current_dns_server
), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
1977 SD_BUS_PROPERTY("Domains", "a(isb)", bus_property_get_domains
, 0, 0),
1978 SD_BUS_PROPERTY("TransactionStatistics", "(tt)", bus_property_get_transaction_statistics
, 0, 0),
1979 SD_BUS_PROPERTY("CacheStatistics", "(ttt)", bus_property_get_cache_statistics
, 0, 0),
1980 SD_BUS_PROPERTY("DNSSEC", "s", bus_property_get_dnssec_mode
, 0, 0),
1981 SD_BUS_PROPERTY("DNSSECStatistics", "(tttt)", bus_property_get_dnssec_statistics
, 0, 0),
1982 SD_BUS_PROPERTY("DNSSECSupported", "b", bus_property_get_dnssec_supported
, 0, 0),
1983 SD_BUS_PROPERTY("DNSSECNegativeTrustAnchors", "as", bus_property_get_ntas
, 0, 0),
1984 SD_BUS_PROPERTY("DNSStubListener", "s", bus_property_get_dns_stub_listener_mode
, offsetof(Manager
, dns_stub_listener_mode
), 0),
1986 SD_BUS_METHOD_WITH_ARGS("ResolveHostname",
1987 SD_BUS_ARGS("i", ifindex
, "s", name
, "i", family
, "t", flags
),
1988 SD_BUS_RESULT("a(iiay)", addresses
, "s", canonical
, "t", flags
),
1989 bus_method_resolve_hostname
,
1990 SD_BUS_VTABLE_UNPRIVILEGED
),
1991 SD_BUS_METHOD_WITH_ARGS("ResolveAddress",
1992 SD_BUS_ARGS("i", ifindex
, "i", family
, "ay", address
, "t", flags
),
1993 SD_BUS_RESULT("a(is)", names
, "t", flags
),
1994 bus_method_resolve_address
,
1995 SD_BUS_VTABLE_UNPRIVILEGED
),
1996 SD_BUS_METHOD_WITH_ARGS("ResolveRecord",
1997 SD_BUS_ARGS("i", ifindex
, "s", name
, "q", class, "q", type
, "t", flags
),
1998 SD_BUS_RESULT("a(iqqay)", records
, "t", flags
),
1999 bus_method_resolve_record
,
2000 SD_BUS_VTABLE_UNPRIVILEGED
),
2001 SD_BUS_METHOD_WITH_ARGS("ResolveService",
2002 SD_BUS_ARGS("i", ifindex
,
2008 SD_BUS_RESULT("a(qqqsa(iiay)s)", srv_data
,
2010 "s", canonical_name
,
2011 "s", canonical_type
,
2012 "s", canonical_domain
,
2014 bus_method_resolve_service
,
2015 SD_BUS_VTABLE_UNPRIVILEGED
),
2016 SD_BUS_METHOD_WITH_ARGS("GetLink",
2017 SD_BUS_ARGS("i", ifindex
),
2018 SD_BUS_RESULT("o", path
),
2019 bus_method_get_link
,
2020 SD_BUS_VTABLE_UNPRIVILEGED
),
2021 SD_BUS_METHOD_WITH_ARGS("SetLinkDNS",
2022 SD_BUS_ARGS("i", ifindex
, "a(iay)", addresses
),
2024 bus_method_set_link_dns_servers
,
2025 SD_BUS_VTABLE_UNPRIVILEGED
),
2026 SD_BUS_METHOD_WITH_ARGS("SetLinkDNSEx",
2027 SD_BUS_ARGS("i", ifindex
, "a(iayqs)", addresses
),
2029 bus_method_set_link_dns_servers_ex
,
2030 SD_BUS_VTABLE_UNPRIVILEGED
),
2031 SD_BUS_METHOD_WITH_ARGS("SetLinkDomains",
2032 SD_BUS_ARGS("i", ifindex
, "a(sb)", domains
),
2034 bus_method_set_link_domains
,
2035 SD_BUS_VTABLE_UNPRIVILEGED
),
2036 SD_BUS_METHOD_WITH_ARGS("SetLinkDefaultRoute",
2037 SD_BUS_ARGS("i", ifindex
, "b", enable
),
2039 bus_method_set_link_default_route
,
2040 SD_BUS_VTABLE_UNPRIVILEGED
),
2041 SD_BUS_METHOD_WITH_ARGS("SetLinkLLMNR",
2042 SD_BUS_ARGS("i", ifindex
, "s", mode
),
2044 bus_method_set_link_llmnr
,
2045 SD_BUS_VTABLE_UNPRIVILEGED
),
2046 SD_BUS_METHOD_WITH_ARGS("SetLinkMulticastDNS",
2047 SD_BUS_ARGS("i", ifindex
, "s", mode
),
2049 bus_method_set_link_mdns
,
2050 SD_BUS_VTABLE_UNPRIVILEGED
),
2051 SD_BUS_METHOD_WITH_ARGS("SetLinkDNSOverTLS",
2052 SD_BUS_ARGS("i", ifindex
, "s", mode
),
2054 bus_method_set_link_dns_over_tls
,
2055 SD_BUS_VTABLE_UNPRIVILEGED
),
2056 SD_BUS_METHOD_WITH_ARGS("SetLinkDNSSEC",
2057 SD_BUS_ARGS("i", ifindex
, "s", mode
),
2059 bus_method_set_link_dnssec
,
2060 SD_BUS_VTABLE_UNPRIVILEGED
),
2061 SD_BUS_METHOD_WITH_ARGS("SetLinkDNSSECNegativeTrustAnchors",
2062 SD_BUS_ARGS("i", ifindex
, "as", names
),
2064 bus_method_set_link_dnssec_negative_trust_anchors
,
2065 SD_BUS_VTABLE_UNPRIVILEGED
),
2066 SD_BUS_METHOD_WITH_ARGS("RevertLink",
2067 SD_BUS_ARGS("i", ifindex
),
2069 bus_method_revert_link
,
2070 SD_BUS_VTABLE_UNPRIVILEGED
),
2071 SD_BUS_METHOD_WITH_ARGS("RegisterService",
2072 SD_BUS_ARGS("s", name
,
2076 "q", service_priority
,
2077 "q", service_weight
,
2078 "aa{say}", txt_datas
),
2079 SD_BUS_RESULT("o", service_path
),
2080 bus_method_register_service
,
2081 SD_BUS_VTABLE_UNPRIVILEGED
),
2082 SD_BUS_METHOD_WITH_ARGS("UnregisterService",
2083 SD_BUS_ARGS("o", service_path
),
2085 bus_method_unregister_service
,
2086 SD_BUS_VTABLE_UNPRIVILEGED
),
2087 SD_BUS_METHOD_WITH_ARGS("ResetStatistics",
2090 bus_method_reset_statistics
,
2091 SD_BUS_VTABLE_UNPRIVILEGED
),
2092 SD_BUS_METHOD_WITH_ARGS("FlushCaches",
2095 bus_method_flush_caches
,
2096 SD_BUS_VTABLE_UNPRIVILEGED
),
2097 SD_BUS_METHOD_WITH_ARGS("ResetServerFeatures",
2100 bus_method_reset_server_features
,
2101 SD_BUS_VTABLE_UNPRIVILEGED
),
2106 const BusObjectImplementation manager_object
= {
2107 "/org/freedesktop/resolve1",
2108 "org.freedesktop.resolve1.Manager",
2109 .vtables
= BUS_VTABLES(resolve_vtable
),
2110 .children
= BUS_IMPLEMENTATIONS(&link_object
,
2114 static int match_prepare_for_sleep(sd_bus_message
*message
, void *userdata
, sd_bus_error
*ret_error
) {
2115 Manager
*m
= userdata
;
2121 r
= sd_bus_message_read(message
, "b", &b
);
2123 bus_log_parse_error(r
);
2130 log_debug("Coming back from suspend, verifying all RRs...");
2132 manager_verify_all(m
);
2136 int manager_connect_bus(Manager
*m
) {
2144 r
= bus_open_system_watch_bind_with_description(&m
->bus
, "bus-api-resolve");
2146 return log_error_errno(r
, "Failed to connect to system bus: %m");
2148 r
= bus_add_implementation(m
->bus
, &manager_object
, m
);
2152 r
= bus_log_control_api_register(m
->bus
);
2156 r
= sd_bus_request_name_async(m
->bus
, NULL
, "org.freedesktop.resolve1", 0, NULL
, NULL
);
2158 return log_error_errno(r
, "Failed to request name: %m");
2160 r
= sd_bus_attach_event(m
->bus
, m
->event
, 0);
2162 return log_error_errno(r
, "Failed to attach bus to event loop: %m");
2164 r
= sd_bus_match_signal_async(
2167 "org.freedesktop.login1",
2168 "/org/freedesktop/login1",
2169 "org.freedesktop.login1.Manager",
2171 match_prepare_for_sleep
,
2175 log_warning_errno(r
, "Failed to request match for PrepareForSleep, ignoring: %m");
2180 int _manager_send_changed(Manager
*manager
, const char *property
, ...) {
2183 char **l
= strv_from_stdarg_alloca(property
);
2185 int r
= sd_bus_emit_properties_changed_strv(
2187 "/org/freedesktop/resolve1",
2188 "org.freedesktop.resolve1.Manager",
2191 log_notice_errno(r
, "Failed to emit notification about changed property %s: %m", property
);