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);
142 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);
146 r = sd_bus_message_close_container(reply);
150 r = sd_bus_send(q->manager->bus, reply, NULL);
155 case DNS_QUERY_INVALID_REPLY:
156 r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_INVALID_REPLY, "Received invalid reply");
161 assert_not_reached("Unexpected query state");
166 log_error("Failed to send bus reply: %s", strerror(-r));
171 static int bus_method_resolve_hostname(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
172 Manager *m = userdata;
173 const char *hostname;
175 DnsResourceKey keys[2];
184 r = sd_bus_message_read(message, "sy", &hostname, &family);
188 if (!IN_SET(family, AF_INET, AF_INET6, AF_UNSPEC))
189 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown address family %u", family);
191 if (!hostname_is_valid(hostname))
192 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid hostname '%s'", hostname);
194 if (family != AF_INET6) {
195 keys[n].class = DNS_CLASS_IN;
196 keys[n].type = DNS_TYPE_A;
197 keys[n].name = (char*) hostname;
201 if (family != AF_INET) {
202 keys[n].class = DNS_CLASS_IN;
203 keys[n].type = DNS_TYPE_AAAA;
204 keys[n].name = (char*) hostname;
208 r = dns_query_new(m, &q, keys, n);
212 q->request = sd_bus_message_ref(message);
213 q->request_family = family;
214 q->request_hostname = hostname;
215 q->complete = bus_method_resolve_hostname_complete;
217 r = dns_query_start(q);
226 static void bus_method_resolve_address_complete(DnsQuery *q) {
227 _cleanup_free_ char *ip = NULL;
232 in_addr_to_string(q->request_family, &q->request_address, &ip);
236 case DNS_QUERY_SKIPPED:
237 r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_NO_NAME_SERVERS, "Not appropriate name servers or networks found");
240 case DNS_QUERY_TIMEOUT:
241 r = sd_bus_reply_method_errorf(q->request, SD_BUS_ERROR_TIMEOUT, "Query timed out");
244 case DNS_QUERY_ATTEMPTS_MAX:
245 r = sd_bus_reply_method_errorf(q->request, SD_BUS_ERROR_TIMEOUT, "All attempts to contact name servers or networks failed");
248 case DNS_QUERY_FAILURE: {
249 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
251 if (q->rcode == DNS_RCODE_NXDOMAIN)
252 sd_bus_error_setf(&error, _BUS_ERROR_DNS "NXDOMAIN", "No hostname known for address %s ", ip);
255 char p[DECIMAL_STR_MAX(q->rcode)];
257 rc = dns_rcode_to_string(q->rcode);
259 sprintf(p, "%i", q->rcode);
263 n = strappenda(_BUS_ERROR_DNS, rc);
265 sd_bus_error_setf(&error, n, "Could not resolve address %s, server or network returned error %s", ip, rc);
268 r = sd_bus_reply_method_error(q->request, &error);
272 case DNS_QUERY_SUCCESS: {
273 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
274 unsigned i, n, added = 0;
275 _cleanup_free_ char *reverse = NULL;
279 r = dns_name_reverse(q->request_family, &q->request_address, &reverse);
283 r = dns_packet_skip_question(q->packet);
287 r = sd_bus_message_new_method_return(q->request, &reply);
291 r = sd_bus_message_open_container(reply, 'a', "s");
295 n = be16toh(DNS_PACKET_HEADER(q->packet)->ancount) +
296 be16toh(DNS_PACKET_HEADER(q->packet)->nscount) +
297 be16toh(DNS_PACKET_HEADER(q->packet)->arcount);
299 for (i = 0; i < n; i++) {
300 _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
302 r = dns_packet_read_rr(q->packet, &rr, NULL);
306 if (rr->key.class != DNS_CLASS_IN)
308 if (rr->key.type != DNS_TYPE_PTR)
310 if (!dns_name_equal(rr->key.name, reverse))
313 r = sd_bus_message_append(reply, "s", rr->ptr.name);
321 r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_NO_SUCH_RR, "Address %s does not have RR of this type", ip);
325 r = sd_bus_message_close_container(reply);
329 r = sd_bus_send(q->manager->bus, reply, NULL);
334 case DNS_QUERY_INVALID_REPLY:
335 r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_INVALID_REPLY, "Received invalid reply");
340 assert_not_reached("Unexpected query state");
345 log_error("Failed to send bus reply: %s", strerror(-r));
350 static int bus_method_resolve_address(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
351 _cleanup_(dns_resource_key_free) DnsResourceKey key = {};
352 Manager *m = userdata;
364 r = sd_bus_message_read(message, "y", &family);
368 if (!IN_SET(family, AF_INET, AF_INET6))
369 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown address family %u", family);
371 r = sd_bus_message_read_array(message, 'y', &d, &sz);
375 if ((family == AF_INET && sz != sizeof(struct in_addr)) ||
376 (family == AF_INET6 && sz != sizeof(struct in6_addr)))
377 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid address size");
379 r = sd_bus_message_read(message, "i", &ifindex);
383 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid interface index");
385 key.class = DNS_CLASS_IN;
386 key.type = DNS_TYPE_PTR;
387 r = dns_name_reverse(family, d, &key.name);
391 r = dns_query_new(m, &q, &key, 1);
395 q->request = sd_bus_message_ref(message);
396 q->request_family = family;
397 memcpy(&q->request_address, d, sz);
398 q->complete = bus_method_resolve_address_complete;
400 r = dns_query_start(q);
409 static const sd_bus_vtable resolve_vtable[] = {
410 SD_BUS_VTABLE_START(0),
411 SD_BUS_METHOD("ResolveHostname", "sy", "a(yayi)", bus_method_resolve_hostname, SD_BUS_VTABLE_UNPRIVILEGED),
412 SD_BUS_METHOD("ResolveAddress", "yayi", "as", bus_method_resolve_address, SD_BUS_VTABLE_UNPRIVILEGED),
416 static int on_bus_retry(sd_event_source *s, usec_t usec, void *userdata) {
417 Manager *m = userdata;
422 m->bus_retry_event_source = sd_event_source_unref(m->bus_retry_event_source);
424 manager_connect_bus(m);
428 int manager_connect_bus(Manager *m) {
436 r = sd_bus_default_system(&m->bus);
438 /* We failed to connect? Yuck, we must be in early
439 * boot. Let's try in 5s again. As soon as we have
440 * kdbus we can stop doing this... */
442 log_debug("Failed to connect to bus, trying again in 5s: %s", strerror(-r));
444 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);
446 log_error("Failed to install bus reconnect time event: %s", strerror(-r));
453 r = sd_bus_add_object_vtable(m->bus, NULL, "/org/freedesktop/resolve1", "org.freedesktop.resolve1.Manager", resolve_vtable, m);
455 log_error("Failed to register object: %s", strerror(-r));
459 r = sd_bus_request_name(m->bus, "org.freedesktop.resolve1", 0);
461 log_error("Failed to register name: %s", strerror(-r));
465 r = sd_bus_attach_event(m->bus, m->event, 0);
467 log_error("Failed to attach bus to event loop: %s", strerror(-r));