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-errors.h"
25 #include "resolved-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 = strappenda(_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 /* If we didn't find anything, then let's restart the
224 * query, this time with the cname */
228 r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_NO_NAME_SERVERS, "No appropriate name servers or networks for name found");
232 r = sd_bus_reply_method_errno(q->request, -r, NULL);
240 r = sd_bus_message_close_container(reply);
244 /* Return the precise spelling and uppercasing reported by the server */
246 r = sd_bus_message_append(reply, "st", DNS_RESOURCE_KEY_NAME(canonical->key), SD_RESOLVED_FLAGS_MAKE(q->answer_protocol, q->answer_family));
250 r = sd_bus_send(q->manager->bus, reply, NULL);
254 log_error("Failed to send hostname reply: %s", strerror(-r));
255 sd_bus_reply_method_errno(q->request, -r, NULL);
261 static int check_ifindex_flags(int ifindex, uint64_t *flags, sd_bus_error *error) {
265 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid interface index");
267 if (*flags & ~SD_RESOLVED_FLAGS_ALL)
268 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid flags parameter");
271 *flags = SD_RESOLVED_FLAGS_DEFAULT;
276 static int bus_method_resolve_hostname(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
277 _cleanup_(dns_question_unrefp) DnsQuestion *question = NULL;
278 Manager *m = userdata;
279 const char *hostname;
289 r = sd_bus_message_read(message, "isit", &ifindex, &hostname, &family, &flags);
293 if (!IN_SET(family, AF_INET, AF_INET6, AF_UNSPEC))
294 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown address family %i", family);
296 r = dns_name_normalize(hostname, NULL);
298 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid hostname '%s'", hostname);
300 r = check_ifindex_flags(ifindex, &flags, error);
304 question = dns_question_new(family == AF_UNSPEC ? 2 : 1);
308 if (family != AF_INET6) {
309 _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
311 key = dns_resource_key_new(DNS_CLASS_IN, DNS_TYPE_A, hostname);
315 r = dns_question_add(question, key);
320 if (family != AF_INET) {
321 _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
323 key = dns_resource_key_new(DNS_CLASS_IN, DNS_TYPE_AAAA, hostname);
327 r = dns_question_add(question, key);
332 r = dns_query_new(m, &q, question, ifindex, flags);
336 q->request = sd_bus_message_ref(message);
337 q->request_family = family;
338 q->request_hostname = hostname;
339 q->complete = bus_method_resolve_hostname_complete;
341 r = dns_query_bus_track(q, bus, message);
350 sd_bus_error_setf(error, BUS_ERROR_NO_NAME_SERVERS, "No appropriate name servers or networks for name found");
358 static void bus_method_resolve_address_complete(DnsQuery *q) {
359 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
360 _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL;
361 unsigned added = 0, i;
366 if (q->state != DNS_TRANSACTION_SUCCESS) {
367 r = reply_query_state(q);
371 r = sd_bus_message_new_method_return(q->request, &reply);
375 r = sd_bus_message_append(reply, "i", q->answer_ifindex);
379 r = sd_bus_message_open_container(reply, 'a', "s");
384 answer = dns_answer_ref(q->answer);
386 for (i = 0; i < answer->n_rrs; i++) {
387 r = dns_question_matches_rr(q->question, answer->rrs[i]);
393 r = sd_bus_message_append(reply, "s", answer->rrs[i]->ptr.name);
402 _cleanup_free_ char *ip = NULL;
404 in_addr_to_string(q->request_family, &q->request_address, &ip);
406 r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_NO_SUCH_RR, "Address '%s' does not have any RR of requested type", ip);
410 r = sd_bus_message_close_container(reply);
414 r = sd_bus_message_append(reply, "t", SD_RESOLVED_FLAGS_MAKE(q->answer_protocol, q->answer_family));
418 r = sd_bus_send(q->manager->bus, reply, NULL);
422 log_error("Failed to send address reply: %s", strerror(-r));
423 sd_bus_reply_method_errno(q->request, -r, NULL);
429 static int bus_method_resolve_address(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
430 _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
431 _cleanup_(dns_question_unrefp) DnsQuestion *question = NULL;
432 _cleanup_free_ char *reverse = NULL;
433 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, bus, 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("Failed to send record reply: %s", strerror(-r));
595 sd_bus_reply_method_errno(q->request, -r, NULL);
601 static int bus_method_resolve_record(sd_bus *bus, 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;
615 r = sd_bus_message_read(message, "isqqt", &ifindex, &name, &class, &type, &flags);
619 r = dns_name_normalize(name, NULL);
621 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid name '%s'", name);
623 r = check_ifindex_flags(ifindex, &flags, error);
627 question = dns_question_new(1);
631 key = dns_resource_key_new(class, type, name);
635 r = dns_question_add(question, key);
639 r = dns_query_new(m, &q, question, ifindex, flags);
643 q->request = sd_bus_message_ref(message);
644 q->request_hostname = name;
645 q->complete = bus_method_resolve_record_complete;
647 r = dns_query_bus_track(q, bus, message);
656 sd_bus_error_setf(error, BUS_ERROR_NO_NAME_SERVERS, "No appropriate name servers or networks for name found");
664 static const sd_bus_vtable resolve_vtable[] = {
665 SD_BUS_VTABLE_START(0),
666 SD_BUS_METHOD("ResolveHostname", "isit", "ia(iay)st", bus_method_resolve_hostname, SD_BUS_VTABLE_UNPRIVILEGED),
667 SD_BUS_METHOD("ResolveAddress", "iiayt", "iast", bus_method_resolve_address, SD_BUS_VTABLE_UNPRIVILEGED),
668 SD_BUS_METHOD("ResolveRecord", "isqqt", "ia(qqay)t", bus_method_resolve_record, SD_BUS_VTABLE_UNPRIVILEGED),
672 static int on_bus_retry(sd_event_source *s, usec_t usec, void *userdata) {
673 Manager *m = userdata;
678 m->bus_retry_event_source = sd_event_source_unref(m->bus_retry_event_source);
680 manager_connect_bus(m);
684 static int match_prepare_for_sleep(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *ret_error) {
685 Manager *m = userdata;
691 r = sd_bus_message_read(message, "b", &b);
693 log_debug("Failed to parse PrepareForSleep signal: %s", strerror(-r));
700 log_debug("Coming back from suspend, verifying all RRs...");
702 manager_verify_all(m);
706 int manager_connect_bus(Manager *m) {
714 r = sd_bus_default_system(&m->bus);
716 /* We failed to connect? Yuck, we must be in early
717 * boot. Let's try in 5s again. As soon as we have
718 * kdbus we can stop doing this... */
720 log_debug("Failed to connect to bus, trying again in 5s: %s", strerror(-r));
722 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);
724 log_error("Failed to install bus reconnect time event: %s", strerror(-r));
731 r = sd_bus_add_object_vtable(m->bus, NULL, "/org/freedesktop/resolve1", "org.freedesktop.resolve1.Manager", resolve_vtable, m);
733 log_error("Failed to register object: %s", strerror(-r));
737 r = sd_bus_request_name(m->bus, "org.freedesktop.resolve1", 0);
739 log_error("Failed to register name: %s", strerror(-r));
743 r = sd_bus_attach_event(m->bus, m->event, 0);
745 log_error("Failed to attach bus to event loop: %s", strerror(-r));
749 r = sd_bus_add_match(m->bus, &m->prepare_for_sleep_slot,
751 "sender='org.freedesktop.login1',"
752 "interface='org.freedesktop.login1.Manager',"
753 "member='PrepareForSleep',"
754 "path='/org/freedesktop/login1'",
755 match_prepare_for_sleep,
758 log_error("Failed to add match for PrepareForSleep: %s", strerror(-r));