1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2014 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
22 #include "alloc-util.h"
23 #include "bus-common-errors.h"
25 #include "dns-domain.h"
26 #include "resolved-bus.h"
27 #include "resolved-def.h"
29 static int reply_query_state(DnsQuery
*q
) {
30 _cleanup_free_
char *ip
= NULL
;
34 if (q
->request_address_valid
) {
35 r
= in_addr_to_string(q
->request_family
, &q
->request_address
, &ip
);
41 name
= dns_question_first_name(q
->question
);
45 case DNS_TRANSACTION_NO_SERVERS
:
46 return sd_bus_reply_method_errorf(q
->request
, BUS_ERROR_NO_NAME_SERVERS
, "No appropriate name servers or networks for name found");
48 case DNS_TRANSACTION_TIMEOUT
:
49 return sd_bus_reply_method_errorf(q
->request
, SD_BUS_ERROR_TIMEOUT
, "Query timed out");
51 case DNS_TRANSACTION_ATTEMPTS_MAX_REACHED
:
52 return sd_bus_reply_method_errorf(q
->request
, SD_BUS_ERROR_TIMEOUT
, "All attempts to contact name servers or networks failed");
54 case DNS_TRANSACTION_INVALID_REPLY
:
55 return sd_bus_reply_method_errorf(q
->request
, BUS_ERROR_INVALID_REPLY
, "Received invalid reply");
57 case DNS_TRANSACTION_RESOURCES
:
58 return sd_bus_reply_method_errorf(q
->request
, BUS_ERROR_NO_RESOURCES
, "Not enough resources");
60 case DNS_TRANSACTION_CONNECTION_FAILURE
:
61 return sd_bus_reply_method_errorf(q
->request
, BUS_ERROR_CONNECTION_FAILURE
, "DNS server connection failure");
63 case DNS_TRANSACTION_ABORTED
:
64 return sd_bus_reply_method_errorf(q
->request
, BUS_ERROR_ABORTED
, "Query aborted");
66 case DNS_TRANSACTION_DNSSEC_FAILED
:
67 return sd_bus_reply_method_errorf(q
->request
, BUS_ERROR_DNSSEC_FAILED
, "DNSSEC validation failed: %s",
68 dnssec_result_to_string(q
->answer_dnssec_result
));
70 case DNS_TRANSACTION_NO_TRUST_ANCHOR
:
71 return sd_bus_reply_method_errorf(q
->request
, BUS_ERROR_NO_TRUST_ANCHOR
, "No suitable trust anchor known");
73 case DNS_TRANSACTION_RCODE_FAILURE
: {
74 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
76 if (q
->answer_rcode
== DNS_RCODE_NXDOMAIN
)
77 sd_bus_error_setf(&error
, _BUS_ERROR_DNS
"NXDOMAIN", "'%s' not found", name
);
80 char p
[3]; /* the rcode is 4 bits long */
82 rc
= dns_rcode_to_string(q
->answer_rcode
);
84 sprintf(p
, "%i", q
->answer_rcode
);
88 n
= strjoina(_BUS_ERROR_DNS
, rc
);
89 sd_bus_error_setf(&error
, n
, "Could not resolve '%s', server or network returned error %s", name
, rc
);
92 return sd_bus_reply_method_error(q
->request
, &error
);
95 case DNS_TRANSACTION_NULL
:
96 case DNS_TRANSACTION_PENDING
:
97 case DNS_TRANSACTION_SUCCESS
:
99 assert_not_reached("Impossible state");
103 static int append_address(sd_bus_message
*reply
, DnsResourceRecord
*rr
, int ifindex
) {
109 r
= sd_bus_message_open_container(reply
, 'r', "iiay");
113 r
= sd_bus_message_append(reply
, "i", ifindex
);
117 if (rr
->key
->type
== DNS_TYPE_A
) {
118 r
= sd_bus_message_append(reply
, "i", AF_INET
);
122 r
= sd_bus_message_append_array(reply
, 'y', &rr
->a
.in_addr
, sizeof(struct in_addr
));
124 } else if (rr
->key
->type
== DNS_TYPE_AAAA
) {
125 r
= sd_bus_message_append(reply
, "i", AF_INET6
);
129 r
= sd_bus_message_append_array(reply
, 'y', &rr
->aaaa
.in6_addr
, sizeof(struct in6_addr
));
131 return -EAFNOSUPPORT
;
136 r
= sd_bus_message_close_container(reply
);
143 static void bus_method_resolve_hostname_complete(DnsQuery
*q
) {
144 _cleanup_(dns_resource_record_unrefp
) DnsResourceRecord
*canonical
= NULL
;
145 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
151 if (q
->state
!= DNS_TRANSACTION_SUCCESS
) {
152 r
= reply_query_state(q
);
156 r
= dns_query_process_cname(q
);
158 r
= sd_bus_reply_method_errorf(q
->request
, BUS_ERROR_CNAME_LOOP
, "CNAME loop detected, or CNAME resolving disabled on '%s'", dns_question_first_name(q
->question
));
163 if (r
== DNS_QUERY_RESTARTED
) /* This was a cname, and the query was restarted. */
166 r
= sd_bus_message_new_method_return(q
->request
, &reply
);
170 r
= sd_bus_message_open_container(reply
, 'a', "(iiay)");
175 DnsResourceRecord
*rr
;
178 DNS_ANSWER_FOREACH_IFINDEX(rr
, ifindex
, q
->answer
) {
179 r
= dns_question_matches_rr(q
->question
, rr
, DNS_SEARCH_DOMAIN_NAME(q
->answer_search_domain
));
185 r
= append_address(reply
, rr
, ifindex
);
190 canonical
= dns_resource_record_ref(rr
);
197 r
= sd_bus_reply_method_errorf(q
->request
, BUS_ERROR_NO_SUCH_RR
, "'%s' does not have any RR of the requested type", dns_question_first_name(q
->question
));
201 r
= sd_bus_message_close_container(reply
);
205 /* Return the precise spelling and uppercasing and CNAME target reported by the server */
207 r
= sd_bus_message_append(
209 DNS_RESOURCE_KEY_NAME(canonical
->key
),
210 SD_RESOLVED_FLAGS_MAKE(q
->answer_protocol
, q
->answer_family
, q
->answer_authenticated
));
214 r
= sd_bus_send(q
->manager
->bus
, reply
, NULL
);
218 log_error_errno(r
, "Failed to send hostname reply: %m");
219 sd_bus_reply_method_errno(q
->request
, r
, NULL
);
225 static int check_ifindex_flags(int ifindex
, uint64_t *flags
, uint64_t ok
, sd_bus_error
*error
) {
229 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid interface index");
231 if (*flags
& ~(SD_RESOLVED_PROTOCOLS_ALL
|SD_RESOLVED_NO_CNAME
|ok
))
232 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid flags parameter");
234 if ((*flags
& SD_RESOLVED_PROTOCOLS_ALL
) == 0) /* If no protocol is enabled, enable all */
235 *flags
|= SD_RESOLVED_PROTOCOLS_ALL
;
240 static int bus_method_resolve_hostname(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
241 _cleanup_(dns_question_unrefp
) DnsQuestion
*question
= NULL
;
242 Manager
*m
= userdata
;
243 const char *hostname
;
252 assert_cc(sizeof(int) == sizeof(int32_t));
254 r
= sd_bus_message_read(message
, "isit", &ifindex
, &hostname
, &family
, &flags
);
258 if (!IN_SET(family
, AF_INET
, AF_INET6
, AF_UNSPEC
))
259 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Unknown address family %i", family
);
261 r
= dns_name_is_valid(hostname
);
265 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid hostname '%s'", hostname
);
267 r
= check_ifindex_flags(ifindex
, &flags
, SD_RESOLVED_NO_SEARCH
, error
);
271 r
= dns_question_new_address(&question
, family
, hostname
);
275 r
= dns_query_new(m
, &q
, question
, ifindex
, flags
);
279 q
->request
= sd_bus_message_ref(message
);
280 q
->request_family
= family
;
281 q
->complete
= bus_method_resolve_hostname_complete
;
283 r
= dns_query_bus_track(q
, message
);
298 static void bus_method_resolve_address_complete(DnsQuery
*q
) {
299 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
300 DnsResourceRecord
*rr
;
306 if (q
->state
!= DNS_TRANSACTION_SUCCESS
) {
307 r
= reply_query_state(q
);
311 r
= dns_query_process_cname(q
);
313 r
= sd_bus_reply_method_errorf(q
->request
, BUS_ERROR_CNAME_LOOP
, "CNAME loop detected, or CNAME resolving disabled on '%s'", dns_question_first_name(q
->question
));
318 if (r
== DNS_QUERY_RESTARTED
) /* This was a cname, and the query was restarted. */
321 r
= sd_bus_message_new_method_return(q
->request
, &reply
);
325 r
= sd_bus_message_open_container(reply
, 'a', "(is)");
330 DNS_ANSWER_FOREACH_IFINDEX(rr
, ifindex
, q
->answer
) {
331 r
= dns_question_matches_rr(q
->question
, rr
, NULL
);
337 r
= sd_bus_message_append(reply
, "(is)", ifindex
, rr
->ptr
.name
);
346 _cleanup_free_
char *ip
= NULL
;
348 in_addr_to_string(q
->request_family
, &q
->request_address
, &ip
);
349 r
= sd_bus_reply_method_errorf(q
->request
, BUS_ERROR_NO_SUCH_RR
, "Address '%s' does not have any RR of requested type", strna(ip
));
353 r
= sd_bus_message_close_container(reply
);
357 r
= sd_bus_message_append(reply
, "t", SD_RESOLVED_FLAGS_MAKE(q
->answer_protocol
, q
->answer_family
, q
->answer_authenticated
));
361 r
= sd_bus_send(q
->manager
->bus
, reply
, NULL
);
365 log_error_errno(r
, "Failed to send address reply: %m");
366 sd_bus_reply_method_errno(q
->request
, r
, NULL
);
372 static int bus_method_resolve_address(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
373 _cleanup_(dns_question_unrefp
) DnsQuestion
*question
= NULL
;
374 Manager
*m
= userdata
;
385 assert_cc(sizeof(int) == sizeof(int32_t));
387 r
= sd_bus_message_read(message
, "ii", &ifindex
, &family
);
391 if (!IN_SET(family
, AF_INET
, AF_INET6
))
392 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Unknown address family %i", family
);
394 r
= sd_bus_message_read_array(message
, 'y', &d
, &sz
);
398 if (sz
!= FAMILY_ADDRESS_SIZE(family
))
399 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid address size");
401 r
= sd_bus_message_read(message
, "t", &flags
);
405 r
= check_ifindex_flags(ifindex
, &flags
, 0, error
);
409 r
= dns_question_new_reverse(&question
, family
, d
);
413 r
= dns_query_new(m
, &q
, question
, ifindex
, flags
|SD_RESOLVED_NO_SEARCH
);
417 q
->request
= sd_bus_message_ref(message
);
418 q
->request_family
= family
;
419 memcpy(&q
->request_address
, d
, sz
);
420 q
->complete
= bus_method_resolve_address_complete
;
422 r
= dns_query_bus_track(q
, message
);
437 static int bus_message_append_rr(sd_bus_message
*m
, DnsResourceRecord
*rr
, int ifindex
) {
443 r
= sd_bus_message_open_container(m
, 'r', "iqqay");
447 r
= sd_bus_message_append(m
, "iqq",
454 r
= dns_resource_record_to_wire_format(rr
, false);
458 r
= sd_bus_message_append_array(m
, 'y', rr
->wire_format
, rr
->wire_format_size
);
462 return sd_bus_message_close_container(m
);
465 static void bus_method_resolve_record_complete(DnsQuery
*q
) {
466 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
472 if (q
->state
!= DNS_TRANSACTION_SUCCESS
) {
473 r
= reply_query_state(q
);
477 r
= dns_query_process_cname(q
);
479 r
= sd_bus_reply_method_errorf(q
->request
, BUS_ERROR_CNAME_LOOP
, "CNAME loop detected, or CNAME resolving disabled on '%s'", dns_question_first_name(q
->question
));
484 if (r
== DNS_QUERY_RESTARTED
) /* This was a cname, and the query was restarted. */
487 r
= sd_bus_message_new_method_return(q
->request
, &reply
);
491 r
= sd_bus_message_open_container(reply
, 'a', "(iqqay)");
496 DnsResourceRecord
*rr
;
499 DNS_ANSWER_FOREACH_IFINDEX(rr
, ifindex
, q
->answer
) {
500 r
= dns_question_matches_rr(q
->question
, rr
, NULL
);
506 r
= bus_message_append_rr(reply
, rr
, ifindex
);
515 r
= sd_bus_reply_method_errorf(q
->request
, BUS_ERROR_NO_SUCH_RR
, "Name '%s' does not have any RR of the requested type", dns_question_first_name(q
->question
));
519 r
= sd_bus_message_close_container(reply
);
523 r
= sd_bus_message_append(reply
, "t", SD_RESOLVED_FLAGS_MAKE(q
->answer_protocol
, q
->answer_family
, q
->answer_authenticated
));
527 r
= sd_bus_send(q
->manager
->bus
, reply
, NULL
);
531 log_error_errno(r
, "Failed to send record reply: %m");
532 sd_bus_reply_method_errno(q
->request
, r
, NULL
);
538 static int bus_method_resolve_record(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
539 _cleanup_(dns_resource_key_unrefp
) DnsResourceKey
*key
= NULL
;
540 _cleanup_(dns_question_unrefp
) DnsQuestion
*question
= NULL
;
541 Manager
*m
= userdata
;
542 uint16_t class, type
;
551 assert_cc(sizeof(int) == sizeof(int32_t));
553 r
= sd_bus_message_read(message
, "isqqt", &ifindex
, &name
, &class, &type
, &flags
);
557 r
= dns_name_is_valid(name
);
561 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid name '%s'", name
);
563 if (!dns_type_is_valid_query(type
))
564 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid RR type for query %" PRIu16
, type
);
566 r
= check_ifindex_flags(ifindex
, &flags
, 0, error
);
570 question
= dns_question_new(1);
574 key
= dns_resource_key_new(class, type
, name
);
578 r
= dns_question_add(question
, key
);
582 r
= dns_query_new(m
, &q
, question
, ifindex
, flags
|SD_RESOLVED_NO_SEARCH
);
586 q
->request
= sd_bus_message_ref(message
);
587 q
->complete
= bus_method_resolve_record_complete
;
589 r
= dns_query_bus_track(q
, message
);
604 static int append_srv(DnsQuery
*q
, sd_bus_message
*reply
, DnsResourceRecord
*rr
) {
605 _cleanup_(dns_resource_record_unrefp
) DnsResourceRecord
*canonical
= NULL
;
614 if (rr
->key
->type
!= DNS_TYPE_SRV
)
617 if ((q
->flags
& SD_RESOLVED_NO_ADDRESS
) == 0) {
618 /* First, let's see if we could find an appropriate A or AAAA
619 * record for the SRV record */
620 LIST_FOREACH(auxiliary_queries
, aux
, q
->auxiliary_queries
) {
621 DnsResourceRecord
*zz
;
623 if (aux
->state
!= DNS_TRANSACTION_SUCCESS
)
625 if (aux
->auxiliary_result
!= 0)
628 r
= dns_name_equal(dns_question_first_name(aux
->question
), rr
->srv
.name
);
634 DNS_ANSWER_FOREACH(zz
, aux
->answer
) {
636 r
= dns_question_matches_rr(aux
->question
, zz
, NULL
);
642 canonical
= dns_resource_record_ref(zz
);
650 /* Is there are successful A/AAAA lookup for this SRV RR? If not, don't add it */
655 r
= sd_bus_message_open_container(reply
, 'r', "qqqsa(iiay)s");
659 r
= sd_bus_message_append(
662 rr
->srv
.priority
, rr
->srv
.weight
, rr
->srv
.port
, rr
->srv
.name
);
666 r
= sd_bus_message_open_container(reply
, 'a', "(iiay)");
670 if ((q
->flags
& SD_RESOLVED_NO_ADDRESS
) == 0) {
671 LIST_FOREACH(auxiliary_queries
, aux
, q
->auxiliary_queries
) {
672 DnsResourceRecord
*zz
;
675 if (aux
->state
!= DNS_TRANSACTION_SUCCESS
)
677 if (aux
->auxiliary_result
!= 0)
680 r
= dns_name_equal(dns_question_first_name(aux
->question
), rr
->srv
.name
);
686 DNS_ANSWER_FOREACH_IFINDEX(zz
, ifindex
, aux
->answer
) {
688 r
= dns_question_matches_rr(aux
->question
, zz
, NULL
);
694 r
= append_address(reply
, zz
, ifindex
);
701 r
= sd_bus_message_close_container(reply
);
705 /* Note that above we appended the hostname as encoded in the
706 * SRV, and here the canonical hostname this maps to. */
707 r
= sd_bus_message_append(reply
, "s", canonical
? DNS_RESOURCE_KEY_NAME(canonical
->key
) : rr
->srv
.name
);
711 r
= sd_bus_message_close_container(reply
);
718 static int append_txt(sd_bus_message
*reply
, DnsResourceRecord
*rr
) {
726 if (rr
->key
->type
!= DNS_TYPE_TXT
)
729 LIST_FOREACH(items
, i
, rr
->txt
.items
) {
734 r
= sd_bus_message_append_array(reply
, 'y', i
->data
, i
->length
);
742 static void resolve_service_all_complete(DnsQuery
*q
) {
743 _cleanup_(dns_resource_record_unrefp
) DnsResourceRecord
*canonical
= NULL
;
744 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
745 _cleanup_free_
char *name
= NULL
, *type
= NULL
, *domain
= NULL
;
747 unsigned added
= false;
752 if (q
->block_all_complete
> 0)
755 if ((q
->flags
& SD_RESOLVED_NO_ADDRESS
) == 0) {
756 DnsQuery
*bad
= NULL
;
757 bool have_success
= false;
759 LIST_FOREACH(auxiliary_queries
, aux
, q
->auxiliary_queries
) {
761 switch (aux
->state
) {
763 case DNS_TRANSACTION_PENDING
:
764 /* If an auxiliary query is still pending, let's wait */
767 case DNS_TRANSACTION_SUCCESS
:
768 if (aux
->auxiliary_result
== 0)
781 /* We can only return one error, hence pick the last error we encountered */
785 if (bad
->state
== DNS_TRANSACTION_SUCCESS
) {
786 assert(bad
->auxiliary_result
!= 0);
788 if (bad
->auxiliary_result
== -ELOOP
) {
789 r
= sd_bus_reply_method_errorf(q
->request
, BUS_ERROR_CNAME_LOOP
, "CNAME loop detected, or CNAME resolving disabled on '%s'", dns_question_first_name(bad
->question
));
793 r
= bad
->auxiliary_result
;
797 r
= reply_query_state(bad
);
802 r
= sd_bus_message_new_method_return(q
->request
, &reply
);
806 r
= sd_bus_message_open_container(reply
, 'a', "(qqqsa(iiay)s)");
811 DnsResourceRecord
*rr
;
813 DNS_ANSWER_FOREACH(rr
, q
->answer
) {
814 r
= dns_question_matches_rr(q
->question
, rr
, NULL
);
820 r
= append_srv(q
, reply
, rr
);
823 if (r
== 0) /* not an SRV record */
827 canonical
= dns_resource_record_ref(rr
);
834 r
= sd_bus_reply_method_errorf(q
->request
, BUS_ERROR_NO_SUCH_RR
, "'%s' does not have any RR of the requested type", dns_question_first_name(q
->question
));
838 r
= sd_bus_message_close_container(reply
);
842 r
= sd_bus_message_open_container(reply
, 'a', "ay");
847 DnsResourceRecord
*rr
;
849 DNS_ANSWER_FOREACH(rr
, q
->answer
) {
850 r
= dns_question_matches_rr(q
->question
, rr
, NULL
);
856 r
= append_txt(reply
, rr
);
862 r
= sd_bus_message_close_container(reply
);
867 r
= dns_service_split(DNS_RESOURCE_KEY_NAME(canonical
->key
), &name
, &type
, &domain
);
871 r
= sd_bus_message_append(
875 SD_RESOLVED_FLAGS_MAKE(q
->answer_protocol
, q
->answer_family
, q
->answer_authenticated
));
879 r
= sd_bus_send(q
->manager
->bus
, reply
, NULL
);
883 log_error_errno(r
, "Failed to send service reply: %m");
884 sd_bus_reply_method_errno(q
->request
, r
, NULL
);
890 static void resolve_service_hostname_complete(DnsQuery
*q
) {
894 assert(q
->auxiliary_for
);
896 if (q
->state
!= DNS_TRANSACTION_SUCCESS
) {
897 resolve_service_all_complete(q
->auxiliary_for
);
901 r
= dns_query_process_cname(q
);
902 if (r
== DNS_QUERY_RESTARTED
) /* This was a cname, and the query was restarted. */
905 /* This auxiliary lookup is finished or failed, let's see if all are finished now. */
906 q
->auxiliary_result
= r
;
907 resolve_service_all_complete(q
->auxiliary_for
);
910 static int resolve_service_hostname(DnsQuery
*q
, DnsResourceRecord
*rr
, int ifindex
) {
911 _cleanup_(dns_question_unrefp
) DnsQuestion
*question
= NULL
;
918 assert(rr
->key
->type
== DNS_TYPE_SRV
);
920 /* OK, we found an SRV record for the service. Let's resolve
921 * the hostname included in it */
923 r
= dns_question_new_address(&question
, q
->request_family
, rr
->srv
.name
);
927 r
= dns_query_new(q
->manager
, &aux
, question
, ifindex
, q
->flags
|SD_RESOLVED_NO_SEARCH
);
931 aux
->request_family
= q
->request_family
;
932 aux
->complete
= resolve_service_hostname_complete
;
934 r
= dns_query_make_auxiliary(aux
, q
);
936 /* Too many auxiliary lookups? If so, don't complain,
937 * let's just not add this one, we already have more
946 /* Note that auxiliary queries do not track the original bus
947 * client, only the primary request does that. */
949 r
= dns_query_go(aux
);
960 static void bus_method_resolve_service_complete(DnsQuery
*q
) {
966 if (q
->state
!= DNS_TRANSACTION_SUCCESS
) {
967 r
= reply_query_state(q
);
971 r
= dns_query_process_cname(q
);
973 r
= sd_bus_reply_method_errorf(q
->request
, BUS_ERROR_CNAME_LOOP
, "CNAME loop detected, or CNAME resolving disabled on '%s'", dns_question_first_name(q
->question
));
978 if (r
== DNS_QUERY_RESTARTED
) /* This was a cname, and the query was restarted. */
982 bool has_root_domain
= false;
983 DnsResourceRecord
*rr
;
986 DNS_ANSWER_FOREACH_IFINDEX(rr
, ifindex
, q
->answer
) {
987 r
= dns_question_matches_rr(q
->question
, rr
, NULL
);
993 if (rr
->key
->type
!= DNS_TYPE_SRV
)
996 if (dns_name_is_root(rr
->srv
.name
)) {
997 has_root_domain
= true;
1001 if ((q
->flags
& SD_RESOLVED_NO_ADDRESS
) == 0) {
1002 q
->block_all_complete
++;
1003 r
= resolve_service_hostname(q
, rr
, ifindex
);
1004 q
->block_all_complete
--;
1013 if (has_root_domain
&& found
== 0) {
1014 /* If there's exactly one SRV RR and it uses
1015 * the root domain as host name, then the
1016 * service is explicitly not offered on the
1017 * domain. Report this as a recognizable
1018 * error. See RFC 2782, Section "Usage
1020 r
= sd_bus_reply_method_errorf(q
->request
, BUS_ERROR_NO_SUCH_SERVICE
, "'%s' does not provide the requested service", dns_question_first_name(q
->question
));
1027 r
= sd_bus_reply_method_errorf(q
->request
, BUS_ERROR_NO_SUCH_RR
, "'%s' does not have any RR of the requested type", dns_question_first_name(q
->question
));
1031 /* Maybe we are already finished? check now... */
1032 resolve_service_all_complete(q
);
1037 log_error_errno(r
, "Failed to send service reply: %m");
1038 sd_bus_reply_method_errno(q
->request
, r
, NULL
);
1044 static int bus_method_resolve_service(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1045 _cleanup_(dns_question_unrefp
) DnsQuestion
*question
= NULL
;
1046 const char *name
, *type
, *domain
, *joined
;
1047 _cleanup_free_
char *n
= NULL
;
1048 Manager
*m
= userdata
;
1049 int family
, ifindex
;
1057 assert_cc(sizeof(int) == sizeof(int32_t));
1059 r
= sd_bus_message_read(message
, "isssit", &ifindex
, &name
, &type
, &domain
, &family
, &flags
);
1063 if (!IN_SET(family
, AF_INET
, AF_INET6
, AF_UNSPEC
))
1064 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Unknown address family %i", family
);
1069 if (!dns_service_name_is_valid(name
))
1070 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid service name '%s'", name
);
1075 else if (!dns_srv_type_is_valid(type
))
1076 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid SRV service type '%s'", type
);
1078 r
= dns_name_is_valid(domain
);
1082 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid domain '%s'", domain
);
1085 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Service name cannot be specified without service type.");
1087 r
= check_ifindex_flags(ifindex
, &flags
, SD_RESOLVED_NO_TXT
|SD_RESOLVED_NO_ADDRESS
, error
);
1092 /* If the type is specified, we generate the full domain name to look up ourselves */
1093 r
= dns_service_join(name
, type
, domain
, &n
);
1099 /* If no type is specified, we assume the domain
1100 * contains the full domain name to lookup already */
1103 r
= dns_question_new_service(&question
, joined
, !(flags
& SD_RESOLVED_NO_TXT
));
1107 r
= dns_query_new(m
, &q
, question
, ifindex
, flags
|SD_RESOLVED_NO_SEARCH
);
1111 q
->request
= sd_bus_message_ref(message
);
1112 q
->request_family
= family
;
1113 q
->complete
= bus_method_resolve_service_complete
;
1115 r
= dns_query_bus_track(q
, message
);
1119 r
= dns_query_go(q
);
1130 static int append_dns_server(sd_bus_message
*reply
, DnsServer
*s
) {
1136 r
= sd_bus_message_open_container(reply
, 'r', "iiay");
1140 r
= sd_bus_message_append(reply
, "ii", s
->link
? s
->link
->ifindex
: 0, s
->family
);
1144 r
= sd_bus_message_append_array(reply
, 'y', &s
->address
, FAMILY_ADDRESS_SIZE(s
->family
));
1148 return sd_bus_message_close_container(reply
);
1151 static int bus_property_get_dns_servers(
1154 const char *interface
,
1155 const char *property
,
1156 sd_bus_message
*reply
,
1158 sd_bus_error
*error
) {
1160 Manager
*m
= userdata
;
1170 r
= sd_bus_message_open_container(reply
, 'a', "(iiay)");
1174 LIST_FOREACH(servers
, s
, m
->dns_servers
) {
1175 r
= append_dns_server(reply
, s
);
1182 HASHMAP_FOREACH(l
, m
->links
, i
) {
1183 LIST_FOREACH(servers
, s
, l
->dns_servers
) {
1184 r
= append_dns_server(reply
, s
);
1192 LIST_FOREACH(servers
, s
, m
->fallback_dns_servers
) {
1193 r
= append_dns_server(reply
, s
);
1199 return sd_bus_message_close_container(reply
);
1202 static int bus_property_get_search_domains(
1205 const char *interface
,
1206 const char *property
,
1207 sd_bus_message
*reply
,
1209 sd_bus_error
*error
) {
1211 Manager
*m
= userdata
;
1220 r
= sd_bus_message_open_container(reply
, 'a', "(is)");
1224 LIST_FOREACH(domains
, d
, m
->search_domains
) {
1225 r
= sd_bus_message_append(reply
, "(is)", 0, d
->name
);
1230 HASHMAP_FOREACH(l
, m
->links
, i
) {
1231 LIST_FOREACH(domains
, d
, l
->search_domains
) {
1232 r
= sd_bus_message_append(reply
, "is", l
->ifindex
, d
->name
);
1238 return sd_bus_message_close_container(reply
);
1241 static int bus_property_get_transaction_statistics(
1244 const char *interface
,
1245 const char *property
,
1246 sd_bus_message
*reply
,
1248 sd_bus_error
*error
) {
1250 Manager
*m
= userdata
;
1255 return sd_bus_message_append(reply
, "(tt)",
1256 (uint64_t) hashmap_size(m
->dns_transactions
),
1257 (uint64_t) m
->n_transactions_total
);
1260 static int bus_property_get_cache_statistics(
1263 const char *interface
,
1264 const char *property
,
1265 sd_bus_message
*reply
,
1267 sd_bus_error
*error
) {
1269 uint64_t size
= 0, hit
= 0, miss
= 0;
1270 Manager
*m
= userdata
;
1276 LIST_FOREACH(scopes
, s
, m
->dns_scopes
) {
1277 size
+= dns_cache_size(&s
->cache
);
1278 hit
+= s
->cache
.n_hit
;
1279 miss
+= s
->cache
.n_miss
;
1282 return sd_bus_message_append(reply
, "(ttt)", size
, hit
, miss
);
1285 static int bus_property_get_dnssec_statistics(
1288 const char *interface
,
1289 const char *property
,
1290 sd_bus_message
*reply
,
1292 sd_bus_error
*error
) {
1294 Manager
*m
= userdata
;
1299 return sd_bus_message_append(reply
, "(tttt)",
1300 (uint64_t) m
->n_dnssec_secure
,
1301 (uint64_t) m
->n_dnssec_insecure
,
1302 (uint64_t) m
->n_dnssec_bogus
,
1303 (uint64_t) m
->n_dnssec_indeterminate
);
1306 static int bus_method_reset_statistics(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1307 Manager
*m
= userdata
;
1313 LIST_FOREACH(scopes
, s
, m
->dns_scopes
)
1314 s
->cache
.n_hit
= s
->cache
.n_miss
= 0;
1316 m
->n_transactions_total
= 0;
1317 m
->n_dnssec_secure
= m
->n_dnssec_insecure
= m
->n_dnssec_bogus
= m
->n_dnssec_indeterminate
= 0;
1319 return sd_bus_reply_method_return(message
, NULL
);
1322 static const sd_bus_vtable resolve_vtable
[] = {
1323 SD_BUS_VTABLE_START(0),
1324 SD_BUS_PROPERTY("LLMNRHostname", "s", NULL
, offsetof(Manager
, llmnr_hostname
), 0),
1325 SD_BUS_PROPERTY("DNSServers", "a(iiay)", bus_property_get_dns_servers
, 0, 0),
1326 SD_BUS_PROPERTY("SearchDomains", "a(is)", bus_property_get_search_domains
, 0, 0),
1327 SD_BUS_PROPERTY("TransactionStatistics", "(tt)", bus_property_get_transaction_statistics
, 0, 0),
1328 SD_BUS_PROPERTY("CacheStatistics", "(ttt)", bus_property_get_cache_statistics
, 0, 0),
1329 SD_BUS_PROPERTY("DNSSECStatistics", "(tttt)", bus_property_get_dnssec_statistics
, 0, 0),
1331 SD_BUS_METHOD("ResolveHostname", "isit", "a(iiay)st", bus_method_resolve_hostname
, SD_BUS_VTABLE_UNPRIVILEGED
),
1332 SD_BUS_METHOD("ResolveAddress", "iiayt", "a(is)t", bus_method_resolve_address
, SD_BUS_VTABLE_UNPRIVILEGED
),
1333 SD_BUS_METHOD("ResolveRecord", "isqqt", "a(iqqay)t", bus_method_resolve_record
, SD_BUS_VTABLE_UNPRIVILEGED
),
1334 SD_BUS_METHOD("ResolveService", "isssit", "a(qqqsa(iiay)s)aayssst", bus_method_resolve_service
, SD_BUS_VTABLE_UNPRIVILEGED
),
1335 SD_BUS_METHOD("ResetStatistics", NULL
, NULL
, bus_method_reset_statistics
, 0),
1339 static int on_bus_retry(sd_event_source
*s
, usec_t usec
, void *userdata
) {
1340 Manager
*m
= userdata
;
1345 m
->bus_retry_event_source
= sd_event_source_unref(m
->bus_retry_event_source
);
1347 manager_connect_bus(m
);
1351 static int match_prepare_for_sleep(sd_bus_message
*message
, void *userdata
, sd_bus_error
*ret_error
) {
1352 Manager
*m
= userdata
;
1358 r
= sd_bus_message_read(message
, "b", &b
);
1360 log_debug_errno(r
, "Failed to parse PrepareForSleep signal: %m");
1367 log_debug("Coming back from suspend, verifying all RRs...");
1369 manager_verify_all(m
);
1373 int manager_connect_bus(Manager
*m
) {
1381 r
= sd_bus_default_system(&m
->bus
);
1383 /* We failed to connect? Yuck, we must be in early
1384 * boot. Let's try in 5s again. As soon as we have
1385 * kdbus we can stop doing this... */
1387 log_debug_errno(r
, "Failed to connect to bus, trying again in 5s: %m");
1389 r
= sd_event_add_time(m
->event
, &m
->bus_retry_event_source
, CLOCK_MONOTONIC
, now(CLOCK_MONOTONIC
) + 5*USEC_PER_SEC
, 0, on_bus_retry
, m
);
1391 return log_error_errno(r
, "Failed to install bus reconnect time event: %m");
1393 (void) sd_event_source_set_description(m
->bus_retry_event_source
, "bus-retry");
1397 r
= sd_bus_add_object_vtable(m
->bus
, NULL
, "/org/freedesktop/resolve1", "org.freedesktop.resolve1.Manager", resolve_vtable
, m
);
1399 return log_error_errno(r
, "Failed to register object: %m");
1401 r
= sd_bus_request_name(m
->bus
, "org.freedesktop.resolve1", 0);
1403 return log_error_errno(r
, "Failed to register name: %m");
1405 r
= sd_bus_attach_event(m
->bus
, m
->event
, 0);
1407 return log_error_errno(r
, "Failed to attach bus to event loop: %m");
1409 r
= sd_bus_add_match(m
->bus
, &m
->prepare_for_sleep_slot
,
1411 "sender='org.freedesktop.login1',"
1412 "interface='org.freedesktop.login1.Manager',"
1413 "member='PrepareForSleep',"
1414 "path='/org/freedesktop/login1'",
1415 match_prepare_for_sleep
,
1418 log_error_errno(r
, "Failed to add match for PrepareForSleep: %m");