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 "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_hostname
)
35 name
= q
->request_hostname
;
37 r
= in_addr_to_string(q
->request_family
, &q
->request_address
, &ip
);
46 case DNS_TRANSACTION_NO_SERVERS
:
47 return sd_bus_reply_method_errorf(q
->request
, BUS_ERROR_NO_NAME_SERVERS
, "No appropriate name servers or networks for name found");
49 case DNS_TRANSACTION_TIMEOUT
:
50 return sd_bus_reply_method_errorf(q
->request
, SD_BUS_ERROR_TIMEOUT
, "Query timed out");
52 case DNS_TRANSACTION_ATTEMPTS_MAX_REACHED
:
53 return sd_bus_reply_method_errorf(q
->request
, SD_BUS_ERROR_TIMEOUT
, "All attempts to contact name servers or networks failed");
55 case DNS_TRANSACTION_INVALID_REPLY
:
56 return sd_bus_reply_method_errorf(q
->request
, BUS_ERROR_INVALID_REPLY
, "Received invalid reply");
58 case DNS_TRANSACTION_RESOURCES
:
59 return sd_bus_reply_method_errorf(q
->request
, BUS_ERROR_NO_RESOURCES
, "Not enough resources");
61 case DNS_TRANSACTION_ABORTED
:
62 return sd_bus_reply_method_errorf(q
->request
, BUS_ERROR_ABORTED
, "Query aborted");
64 case DNS_TRANSACTION_FAILURE
: {
65 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
67 if (q
->answer_rcode
== DNS_RCODE_NXDOMAIN
)
68 sd_bus_error_setf(&error
, _BUS_ERROR_DNS
"NXDOMAIN", "'%s' not found", name
);
71 char p
[3]; /* the rcode is 4 bits long */
73 rc
= dns_rcode_to_string(q
->answer_rcode
);
75 sprintf(p
, "%i", q
->answer_rcode
);
79 n
= strjoina(_BUS_ERROR_DNS
, rc
);
80 sd_bus_error_setf(&error
, n
, "Could not resolve '%s', server or network returned error %s", name
, rc
);
83 return sd_bus_reply_method_error(q
->request
, &error
);
86 case DNS_TRANSACTION_NULL
:
87 case DNS_TRANSACTION_PENDING
:
88 case DNS_TRANSACTION_SUCCESS
:
90 assert_not_reached("Impossible state");
94 static int append_address(sd_bus_message
*reply
, DnsResourceRecord
*rr
, int ifindex
) {
100 r
= sd_bus_message_open_container(reply
, 'r', "iiay");
104 r
= sd_bus_message_append(reply
, "i", ifindex
);
108 if (rr
->key
->type
== DNS_TYPE_A
) {
109 r
= sd_bus_message_append(reply
, "i", AF_INET
);
113 r
= sd_bus_message_append_array(reply
, 'y', &rr
->a
.in_addr
, sizeof(struct in_addr
));
115 } else if (rr
->key
->type
== DNS_TYPE_AAAA
) {
116 r
= sd_bus_message_append(reply
, "i", AF_INET6
);
120 r
= sd_bus_message_append_array(reply
, 'y', &rr
->aaaa
.in6_addr
, sizeof(struct in6_addr
));
122 return -EAFNOSUPPORT
;
127 r
= sd_bus_message_close_container(reply
);
134 static void bus_method_resolve_hostname_complete(DnsQuery
*q
) {
135 _cleanup_(dns_resource_record_unrefp
) DnsResourceRecord
*cname
= NULL
, *canonical
= NULL
;
136 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
137 _cleanup_(dns_answer_unrefp
) DnsAnswer
*answer
= NULL
;
138 unsigned added
= 0, i
;
143 if (q
->state
!= DNS_TRANSACTION_SUCCESS
) {
144 r
= reply_query_state(q
);
148 r
= sd_bus_message_new_method_return(q
->request
, &reply
);
152 r
= sd_bus_message_open_container(reply
, 'a', "(iiay)");
157 answer
= dns_answer_ref(q
->answer
);
159 for (i
= 0; i
< answer
->n_rrs
; i
++) {
160 r
= dns_question_matches_rr(q
->question
, answer
->items
[i
].rr
);
164 /* Hmm, if this is not an address record,
165 maybe it's a cname? If so, remember this */
166 r
= dns_question_matches_cname(q
->question
, answer
->items
[i
].rr
);
170 cname
= dns_resource_record_ref(answer
->items
[i
].rr
);
175 r
= append_address(reply
, answer
->items
[i
].rr
, answer
->items
[i
].ifindex
);
180 canonical
= dns_resource_record_ref(answer
->items
[i
].rr
);
188 r
= sd_bus_reply_method_errorf(q
->request
, BUS_ERROR_NO_SUCH_RR
, "'%s' does not have any RR of requested type", q
->request_hostname
);
192 /* This has a cname? Then update the query with the
194 r
= dns_query_cname_redirect(q
, cname
->cname
.name
);
197 r
= sd_bus_reply_method_errorf(q
->request
, BUS_ERROR_CNAME_LOOP
, "CNAME loop on '%s'", q
->request_hostname
);
199 r
= sd_bus_reply_method_errno(q
->request
, -r
, NULL
);
204 /* Before we restart the query, let's see if any of
205 * the RRs we already got already answers our query */
206 for (i
= 0; i
< answer
->n_rrs
; i
++) {
207 r
= dns_question_matches_rr(q
->question
, answer
->items
[i
].rr
);
213 r
= append_address(reply
, answer
->items
[i
].rr
, answer
->items
[i
].ifindex
);
218 canonical
= dns_resource_record_ref(answer
->items
[i
].rr
);
223 // what about the cache?
225 /* If we didn't find anything, then let's restart the
226 * query, this time with the cname */
230 r
= sd_bus_reply_method_errno(q
->request
, -r
, NULL
);
238 r
= sd_bus_message_close_container(reply
);
242 /* Return the precise spelling and uppercasing reported by the server */
244 r
= sd_bus_message_append(reply
, "st", DNS_RESOURCE_KEY_NAME(canonical
->key
), SD_RESOLVED_FLAGS_MAKE(q
->answer_protocol
, q
->answer_family
));
248 r
= sd_bus_send(q
->manager
->bus
, reply
, NULL
);
252 log_error_errno(r
, "Failed to send hostname reply: %m");
253 sd_bus_reply_method_errno(q
->request
, -r
, NULL
);
259 static int check_ifindex_flags(int ifindex
, uint64_t *flags
, sd_bus_error
*error
) {
263 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid interface index");
265 if (*flags
& ~SD_RESOLVED_FLAGS_ALL
)
266 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid flags parameter");
269 *flags
= SD_RESOLVED_FLAGS_DEFAULT
;
274 static int bus_method_resolve_hostname(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
275 _cleanup_(dns_question_unrefp
) DnsQuestion
*question
= NULL
;
276 Manager
*m
= userdata
;
277 const char *hostname
;
286 r
= sd_bus_message_read(message
, "isit", &ifindex
, &hostname
, &family
, &flags
);
290 if (!IN_SET(family
, AF_INET
, AF_INET6
, AF_UNSPEC
))
291 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Unknown address family %i", family
);
293 r
= dns_name_normalize(hostname
, NULL
);
295 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid hostname '%s'", hostname
);
297 r
= check_ifindex_flags(ifindex
, &flags
, error
);
301 question
= dns_question_new(family
== AF_UNSPEC
? 2 : 1);
305 if (family
!= AF_INET6
) {
306 _cleanup_(dns_resource_key_unrefp
) DnsResourceKey
*key
= NULL
;
308 key
= dns_resource_key_new(DNS_CLASS_IN
, DNS_TYPE_A
, hostname
);
312 r
= dns_question_add(question
, key
);
317 if (family
!= AF_INET
) {
318 _cleanup_(dns_resource_key_unrefp
) DnsResourceKey
*key
= NULL
;
320 key
= dns_resource_key_new(DNS_CLASS_IN
, DNS_TYPE_AAAA
, hostname
);
324 r
= dns_question_add(question
, key
);
329 r
= dns_query_new(m
, &q
, question
, ifindex
, flags
);
333 q
->request
= sd_bus_message_ref(message
);
334 q
->request_family
= family
;
335 q
->request_hostname
= hostname
;
336 q
->complete
= bus_method_resolve_hostname_complete
;
338 r
= dns_query_bus_track(q
, message
);
351 static void bus_method_resolve_address_complete(DnsQuery
*q
) {
352 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
353 _cleanup_(dns_answer_unrefp
) DnsAnswer
*answer
= NULL
;
354 unsigned added
= 0, i
;
359 if (q
->state
!= DNS_TRANSACTION_SUCCESS
) {
360 r
= reply_query_state(q
);
364 r
= sd_bus_message_new_method_return(q
->request
, &reply
);
368 r
= sd_bus_message_open_container(reply
, 'a', "(is)");
373 answer
= dns_answer_ref(q
->answer
);
375 for (i
= 0; i
< answer
->n_rrs
; i
++) {
376 r
= dns_question_matches_rr(q
->question
, answer
->items
[i
].rr
);
382 r
= sd_bus_message_append(reply
, "(is)", answer
->items
[i
].ifindex
, answer
->items
[i
].rr
->ptr
.name
);
391 _cleanup_free_
char *ip
= NULL
;
393 in_addr_to_string(q
->request_family
, &q
->request_address
, &ip
);
395 r
= sd_bus_reply_method_errorf(q
->request
, BUS_ERROR_NO_SUCH_RR
, "Address '%s' does not have any RR of requested type", ip
);
399 r
= sd_bus_message_close_container(reply
);
403 r
= sd_bus_message_append(reply
, "t", SD_RESOLVED_FLAGS_MAKE(q
->answer_protocol
, q
->answer_family
));
407 r
= sd_bus_send(q
->manager
->bus
, reply
, NULL
);
411 log_error_errno(r
, "Failed to send address reply: %m");
412 sd_bus_reply_method_errno(q
->request
, -r
, NULL
);
418 static int bus_method_resolve_address(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
419 _cleanup_(dns_resource_key_unrefp
) DnsResourceKey
*key
= NULL
;
420 _cleanup_(dns_question_unrefp
) DnsQuestion
*question
= NULL
;
421 _cleanup_free_
char *reverse
= NULL
;
422 Manager
*m
= userdata
;
433 r
= sd_bus_message_read(message
, "ii", &ifindex
, &family
);
437 if (!IN_SET(family
, AF_INET
, AF_INET6
))
438 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Unknown address family %i", family
);
440 r
= sd_bus_message_read_array(message
, 'y', &d
, &sz
);
444 if (sz
!= FAMILY_ADDRESS_SIZE(family
))
445 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid address size");
447 r
= sd_bus_message_read(message
, "t", &flags
);
451 r
= check_ifindex_flags(ifindex
, &flags
, error
);
455 r
= dns_name_reverse(family
, d
, &reverse
);
459 question
= dns_question_new(1);
463 key
= dns_resource_key_new_consume(DNS_CLASS_IN
, DNS_TYPE_PTR
, reverse
);
469 r
= dns_question_add(question
, key
);
473 r
= dns_query_new(m
, &q
, question
, ifindex
, flags
);
477 q
->request
= sd_bus_message_ref(message
);
478 q
->request_family
= family
;
479 memcpy(&q
->request_address
, d
, sz
);
480 q
->complete
= bus_method_resolve_address_complete
;
482 r
= dns_query_bus_track(q
, message
);
495 static void bus_method_resolve_record_complete(DnsQuery
*q
) {
496 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
497 _cleanup_(dns_answer_unrefp
) DnsAnswer
*answer
= NULL
;
498 unsigned added
= 0, i
;
503 if (q
->state
!= DNS_TRANSACTION_SUCCESS
) {
504 r
= reply_query_state(q
);
508 r
= sd_bus_message_new_method_return(q
->request
, &reply
);
512 r
= sd_bus_message_open_container(reply
, 'a', "(iqqay)");
517 answer
= dns_answer_ref(q
->answer
);
519 for (i
= 0; i
< answer
->n_rrs
; i
++) {
520 _cleanup_(dns_packet_unrefp
) DnsPacket
*p
= NULL
;
523 r
= dns_question_matches_rr(q
->question
, answer
->items
[i
].rr
);
529 r
= dns_packet_new(&p
, DNS_PROTOCOL_DNS
, 0);
533 p
->refuse_compression
= true;
535 r
= dns_packet_append_rr(p
, answer
->items
[i
].rr
, &start
);
539 r
= sd_bus_message_open_container(reply
, 'r', "iqqay");
543 r
= sd_bus_message_append(reply
, "iqq",
544 answer
->items
[i
].ifindex
,
545 answer
->items
[i
].rr
->key
->class,
546 answer
->items
[i
].rr
->key
->type
);
550 r
= sd_bus_message_append_array(reply
, 'y', DNS_PACKET_DATA(p
) + start
, p
->size
- start
);
554 r
= sd_bus_message_close_container(reply
);
563 r
= sd_bus_reply_method_errorf(q
->request
, BUS_ERROR_NO_SUCH_RR
, "Name '%s' does not have any RR of the requested type", q
->request_hostname
);
567 r
= sd_bus_message_close_container(reply
);
571 r
= sd_bus_message_append(reply
, "t", SD_RESOLVED_FLAGS_MAKE(q
->answer_protocol
, q
->answer_family
));
575 r
= sd_bus_send(q
->manager
->bus
, reply
, NULL
);
579 log_error_errno(r
, "Failed to send record reply: %m");
580 sd_bus_reply_method_errno(q
->request
, -r
, NULL
);
586 static int bus_method_resolve_record(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
587 _cleanup_(dns_resource_key_unrefp
) DnsResourceKey
*key
= NULL
;
588 _cleanup_(dns_question_unrefp
) DnsQuestion
*question
= NULL
;
589 Manager
*m
= userdata
;
590 uint16_t class, type
;
599 r
= sd_bus_message_read(message
, "isqqt", &ifindex
, &name
, &class, &type
, &flags
);
603 r
= dns_name_normalize(name
, NULL
);
605 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid name '%s'", name
);
607 r
= check_ifindex_flags(ifindex
, &flags
, error
);
611 question
= dns_question_new(1);
615 key
= dns_resource_key_new(class, type
, name
);
619 r
= dns_question_add(question
, key
);
623 r
= dns_query_new(m
, &q
, question
, ifindex
, flags
);
627 q
->request
= sd_bus_message_ref(message
);
628 q
->request_hostname
= name
;
629 q
->complete
= bus_method_resolve_record_complete
;
631 r
= dns_query_bus_track(q
, message
);
644 static const sd_bus_vtable resolve_vtable
[] = {
645 SD_BUS_VTABLE_START(0),
646 SD_BUS_METHOD("ResolveHostname", "isit", "a(iiay)st", bus_method_resolve_hostname
, SD_BUS_VTABLE_UNPRIVILEGED
),
647 SD_BUS_METHOD("ResolveAddress", "iiayt", "a(is)t", bus_method_resolve_address
, SD_BUS_VTABLE_UNPRIVILEGED
),
648 SD_BUS_METHOD("ResolveRecord", "isqqt", "a(iqqay)t", bus_method_resolve_record
, SD_BUS_VTABLE_UNPRIVILEGED
),
652 static int on_bus_retry(sd_event_source
*s
, usec_t usec
, void *userdata
) {
653 Manager
*m
= userdata
;
658 m
->bus_retry_event_source
= sd_event_source_unref(m
->bus_retry_event_source
);
660 manager_connect_bus(m
);
664 static int match_prepare_for_sleep(sd_bus_message
*message
, void *userdata
, sd_bus_error
*ret_error
) {
665 Manager
*m
= userdata
;
671 r
= sd_bus_message_read(message
, "b", &b
);
673 log_debug_errno(r
, "Failed to parse PrepareForSleep signal: %m");
680 log_debug("Coming back from suspend, verifying all RRs...");
682 manager_verify_all(m
);
686 int manager_connect_bus(Manager
*m
) {
694 r
= sd_bus_default_system(&m
->bus
);
696 /* We failed to connect? Yuck, we must be in early
697 * boot. Let's try in 5s again. As soon as we have
698 * kdbus we can stop doing this... */
700 log_debug_errno(r
, "Failed to connect to bus, trying again in 5s: %m");
702 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
);
704 return log_error_errno(r
, "Failed to install bus reconnect time event: %m");
709 r
= sd_bus_add_object_vtable(m
->bus
, NULL
, "/org/freedesktop/resolve1", "org.freedesktop.resolve1.Manager", resolve_vtable
, m
);
711 return log_error_errno(r
, "Failed to register object: %m");
713 r
= sd_bus_request_name(m
->bus
, "org.freedesktop.resolve1", 0);
715 return log_error_errno(r
, "Failed to register name: %m");
717 r
= sd_bus_attach_event(m
->bus
, m
->event
, 0);
719 return log_error_errno(r
, "Failed to attach bus to event loop: %m");
721 r
= sd_bus_add_match(m
->bus
, &m
->prepare_for_sleep_slot
,
723 "sender='org.freedesktop.login1',"
724 "interface='org.freedesktop.login1.Manager',"
725 "member='PrepareForSleep',"
726 "path='/org/freedesktop/login1'",
727 match_prepare_for_sleep
,
730 log_error_errno(r
, "Failed to add match for PrepareForSleep: %m");