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
) {
100 r
= sd_bus_message_open_container(reply
, 'r', "iay");
104 if (rr
->key
->type
== DNS_TYPE_A
) {
105 r
= sd_bus_message_append(reply
, "i", AF_INET
);
109 r
= sd_bus_message_append_array(reply
, 'y', &rr
->a
.in_addr
, sizeof(struct in_addr
));
111 } else if (rr
->key
->type
== DNS_TYPE_AAAA
) {
112 r
= sd_bus_message_append(reply
, "i", AF_INET6
);
116 r
= sd_bus_message_append_array(reply
, 'y', &rr
->aaaa
.in6_addr
, sizeof(struct in6_addr
));
118 return -EAFNOSUPPORT
;
123 r
= sd_bus_message_close_container(reply
);
130 static void bus_method_resolve_hostname_complete(DnsQuery
*q
) {
131 _cleanup_(dns_resource_record_unrefp
) DnsResourceRecord
*cname
= NULL
, *canonical
= NULL
;
132 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
133 _cleanup_(dns_answer_unrefp
) DnsAnswer
*answer
= NULL
;
134 unsigned added
= 0, i
;
139 if (q
->state
!= DNS_TRANSACTION_SUCCESS
) {
140 r
= reply_query_state(q
);
144 r
= sd_bus_message_new_method_return(q
->request
, &reply
);
148 r
= sd_bus_message_append(reply
, "i", q
->answer_ifindex
);
152 r
= sd_bus_message_open_container(reply
, 'a', "(iay)");
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
->rrs
[i
]);
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
->rrs
[i
]);
170 cname
= dns_resource_record_ref(answer
->rrs
[i
]);
175 r
= append_address(reply
, answer
->rrs
[i
]);
180 canonical
= dns_resource_record_ref(answer
->rrs
[i
]);
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
->rrs
[i
]);
213 r
= append_address(reply
, answer
->rrs
[i
]);
218 canonical
= dns_resource_record_ref(answer
->rrs
[i
]);
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_errorf(q
->request
, BUS_ERROR_NO_NAME_SERVERS
, "No appropriate name servers or networks for name found");
234 r
= sd_bus_reply_method_errno(q
->request
, -r
, NULL
);
242 r
= sd_bus_message_close_container(reply
);
246 /* Return the precise spelling and uppercasing reported by the server */
248 r
= sd_bus_message_append(reply
, "st", DNS_RESOURCE_KEY_NAME(canonical
->key
), SD_RESOLVED_FLAGS_MAKE(q
->answer_protocol
, q
->answer_family
));
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
->request
, -r
, NULL
);
263 static int check_ifindex_flags(int ifindex
, uint64_t *flags
, sd_bus_error
*error
) {
267 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid interface index");
269 if (*flags
& ~SD_RESOLVED_FLAGS_ALL
)
270 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid flags parameter");
273 *flags
= SD_RESOLVED_FLAGS_DEFAULT
;
278 static int bus_method_resolve_hostname(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
279 _cleanup_(dns_question_unrefp
) DnsQuestion
*question
= NULL
;
280 Manager
*m
= userdata
;
281 const char *hostname
;
290 r
= sd_bus_message_read(message
, "isit", &ifindex
, &hostname
, &family
, &flags
);
294 if (!IN_SET(family
, AF_INET
, AF_INET6
, AF_UNSPEC
))
295 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Unknown address family %i", family
);
297 r
= dns_name_normalize(hostname
, NULL
);
299 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid hostname '%s'", hostname
);
301 r
= check_ifindex_flags(ifindex
, &flags
, error
);
305 question
= dns_question_new(family
== AF_UNSPEC
? 2 : 1);
309 if (family
!= AF_INET6
) {
310 _cleanup_(dns_resource_key_unrefp
) DnsResourceKey
*key
= NULL
;
312 key
= dns_resource_key_new(DNS_CLASS_IN
, DNS_TYPE_A
, hostname
);
316 r
= dns_question_add(question
, key
);
321 if (family
!= AF_INET
) {
322 _cleanup_(dns_resource_key_unrefp
) DnsResourceKey
*key
= NULL
;
324 key
= dns_resource_key_new(DNS_CLASS_IN
, DNS_TYPE_AAAA
, hostname
);
328 r
= dns_question_add(question
, key
);
333 r
= dns_query_new(m
, &q
, question
, ifindex
, flags
);
337 q
->request
= sd_bus_message_ref(message
);
338 q
->request_family
= family
;
339 q
->request_hostname
= hostname
;
340 q
->complete
= bus_method_resolve_hostname_complete
;
342 r
= dns_query_bus_track(q
, message
);
351 sd_bus_error_setf(error
, BUS_ERROR_NO_NAME_SERVERS
, "No appropriate name servers or networks for name found");
359 static void bus_method_resolve_address_complete(DnsQuery
*q
) {
360 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
361 _cleanup_(dns_answer_unrefp
) DnsAnswer
*answer
= NULL
;
362 unsigned added
= 0, i
;
367 if (q
->state
!= DNS_TRANSACTION_SUCCESS
) {
368 r
= reply_query_state(q
);
372 r
= sd_bus_message_new_method_return(q
->request
, &reply
);
376 r
= sd_bus_message_append(reply
, "i", q
->answer_ifindex
);
380 r
= sd_bus_message_open_container(reply
, 'a', "s");
385 answer
= dns_answer_ref(q
->answer
);
387 for (i
= 0; i
< answer
->n_rrs
; i
++) {
388 r
= dns_question_matches_rr(q
->question
, answer
->rrs
[i
]);
394 r
= sd_bus_message_append(reply
, "s", answer
->rrs
[i
]->ptr
.name
);
403 _cleanup_free_
char *ip
= NULL
;
405 in_addr_to_string(q
->request_family
, &q
->request_address
, &ip
);
407 r
= sd_bus_reply_method_errorf(q
->request
, BUS_ERROR_NO_SUCH_RR
, "Address '%s' does not have any RR of requested type", ip
);
411 r
= sd_bus_message_close_container(reply
);
415 r
= sd_bus_message_append(reply
, "t", SD_RESOLVED_FLAGS_MAKE(q
->answer_protocol
, q
->answer_family
));
419 r
= sd_bus_send(q
->manager
->bus
, reply
, NULL
);
423 log_error_errno(r
, "Failed to send address reply: %m");
424 sd_bus_reply_method_errno(q
->request
, -r
, NULL
);
430 static int bus_method_resolve_address(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
431 _cleanup_(dns_resource_key_unrefp
) DnsResourceKey
*key
= NULL
;
432 _cleanup_(dns_question_unrefp
) DnsQuestion
*question
= NULL
;
433 _cleanup_free_
char *reverse
= NULL
;
434 Manager
*m
= userdata
;
445 r
= sd_bus_message_read(message
, "ii", &ifindex
, &family
);
449 if (!IN_SET(family
, AF_INET
, AF_INET6
))
450 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Unknown address family %i", family
);
452 r
= sd_bus_message_read_array(message
, 'y', &d
, &sz
);
456 if (sz
!= FAMILY_ADDRESS_SIZE(family
))
457 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid address size");
459 r
= sd_bus_message_read(message
, "t", &flags
);
463 r
= check_ifindex_flags(ifindex
, &flags
, error
);
467 r
= dns_name_reverse(family
, d
, &reverse
);
471 question
= dns_question_new(1);
475 key
= dns_resource_key_new_consume(DNS_CLASS_IN
, DNS_TYPE_PTR
, reverse
);
481 r
= dns_question_add(question
, key
);
485 r
= dns_query_new(m
, &q
, question
, ifindex
, flags
);
489 q
->request
= sd_bus_message_ref(message
);
490 q
->request_family
= family
;
491 memcpy(&q
->request_address
, d
, sz
);
492 q
->complete
= bus_method_resolve_address_complete
;
494 r
= dns_query_bus_track(q
, message
);
503 sd_bus_error_setf(error
, BUS_ERROR_NO_NAME_SERVERS
, "No appropriate name servers or networks for name found");
511 static void bus_method_resolve_record_complete(DnsQuery
*q
) {
512 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
513 _cleanup_(dns_answer_unrefp
) DnsAnswer
*answer
= NULL
;
514 unsigned added
= 0, i
;
519 if (q
->state
!= DNS_TRANSACTION_SUCCESS
) {
520 r
= reply_query_state(q
);
524 r
= sd_bus_message_new_method_return(q
->request
, &reply
);
528 r
= sd_bus_message_append(reply
, "i", q
->answer_ifindex
);
532 r
= sd_bus_message_open_container(reply
, 'a', "(qqay)");
537 answer
= dns_answer_ref(q
->answer
);
539 for (i
= 0; i
< answer
->n_rrs
; i
++) {
540 _cleanup_(dns_packet_unrefp
) DnsPacket
*p
= NULL
;
543 r
= dns_question_matches_rr(q
->question
, answer
->rrs
[i
]);
549 r
= dns_packet_new(&p
, DNS_PROTOCOL_DNS
, 0);
553 r
= dns_packet_append_rr(p
, answer
->rrs
[i
], &start
);
557 r
= sd_bus_message_open_container(reply
, 'r', "qqay");
561 r
= sd_bus_message_append(reply
, "qq", answer
->rrs
[i
]->key
->class, answer
->rrs
[i
]->key
->type
);
565 r
= sd_bus_message_append_array(reply
, 'y', DNS_PACKET_DATA(p
) + start
, p
->size
- start
);
569 r
= sd_bus_message_close_container(reply
);
578 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
);
582 r
= sd_bus_message_close_container(reply
);
586 r
= sd_bus_message_append(reply
, "t", SD_RESOLVED_FLAGS_MAKE(q
->answer_protocol
, q
->answer_family
));
590 r
= sd_bus_send(q
->manager
->bus
, reply
, NULL
);
594 log_error_errno(r
, "Failed to send record reply: %m");
595 sd_bus_reply_method_errno(q
->request
, -r
, NULL
);
601 static int bus_method_resolve_record(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
602 _cleanup_(dns_resource_key_unrefp
) DnsResourceKey
*key
= NULL
;
603 _cleanup_(dns_question_unrefp
) DnsQuestion
*question
= NULL
;
604 Manager
*m
= userdata
;
605 uint16_t class, type
;
614 r
= sd_bus_message_read(message
, "isqqt", &ifindex
, &name
, &class, &type
, &flags
);
618 r
= dns_name_normalize(name
, NULL
);
620 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid name '%s'", name
);
622 r
= check_ifindex_flags(ifindex
, &flags
, error
);
626 question
= dns_question_new(1);
630 key
= dns_resource_key_new(class, type
, name
);
634 r
= dns_question_add(question
, key
);
638 r
= dns_query_new(m
, &q
, question
, ifindex
, flags
);
642 q
->request
= sd_bus_message_ref(message
);
643 q
->request_hostname
= name
;
644 q
->complete
= bus_method_resolve_record_complete
;
646 r
= dns_query_bus_track(q
, message
);
655 sd_bus_error_setf(error
, BUS_ERROR_NO_NAME_SERVERS
, "No appropriate name servers or networks for name found");
663 static const sd_bus_vtable resolve_vtable
[] = {
664 SD_BUS_VTABLE_START(0),
665 SD_BUS_METHOD("ResolveHostname", "isit", "ia(iay)st", bus_method_resolve_hostname
, SD_BUS_VTABLE_UNPRIVILEGED
),
666 SD_BUS_METHOD("ResolveAddress", "iiayt", "iast", bus_method_resolve_address
, SD_BUS_VTABLE_UNPRIVILEGED
),
667 SD_BUS_METHOD("ResolveRecord", "isqqt", "ia(qqay)t", bus_method_resolve_record
, SD_BUS_VTABLE_UNPRIVILEGED
),
671 static int on_bus_retry(sd_event_source
*s
, usec_t usec
, void *userdata
) {
672 Manager
*m
= userdata
;
677 m
->bus_retry_event_source
= sd_event_source_unref(m
->bus_retry_event_source
);
679 manager_connect_bus(m
);
683 static int match_prepare_for_sleep(sd_bus_message
*message
, void *userdata
, sd_bus_error
*ret_error
) {
684 Manager
*m
= userdata
;
690 r
= sd_bus_message_read(message
, "b", &b
);
692 log_debug_errno(r
, "Failed to parse PrepareForSleep signal: %m");
699 log_debug("Coming back from suspend, verifying all RRs...");
701 manager_verify_all(m
);
705 int manager_connect_bus(Manager
*m
) {
713 r
= sd_bus_default_system(&m
->bus
);
715 /* We failed to connect? Yuck, we must be in early
716 * boot. Let's try in 5s again. As soon as we have
717 * kdbus we can stop doing this... */
719 log_debug_errno(r
, "Failed to connect to bus, trying again in 5s: %m");
721 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
);
723 return log_error_errno(r
, "Failed to install bus reconnect time event: %m");
728 r
= sd_bus_add_object_vtable(m
->bus
, NULL
, "/org/freedesktop/resolve1", "org.freedesktop.resolve1.Manager", resolve_vtable
, m
);
730 return log_error_errno(r
, "Failed to register object: %m");
732 r
= sd_bus_request_name(m
->bus
, "org.freedesktop.resolve1", 0);
734 return log_error_errno(r
, "Failed to register name: %m");
736 r
= sd_bus_attach_event(m
->bus
, m
->event
, 0);
738 return log_error_errno(r
, "Failed to attach bus to event loop: %m");
740 r
= sd_bus_add_match(m
->bus
, &m
->prepare_for_sleep_slot
,
742 "sender='org.freedesktop.login1',"
743 "interface='org.freedesktop.login1.Manager',"
744 "member='PrepareForSleep',"
745 "path='/org/freedesktop/login1'",
746 match_prepare_for_sleep
,
749 log_error_errno(r
, "Failed to add match for PrepareForSleep: %m");