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 = DNS_PACKET_ANCOUNT(q->packet) +
90 DNS_PACKET_NSCOUNT(q->packet) +
91 DNS_PACKET_ARCOUNT(q->packet);
92 for (i = 0; i < n; i++) {
93 _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
95 r = dns_packet_read_rr(q->packet, &rr, NULL);
99 if (rr->key.class != DNS_CLASS_IN)
102 if (!(q->request_family != AF_INET6 && rr->key.type == DNS_TYPE_A) &&
103 !(q->request_family != AF_INET && rr->key.type == DNS_TYPE_AAAA))
106 if (!dns_name_equal(rr->key.name, q->request_hostname))
109 r = sd_bus_message_open_container(reply, 'r', "yayi");
113 if (rr->key.type == DNS_TYPE_A) {
114 r = sd_bus_message_append(reply, "y", AF_INET);
118 r = sd_bus_message_append_array(reply, 'y', &rr->a.in_addr, sizeof(struct in_addr));
120 r = sd_bus_message_append(reply, "y", AF_INET6);
124 r = sd_bus_message_append_array(reply, 'y', &rr->aaaa.in6_addr, sizeof(struct in6_addr));
129 r = sd_bus_message_append(reply, "i", q->packet->ifindex);
133 r = sd_bus_message_close_container(reply);
141 r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_NO_SUCH_RR, "Hostname %s does not have RR of this type", q->request_hostname);
145 r = sd_bus_message_close_container(reply);
149 r = sd_bus_send(q->manager->bus, reply, NULL);
154 case DNS_QUERY_INVALID_REPLY:
155 r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_INVALID_REPLY, "Received invalid reply");
160 assert_not_reached("Unexpected query state");
165 log_error("Failed to send bus reply: %s", strerror(-r));
170 static int bus_method_resolve_hostname(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
171 Manager *m = userdata;
172 const char *hostname;
174 DnsResourceKey keys[2];
183 r = sd_bus_message_read(message, "sy", &hostname, &family);
187 if (!IN_SET(family, AF_INET, AF_INET6, AF_UNSPEC))
188 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown address family %u", family);
190 if (!hostname_is_valid(hostname))
191 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid hostname '%s'", hostname);
193 if (family != AF_INET6) {
194 keys[n].class = DNS_CLASS_IN;
195 keys[n].type = DNS_TYPE_A;
196 keys[n].name = (char*) hostname;
200 if (family != AF_INET) {
201 keys[n].class = DNS_CLASS_IN;
202 keys[n].type = DNS_TYPE_AAAA;
203 keys[n].name = (char*) hostname;
207 r = dns_query_new(m, &q, keys, n);
211 q->request = sd_bus_message_ref(message);
212 q->request_family = family;
213 q->request_hostname = hostname;
214 q->complete = bus_method_resolve_hostname_complete;
216 r = dns_query_start(q);
225 static void bus_method_resolve_address_complete(DnsQuery *q) {
226 _cleanup_free_ char *ip = NULL;
231 in_addr_to_string(q->request_family, &q->request_address, &ip);
235 case DNS_QUERY_SKIPPED:
236 r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_NO_NAME_SERVERS, "Not appropriate name servers or networks found");
239 case DNS_QUERY_TIMEOUT:
240 r = sd_bus_reply_method_errorf(q->request, SD_BUS_ERROR_TIMEOUT, "Query timed out");
243 case DNS_QUERY_ATTEMPTS_MAX:
244 r = sd_bus_reply_method_errorf(q->request, SD_BUS_ERROR_TIMEOUT, "All attempts to contact name servers or networks failed");
247 case DNS_QUERY_FAILURE: {
248 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
250 if (q->rcode == DNS_RCODE_NXDOMAIN)
251 sd_bus_error_setf(&error, _BUS_ERROR_DNS "NXDOMAIN", "No hostname known for address %s ", ip);
254 char p[DECIMAL_STR_MAX(q->rcode)];
256 rc = dns_rcode_to_string(q->rcode);
258 sprintf(p, "%i", q->rcode);
262 n = strappenda(_BUS_ERROR_DNS, rc);
264 sd_bus_error_setf(&error, n, "Could not resolve address %s, server or network returned error %s", ip, rc);
267 r = sd_bus_reply_method_error(q->request, &error);
271 case DNS_QUERY_SUCCESS: {
272 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
273 unsigned i, n, added = 0;
274 _cleanup_free_ char *reverse = NULL;
278 r = dns_name_reverse(q->request_family, &q->request_address, &reverse);
282 r = dns_packet_skip_question(q->packet);
286 r = sd_bus_message_new_method_return(q->request, &reply);
290 r = sd_bus_message_open_container(reply, 'a', "s");
294 n = DNS_PACKET_ANCOUNT(q->packet) +
295 DNS_PACKET_NSCOUNT(q->packet) +
296 DNS_PACKET_ARCOUNT(q->packet);
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);
319 r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_NO_SUCH_RR, "Address %s does not have RR of this type", ip);
323 r = sd_bus_message_close_container(reply);
327 r = sd_bus_send(q->manager->bus, reply, NULL);
332 case DNS_QUERY_INVALID_REPLY:
333 r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_INVALID_REPLY, "Received invalid reply");
338 assert_not_reached("Unexpected query state");
343 log_error("Failed to send bus reply: %s", strerror(-r));
348 static int bus_method_resolve_address(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
349 _cleanup_(dns_resource_key_free) DnsResourceKey key = {};
350 Manager *m = userdata;
362 r = sd_bus_message_read(message, "y", &family);
366 if (!IN_SET(family, AF_INET, AF_INET6))
367 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown address family %u", family);
369 r = sd_bus_message_read_array(message, 'y', &d, &sz);
373 if ((family == AF_INET && sz != sizeof(struct in_addr)) ||
374 (family == AF_INET6 && sz != sizeof(struct in6_addr)))
375 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid address size");
377 r = sd_bus_message_read(message, "i", &ifindex);
381 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid interface index");
383 key.class = DNS_CLASS_IN;
384 key.type = DNS_TYPE_PTR;
385 r = dns_name_reverse(family, d, &key.name);
389 r = dns_query_new(m, &q, &key, 1);
393 q->request = sd_bus_message_ref(message);
394 q->request_family = family;
395 memcpy(&q->request_address, d, sz);
396 q->complete = bus_method_resolve_address_complete;
398 r = dns_query_start(q);
407 static const sd_bus_vtable resolve_vtable[] = {
408 SD_BUS_VTABLE_START(0),
409 SD_BUS_METHOD("ResolveHostname", "sy", "a(yayi)", bus_method_resolve_hostname, SD_BUS_VTABLE_UNPRIVILEGED),
410 SD_BUS_METHOD("ResolveAddress", "yayi", "as", bus_method_resolve_address, SD_BUS_VTABLE_UNPRIVILEGED),
414 static int on_bus_retry(sd_event_source *s, usec_t usec, void *userdata) {
415 Manager *m = userdata;
420 m->bus_retry_event_source = sd_event_source_unref(m->bus_retry_event_source);
422 manager_connect_bus(m);
426 int manager_connect_bus(Manager *m) {
434 r = sd_bus_default_system(&m->bus);
436 /* We failed to connect? Yuck, we must be in early
437 * boot. Let's try in 5s again. As soon as we have
438 * kdbus we can stop doing this... */
440 log_debug("Failed to connect to bus, trying again in 5s: %s", strerror(-r));
442 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);
444 log_error("Failed to install bus reconnect time event: %s", strerror(-r));
451 r = sd_bus_add_object_vtable(m->bus, NULL, "/org/freedesktop/resolve1", "org.freedesktop.resolve1.Manager", resolve_vtable, m);
453 log_error("Failed to register object: %s", strerror(-r));
457 r = sd_bus_request_name(m->bus, "org.freedesktop.resolve1", 0);
459 log_error("Failed to register name: %s", strerror(-r));
463 r = sd_bus_attach_event(m->bus, m->event, 0);
465 log_error("Failed to attach bus to event loop: %s", strerror(-r));