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 int reply_query_state(DnsQuery *q) {
29 _cleanup_free_ char *ip = NULL;
33 if (q->request_hostname)
34 name = q->request_hostname;
36 r = in_addr_to_string(q->request_family, &q->request_address, &ip);
45 case DNS_QUERY_NO_SERVERS:
46 return sd_bus_reply_method_errorf(q->request, BUS_ERROR_NO_NAME_SERVERS, "Not appropriate name servers or networks found");
48 case DNS_QUERY_TIMEOUT:
49 return sd_bus_reply_method_errorf(q->request, SD_BUS_ERROR_TIMEOUT, "Query timed out");
51 case DNS_QUERY_ATTEMPTS_MAX:
52 return sd_bus_reply_method_errorf(q->request, SD_BUS_ERROR_TIMEOUT, "All attempts to contact name servers or networks failed");
54 case DNS_QUERY_RESOURCES:
55 return sd_bus_reply_method_errorf(q->request, BUS_ERROR_NO_RESOURCES, "Not enough resources");
57 case DNS_QUERY_INVALID_REPLY:
58 return sd_bus_reply_method_errorf(q->request, BUS_ERROR_INVALID_REPLY, "Received invalid reply");
60 case DNS_QUERY_FAILURE: {
61 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
65 if (DNS_PACKET_RCODE(q->received) == DNS_RCODE_NXDOMAIN)
66 sd_bus_error_setf(&error, _BUS_ERROR_DNS "NXDOMAIN", "'%s' not found", name);
69 char p[3]; /* the rcode is 4 bits long */
71 rc = dns_rcode_to_string(DNS_PACKET_RCODE(q->received));
73 sprintf(p, "%i", DNS_PACKET_RCODE(q->received));
77 n = strappenda(_BUS_ERROR_DNS, rc);
78 sd_bus_error_setf(&error, n, "Could not resolve '%s', server or network returned error %s", name, rc);
81 return sd_bus_reply_method_error(q->request, &error);
86 case DNS_QUERY_SUCCESS:
87 assert_not_reached("Impossible state");
91 static void bus_method_resolve_hostname_complete(DnsQuery *q) {
92 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
93 unsigned i, n, added = 0;
98 if (q->state != DNS_QUERY_SUCCESS) {
99 r = reply_query_state(q);
105 r = dns_packet_skip_question(q->received);
109 r = sd_bus_message_new_method_return(q->request, &reply);
113 r = sd_bus_message_open_container(reply, 'a', "(yayi)");
117 n = DNS_PACKET_ANCOUNT(q->received) +
118 DNS_PACKET_NSCOUNT(q->received) +
119 DNS_PACKET_ARCOUNT(q->received);
120 for (i = 0; i < n; i++) {
121 _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
123 r = dns_packet_read_rr(q->received, &rr, NULL);
127 if (rr->key.class != DNS_CLASS_IN)
130 if (!(q->request_family != AF_INET6 && rr->key.type == DNS_TYPE_A) &&
131 !(q->request_family != AF_INET && rr->key.type == DNS_TYPE_AAAA))
134 if (!dns_name_equal(rr->key.name, q->request_hostname))
137 r = sd_bus_message_open_container(reply, 'r', "yayi");
141 if (rr->key.type == DNS_TYPE_A) {
142 r = sd_bus_message_append(reply, "y", AF_INET);
146 r = sd_bus_message_append_array(reply, 'y', &rr->a.in_addr, sizeof(struct in_addr));
148 r = sd_bus_message_append(reply, "y", AF_INET6);
152 r = sd_bus_message_append_array(reply, 'y', &rr->aaaa.in6_addr, sizeof(struct in6_addr));
157 r = sd_bus_message_append(reply, "i", q->received->ifindex);
161 r = sd_bus_message_close_container(reply);
169 r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_NO_SUCH_RR, "'%s' does not have RR of this type", q->request_hostname);
173 r = sd_bus_message_close_container(reply);
177 r = sd_bus_send(q->manager->bus, reply, NULL);
181 r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_INVALID_REPLY, "Received invalid reply");
185 log_error("Failed to send bus reply: %s", strerror(-r));
190 static int bus_method_resolve_hostname(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
191 Manager *m = userdata;
192 const char *hostname;
194 DnsResourceKey keys[2];
203 r = sd_bus_message_read(message, "sy", &hostname, &family);
207 if (!IN_SET(family, AF_INET, AF_INET6, AF_UNSPEC))
208 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown address family %u", family);
210 if (!hostname_is_valid(hostname))
211 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid hostname '%s'", hostname);
213 if (family != AF_INET6) {
214 keys[n].class = DNS_CLASS_IN;
215 keys[n].type = DNS_TYPE_A;
216 keys[n].name = (char*) hostname;
220 if (family != AF_INET) {
221 keys[n].class = DNS_CLASS_IN;
222 keys[n].type = DNS_TYPE_AAAA;
223 keys[n].name = (char*) hostname;
227 r = dns_query_new(m, &q, keys, n);
231 q->request = sd_bus_message_ref(message);
232 q->request_family = family;
233 q->request_hostname = hostname;
234 q->complete = bus_method_resolve_hostname_complete;
236 r = dns_query_start(q);
245 static void bus_method_resolve_address_complete(DnsQuery *q) {
246 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
247 unsigned i, n, added = 0;
248 _cleanup_free_ char *reverse = NULL;
253 if (q->state != DNS_QUERY_SUCCESS) {
254 r = reply_query_state(q);
260 r = dns_name_reverse(q->request_family, &q->request_address, &reverse);
264 r = dns_packet_skip_question(q->received);
268 r = sd_bus_message_new_method_return(q->request, &reply);
272 r = sd_bus_message_open_container(reply, 'a', "s");
276 n = DNS_PACKET_ANCOUNT(q->received) +
277 DNS_PACKET_NSCOUNT(q->received) +
278 DNS_PACKET_ARCOUNT(q->received);
280 for (i = 0; i < n; i++) {
281 _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
283 r = dns_packet_read_rr(q->received, &rr, NULL);
287 if (rr->key.class != DNS_CLASS_IN)
289 if (rr->key.type != DNS_TYPE_PTR)
291 if (!dns_name_equal(rr->key.name, reverse))
294 r = sd_bus_message_append(reply, "s", rr->ptr.name);
302 _cleanup_free_ char *ip = NULL;
304 in_addr_to_string(q->request_family, &q->request_address, &ip);
306 r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_NO_SUCH_RR, "Address '%s' does not have RR of this type", ip);
310 r = sd_bus_message_close_container(reply);
314 r = sd_bus_send(q->manager->bus, reply, NULL);
318 r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_INVALID_REPLY, "Received invalid reply");
322 log_error("Failed to send bus reply: %s", strerror(-r));
327 static int bus_method_resolve_address(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
328 _cleanup_(dns_resource_key_free) DnsResourceKey key = {};
329 Manager *m = userdata;
341 r = sd_bus_message_read(message, "y", &family);
345 if (!IN_SET(family, AF_INET, AF_INET6))
346 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown address family %u", family);
348 r = sd_bus_message_read_array(message, 'y', &d, &sz);
352 if ((family == AF_INET && sz != sizeof(struct in_addr)) ||
353 (family == AF_INET6 && sz != sizeof(struct in6_addr)))
354 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid address size");
356 r = sd_bus_message_read(message, "i", &ifindex);
360 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid interface index");
362 key.class = DNS_CLASS_IN;
363 key.type = DNS_TYPE_PTR;
364 r = dns_name_reverse(family, d, &key.name);
368 r = dns_query_new(m, &q, &key, 1);
372 q->request = sd_bus_message_ref(message);
373 q->request_family = family;
374 memcpy(&q->request_address, d, sz);
375 q->complete = bus_method_resolve_address_complete;
377 r = dns_query_start(q);
386 static const sd_bus_vtable resolve_vtable[] = {
387 SD_BUS_VTABLE_START(0),
388 SD_BUS_METHOD("ResolveHostname", "sy", "a(yayi)", bus_method_resolve_hostname, SD_BUS_VTABLE_UNPRIVILEGED),
389 SD_BUS_METHOD("ResolveAddress", "yayi", "as", bus_method_resolve_address, SD_BUS_VTABLE_UNPRIVILEGED),
393 static int on_bus_retry(sd_event_source *s, usec_t usec, void *userdata) {
394 Manager *m = userdata;
399 m->bus_retry_event_source = sd_event_source_unref(m->bus_retry_event_source);
401 manager_connect_bus(m);
405 int manager_connect_bus(Manager *m) {
413 r = sd_bus_default_system(&m->bus);
415 /* We failed to connect? Yuck, we must be in early
416 * boot. Let's try in 5s again. As soon as we have
417 * kdbus we can stop doing this... */
419 log_debug("Failed to connect to bus, trying again in 5s: %s", strerror(-r));
421 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);
423 log_error("Failed to install bus reconnect time event: %s", strerror(-r));
430 r = sd_bus_add_object_vtable(m->bus, NULL, "/org/freedesktop/resolve1", "org.freedesktop.resolve1.Manager", resolve_vtable, m);
432 log_error("Failed to register object: %s", strerror(-r));
436 r = sd_bus_request_name(m->bus, "org.freedesktop.resolve1", 0);
438 log_error("Failed to register name: %s", strerror(-r));
442 r = sd_bus_attach_event(m->bus, m->event, 0);
444 log_error("Failed to attach bus to event loop: %s", strerror(-r));