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"
26 #include "resolved-dns-domain.h"
28 static void bus_method_resolve_hostname_complete(DnsQuery *q) {
35 case DNS_QUERY_SKIPPED:
36 r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_NO_NAME_SERVERS, "Not appropriate name servers or networks found");
39 case DNS_QUERY_TIMEOUT:
40 r = sd_bus_reply_method_errorf(q->request, SD_BUS_ERROR_TIMEOUT, "Query timed out");
43 case DNS_QUERY_ATTEMPTS_MAX:
44 r = sd_bus_reply_method_errorf(q->request, SD_BUS_ERROR_TIMEOUT, "All attempts to contact name servers or networks failed");
47 case DNS_QUERY_FAILURE: {
48 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
50 if (q->rcode == DNS_RCODE_NXDOMAIN)
51 sd_bus_error_setf(&error, _BUS_ERROR_DNS "NXDOMAIN", "Hostname %s does not exist", q->request_hostname);
54 char p[DECIMAL_STR_MAX(q->rcode)];
56 rc = dns_rcode_to_string(q->rcode);
58 sprintf(p, "%i", q->rcode);
62 n = strappenda(_BUS_ERROR_DNS, rc);
64 sd_bus_error_setf(&error, n, "Could not resolve hostname %s, server or network returned error %s", q->request_hostname, rc);
67 r = sd_bus_reply_method_error(q->request, &error);
71 case DNS_QUERY_SUCCESS: {
72 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
73 unsigned i, n, added = 0;
77 r = dns_packet_skip_question(q->packet);
81 r = sd_bus_message_new_method_return(q->request, &reply);
85 r = sd_bus_message_open_container(reply, 'a', "(yayi)");
89 n = be16toh(DNS_PACKET_HEADER(q->packet)->ancount) +
90 be16toh(DNS_PACKET_HEADER(q->packet)->nscount) +
91 be16toh(DNS_PACKET_HEADER(q->packet)->arcount);
93 for (i = 0; i < n; i++) {
94 _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
96 r = dns_packet_read_rr(q->packet, &rr, NULL);
100 if (rr->key.class != DNS_CLASS_IN)
103 if (!(q->request_family != AF_INET6 && rr->key.type == DNS_TYPE_A) &&
104 !(q->request_family != AF_INET && rr->key.type == DNS_TYPE_AAAA))
107 if (!dns_name_equal(rr->key.name, q->request_hostname))
110 r = sd_bus_message_open_container(reply, 'r', "yayi");
114 if (rr->key.type == DNS_TYPE_A) {
115 r = sd_bus_message_append(reply, "y", AF_INET);
119 r = sd_bus_message_append_array(reply, 'y', &rr->a.in_addr, sizeof(struct in_addr));
121 r = sd_bus_message_append(reply, "y", AF_INET6);
125 r = sd_bus_message_append_array(reply, 'y', &rr->aaaa.in6_addr, sizeof(struct in6_addr));
130 r = sd_bus_message_append(reply, "i", q->packet->ifindex);
134 r = sd_bus_message_close_container(reply);
144 r = sd_bus_message_close_container(reply);
148 r = sd_bus_send(q->manager->bus, reply, NULL);
153 case DNS_QUERY_INVALID_REPLY:
154 r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_INVALID_REPLY, "Received invalid reply");
159 assert_not_reached("Unexpected query state");
164 log_error("Failed to send bus reply: %s", strerror(-r));
169 static int bus_method_resolve_hostname(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
170 Manager *m = userdata;
171 const char *hostname;
173 DnsResourceKey keys[2];
182 r = sd_bus_message_read(message, "sy", &hostname, &family);
186 if (!IN_SET(family, AF_INET, AF_INET6, AF_UNSPEC))
187 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown address family %u", family);
189 if (!hostname_is_valid(hostname))
190 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid hostname '%s'", hostname);
192 if (family != AF_INET6) {
193 keys[n].class = DNS_CLASS_IN;
194 keys[n].type = DNS_TYPE_A;
195 keys[n].name = (char*) hostname;
199 if (family != AF_INET) {
200 keys[n].class = DNS_CLASS_IN;
201 keys[n].type = DNS_TYPE_AAAA;
202 keys[n].name = (char*) hostname;
206 r = dns_query_new(m, &q, keys, n);
210 q->request = sd_bus_message_ref(message);
211 q->request_family = family;
212 q->request_hostname = hostname;
213 q->complete = bus_method_resolve_hostname_complete;
215 r = dns_query_start(q);
224 static void bus_method_resolve_address_complete(DnsQuery *q) {
225 _cleanup_free_ char *ip = NULL;
230 in_addr_to_string(q->request_family, &q->request_address, &ip);
234 case DNS_QUERY_SKIPPED:
235 r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_NO_NAME_SERVERS, "Not appropriate name servers or networks found");
238 case DNS_QUERY_TIMEOUT:
239 r = sd_bus_reply_method_errorf(q->request, SD_BUS_ERROR_TIMEOUT, "Query timed out");
242 case DNS_QUERY_ATTEMPTS_MAX:
243 r = sd_bus_reply_method_errorf(q->request, SD_BUS_ERROR_TIMEOUT, "All attempts to contact name servers or networks failed");
246 case DNS_QUERY_FAILURE: {
247 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
249 if (q->rcode == DNS_RCODE_NXDOMAIN)
250 sd_bus_error_setf(&error, _BUS_ERROR_DNS "NXDOMAIN", "No hostname known for address %s ", ip);
253 char p[DECIMAL_STR_MAX(q->rcode)];
255 rc = dns_rcode_to_string(q->rcode);
257 sprintf(p, "%i", q->rcode);
261 n = strappenda(_BUS_ERROR_DNS, rc);
263 sd_bus_error_setf(&error, n, "Could not resolve address %s, server or network returned error %s", ip, rc);
266 r = sd_bus_reply_method_error(q->request, &error);
270 case DNS_QUERY_SUCCESS: {
271 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
272 unsigned i, n, added = 0;
273 _cleanup_free_ char *reverse = NULL;
277 r = dns_name_reverse(q->request_family, &q->request_address, &reverse);
281 r = dns_packet_skip_question(q->packet);
285 r = sd_bus_message_new_method_return(q->request, &reply);
289 r = sd_bus_message_open_container(reply, 'a', "s");
293 n = be16toh(DNS_PACKET_HEADER(q->packet)->ancount) +
294 be16toh(DNS_PACKET_HEADER(q->packet)->nscount) +
295 be16toh(DNS_PACKET_HEADER(q->packet)->arcount);
297 for (i = 0; i < n; i++) {
298 _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
300 r = dns_packet_read_rr(q->packet, &rr, NULL);
304 if (rr->key.class != DNS_CLASS_IN)
306 if (rr->key.type != DNS_TYPE_PTR)
308 if (!dns_name_equal(rr->key.name, reverse))
311 r = sd_bus_message_append(reply, "s", rr->ptr.name);
321 r = sd_bus_message_close_container(reply);
325 r = sd_bus_send(q->manager->bus, reply, NULL);
330 case DNS_QUERY_INVALID_REPLY:
331 r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_INVALID_REPLY, "Received invalid reply");
336 assert_not_reached("Unexpected query state");
341 log_error("Failed to send bus reply: %s", strerror(-r));
346 static int bus_method_resolve_address(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
347 _cleanup_(dns_resource_key_free) DnsResourceKey key = {};
348 Manager *m = userdata;
360 r = sd_bus_message_read(message, "y", &family);
364 if (!IN_SET(family, AF_INET, AF_INET6))
365 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown address family %u", family);
367 r = sd_bus_message_read_array(message, 'y', &d, &sz);
371 if ((family == AF_INET && sz != sizeof(struct in_addr)) ||
372 (family == AF_INET6 && sz != sizeof(struct in6_addr)))
373 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid address size");
375 r = sd_bus_message_read(message, "i", &ifindex);
379 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid interface index");
381 key.class = DNS_CLASS_IN;
382 key.type = DNS_TYPE_PTR;
383 r = dns_name_reverse(family, d, &key.name);
387 r = dns_query_new(m, &q, &key, 1);
391 q->request = sd_bus_message_ref(message);
392 q->request_family = family;
393 memcpy(&q->request_address, d, sz);
394 q->complete = bus_method_resolve_address_complete;
396 r = dns_query_start(q);
405 static const sd_bus_vtable resolve_vtable[] = {
406 SD_BUS_VTABLE_START(0),
407 SD_BUS_METHOD("ResolveHostname", "sy", "a(yayi)", bus_method_resolve_hostname, SD_BUS_VTABLE_UNPRIVILEGED),
408 SD_BUS_METHOD("ResolveAddress", "yayi", "as", bus_method_resolve_address, SD_BUS_VTABLE_UNPRIVILEGED),
412 static int on_bus_retry(sd_event_source *s, usec_t usec, void *userdata) {
413 Manager *m = userdata;
418 m->bus_retry_event_source = sd_event_source_unref(m->bus_retry_event_source);
420 manager_connect_bus(m);
424 int manager_connect_bus(Manager *m) {
432 r = sd_bus_default_system(&m->bus);
434 /* We failed to connect? Yuck, we must be in early
435 * boot. Let's try in 5s again. As soon as we have
436 * kdbus we can stop doing this... */
438 log_debug("Failed to connect to bus, trying again in 5s: %s", strerror(-r));
440 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);
442 log_error("Failed to install bus reconnect time event: %s", strerror(-r));
449 r = sd_bus_add_object_vtable(m->bus, NULL, "/org/freedesktop/resolve1", "org.freedesktop.resolve1", resolve_vtable, m);
451 log_error("Failed to register object: %s", strerror(-r));
455 r = sd_bus_request_name(m->bus, "org.freedesktop.resolve1", 0);
457 log_error("Failed to register name: %s", strerror(-r));
461 r = sd_bus_attach_event(m->bus, m->event, 0);
463 log_error("Failed to attach bus to event loop: %s", strerror(-r));