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 "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 = 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 *bus, 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;
291 r = sd_bus_message_read(message, "isit", &ifindex, &hostname, &family, &flags);
295 if (!IN_SET(family, AF_INET, AF_INET6, AF_UNSPEC))
296 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown address family %i", family);
298 r = dns_name_normalize(hostname, NULL);
300 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid hostname '%s'", hostname);
302 r = check_ifindex_flags(ifindex, &flags, error);
306 question = dns_question_new(family == AF_UNSPEC ? 2 : 1);
310 if (family != AF_INET6) {
311 _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
313 key = dns_resource_key_new(DNS_CLASS_IN, DNS_TYPE_A, hostname);
317 r = dns_question_add(question, key);
322 if (family != AF_INET) {
323 _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
325 key = dns_resource_key_new(DNS_CLASS_IN, DNS_TYPE_AAAA, hostname);
329 r = dns_question_add(question, key);
334 r = dns_query_new(m, &q, question, ifindex, flags);
338 q->request = sd_bus_message_ref(message);
339 q->request_family = family;
340 q->request_hostname = hostname;
341 q->complete = bus_method_resolve_hostname_complete;
343 r = dns_query_bus_track(q, bus, message);
352 sd_bus_error_setf(error, BUS_ERROR_NO_NAME_SERVERS, "No appropriate name servers or networks for name found");
360 static void bus_method_resolve_address_complete(DnsQuery *q) {
361 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
362 _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL;
363 unsigned added = 0, i;
368 if (q->state != DNS_TRANSACTION_SUCCESS) {
369 r = reply_query_state(q);
373 r = sd_bus_message_new_method_return(q->request, &reply);
377 r = sd_bus_message_append(reply, "i", q->answer_ifindex);
381 r = sd_bus_message_open_container(reply, 'a', "s");
386 answer = dns_answer_ref(q->answer);
388 for (i = 0; i < answer->n_rrs; i++) {
389 r = dns_question_matches_rr(q->question, answer->rrs[i]);
395 r = sd_bus_message_append(reply, "s", answer->rrs[i]->ptr.name);
404 _cleanup_free_ char *ip = NULL;
406 in_addr_to_string(q->request_family, &q->request_address, &ip);
408 r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_NO_SUCH_RR, "Address '%s' does not have any RR of requested type", ip);
412 r = sd_bus_message_close_container(reply);
416 r = sd_bus_message_append(reply, "t", SD_RESOLVED_FLAGS_MAKE(q->answer_protocol, q->answer_family));
420 r = sd_bus_send(q->manager->bus, reply, NULL);
424 log_error_errno(r, "Failed to send address reply: %m");
425 sd_bus_reply_method_errno(q->request, -r, NULL);
431 static int bus_method_resolve_address(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
432 _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
433 _cleanup_(dns_question_unrefp) DnsQuestion *question = NULL;
434 _cleanup_free_ char *reverse = NULL;
435 Manager *m = userdata;
447 r = sd_bus_message_read(message, "ii", &ifindex, &family);
451 if (!IN_SET(family, AF_INET, AF_INET6))
452 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown address family %i", family);
454 r = sd_bus_message_read_array(message, 'y', &d, &sz);
458 if (sz != FAMILY_ADDRESS_SIZE(family))
459 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid address size");
461 r = sd_bus_message_read(message, "t", &flags);
465 r = check_ifindex_flags(ifindex, &flags, error);
469 r = dns_name_reverse(family, d, &reverse);
473 question = dns_question_new(1);
477 key = dns_resource_key_new_consume(DNS_CLASS_IN, DNS_TYPE_PTR, reverse);
483 r = dns_question_add(question, key);
487 r = dns_query_new(m, &q, question, ifindex, flags);
491 q->request = sd_bus_message_ref(message);
492 q->request_family = family;
493 memcpy(&q->request_address, d, sz);
494 q->complete = bus_method_resolve_address_complete;
496 r = dns_query_bus_track(q, bus, message);
505 sd_bus_error_setf(error, BUS_ERROR_NO_NAME_SERVERS, "No appropriate name servers or networks for name found");
513 static void bus_method_resolve_record_complete(DnsQuery *q) {
514 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
515 _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL;
516 unsigned added = 0, i;
521 if (q->state != DNS_TRANSACTION_SUCCESS) {
522 r = reply_query_state(q);
526 r = sd_bus_message_new_method_return(q->request, &reply);
530 r = sd_bus_message_append(reply, "i", q->answer_ifindex);
534 r = sd_bus_message_open_container(reply, 'a', "(qqay)");
539 answer = dns_answer_ref(q->answer);
541 for (i = 0; i < answer->n_rrs; i++) {
542 _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
545 r = dns_question_matches_rr(q->question, answer->rrs[i]);
551 r = dns_packet_new(&p, DNS_PROTOCOL_DNS, 0);
555 r = dns_packet_append_rr(p, answer->rrs[i], &start);
559 r = sd_bus_message_open_container(reply, 'r', "qqay");
563 r = sd_bus_message_append(reply, "qq", answer->rrs[i]->key->class, answer->rrs[i]->key->type);
567 r = sd_bus_message_append_array(reply, 'y', DNS_PACKET_DATA(p) + start, p->size - start);
571 r = sd_bus_message_close_container(reply);
580 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);
584 r = sd_bus_message_close_container(reply);
588 r = sd_bus_message_append(reply, "t", SD_RESOLVED_FLAGS_MAKE(q->answer_protocol, q->answer_family));
592 r = sd_bus_send(q->manager->bus, reply, NULL);
596 log_error_errno(r, "Failed to send record reply: %m");
597 sd_bus_reply_method_errno(q->request, -r, NULL);
603 static int bus_method_resolve_record(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
604 _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
605 _cleanup_(dns_question_unrefp) DnsQuestion *question = NULL;
606 Manager *m = userdata;
607 uint16_t class, type;
617 r = sd_bus_message_read(message, "isqqt", &ifindex, &name, &class, &type, &flags);
621 r = dns_name_normalize(name, NULL);
623 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid name '%s'", name);
625 r = check_ifindex_flags(ifindex, &flags, error);
629 question = dns_question_new(1);
633 key = dns_resource_key_new(class, type, name);
637 r = dns_question_add(question, key);
641 r = dns_query_new(m, &q, question, ifindex, flags);
645 q->request = sd_bus_message_ref(message);
646 q->request_hostname = name;
647 q->complete = bus_method_resolve_record_complete;
649 r = dns_query_bus_track(q, bus, message);
658 sd_bus_error_setf(error, BUS_ERROR_NO_NAME_SERVERS, "No appropriate name servers or networks for name found");
666 static const sd_bus_vtable resolve_vtable[] = {
667 SD_BUS_VTABLE_START(0),
668 SD_BUS_METHOD("ResolveHostname", "isit", "ia(iay)st", bus_method_resolve_hostname, SD_BUS_VTABLE_UNPRIVILEGED),
669 SD_BUS_METHOD("ResolveAddress", "iiayt", "iast", bus_method_resolve_address, SD_BUS_VTABLE_UNPRIVILEGED),
670 SD_BUS_METHOD("ResolveRecord", "isqqt", "ia(qqay)t", bus_method_resolve_record, SD_BUS_VTABLE_UNPRIVILEGED),
674 static int on_bus_retry(sd_event_source *s, usec_t usec, void *userdata) {
675 Manager *m = userdata;
680 m->bus_retry_event_source = sd_event_source_unref(m->bus_retry_event_source);
682 manager_connect_bus(m);
686 static int match_prepare_for_sleep(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *ret_error) {
687 Manager *m = userdata;
693 r = sd_bus_message_read(message, "b", &b);
695 log_debug_errno(r, "Failed to parse PrepareForSleep signal: %m");
702 log_debug("Coming back from suspend, verifying all RRs...");
704 manager_verify_all(m);
708 int manager_connect_bus(Manager *m) {
716 r = sd_bus_default_system(&m->bus);
718 /* We failed to connect? Yuck, we must be in early
719 * boot. Let's try in 5s again. As soon as we have
720 * kdbus we can stop doing this... */
722 log_debug_errno(r, "Failed to connect to bus, trying again in 5s: %m");
724 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);
726 return log_error_errno(r, "Failed to install bus reconnect time event: %m");
731 r = sd_bus_add_object_vtable(m->bus, NULL, "/org/freedesktop/resolve1", "org.freedesktop.resolve1.Manager", resolve_vtable, m);
733 return log_error_errno(r, "Failed to register object: %m");
735 r = sd_bus_request_name(m->bus, "org.freedesktop.resolve1", 0);
737 return log_error_errno(r, "Failed to register name: %m");
739 r = sd_bus_attach_event(m->bus, m->event, 0);
741 return log_error_errno(r, "Failed to attach bus to event loop: %m");
743 r = sd_bus_add_match(m->bus, &m->prepare_for_sleep_slot,
745 "sender='org.freedesktop.login1',"
746 "interface='org.freedesktop.login1.Manager',"
747 "member='PrepareForSleep',"
748 "path='/org/freedesktop/login1'",
749 match_prepare_for_sleep,
752 log_error_errno(r, "Failed to add match for PrepareForSleep: %m");