]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/resolve/resolved-bus.c
resolved: scope - write() unicast DNS packets
[thirdparty/systemd.git] / src / resolve / resolved-bus.c
CommitLineData
74b2466e
LP
1/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3/***
4 This file is part of systemd.
5
6 Copyright 2014 Lennart Poettering
7
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.
12
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.
17
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/>.
20***/
21
96aad8d1 22#include "bus-common-errors.h"
74b2466e
LP
23#include "bus-util.h"
24
4ad7f276 25#include "dns-domain.h"
39d8db04 26#include "resolved-bus.h"
51323288 27#include "resolved-def.h"
74b2466e 28
ad867662
LP
29static int reply_query_state(DnsQuery *q) {
30 _cleanup_free_ char *ip = NULL;
31 const char *name;
74b2466e
LP
32 int r;
33
ad867662
LP
34 if (q->request_hostname)
35 name = q->request_hostname;
36 else {
37 r = in_addr_to_string(q->request_family, &q->request_address, &ip);
38 if (r < 0)
39 return r;
74b2466e 40
ad867662
LP
41 name = ip;
42 }
43
44 switch (q->state) {
74b2466e 45
ec2c5e43 46 case DNS_TRANSACTION_NO_SERVERS:
309e9d86 47 return sd_bus_reply_method_errorf(q->request, BUS_ERROR_NO_NAME_SERVERS, "No appropriate name servers or networks for name found");
74b2466e 48
ec2c5e43 49 case DNS_TRANSACTION_TIMEOUT:
ad867662 50 return sd_bus_reply_method_errorf(q->request, SD_BUS_ERROR_TIMEOUT, "Query timed out");
74b2466e 51
ec2c5e43 52 case DNS_TRANSACTION_ATTEMPTS_MAX_REACHED:
ad867662
LP
53 return sd_bus_reply_method_errorf(q->request, SD_BUS_ERROR_TIMEOUT, "All attempts to contact name servers or networks failed");
54
818f766b
LP
55 case DNS_TRANSACTION_INVALID_REPLY:
56 return sd_bus_reply_method_errorf(q->request, BUS_ERROR_INVALID_REPLY, "Received invalid reply");
57
ec2c5e43 58 case DNS_TRANSACTION_RESOURCES:
ad867662
LP
59 return sd_bus_reply_method_errorf(q->request, BUS_ERROR_NO_RESOURCES, "Not enough resources");
60
818f766b
LP
61 case DNS_TRANSACTION_ABORTED:
62 return sd_bus_reply_method_errorf(q->request, BUS_ERROR_ABORTED, "Query aborted");
74b2466e 63
ec2c5e43 64 case DNS_TRANSACTION_FAILURE: {
74b2466e
LP
65 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
66
faa133f3 67 if (q->answer_rcode == DNS_RCODE_NXDOMAIN)
ad867662 68 sd_bus_error_setf(&error, _BUS_ERROR_DNS "NXDOMAIN", "'%s' not found", name);
74b2466e
LP
69 else {
70 const char *rc, *n;
ad867662 71 char p[3]; /* the rcode is 4 bits long */
74b2466e 72
faa133f3 73 rc = dns_rcode_to_string(q->answer_rcode);
74b2466e 74 if (!rc) {
faa133f3 75 sprintf(p, "%i", q->answer_rcode);
74b2466e
LP
76 rc = p;
77 }
78
63c372cb 79 n = strjoina(_BUS_ERROR_DNS, rc);
ad867662 80 sd_bus_error_setf(&error, n, "Could not resolve '%s', server or network returned error %s", name, rc);
74b2466e
LP
81 }
82
ad867662 83 return sd_bus_reply_method_error(q->request, &error);
74b2466e
LP
84 }
85
ec2c5e43
LP
86 case DNS_TRANSACTION_NULL:
87 case DNS_TRANSACTION_PENDING:
88 case DNS_TRANSACTION_SUCCESS:
8ba9fd9c 89 default:
ad867662
LP
90 assert_not_reached("Impossible state");
91 }
92}
74b2466e 93
51323288 94static int append_address(sd_bus_message *reply, DnsResourceRecord *rr) {
8ba9fd9c
LP
95 int r;
96
97 assert(reply);
98 assert(rr);
99
51323288 100 r = sd_bus_message_open_container(reply, 'r', "iay");
8ba9fd9c
LP
101 if (r < 0)
102 return r;
103
faa133f3 104 if (rr->key->type == DNS_TYPE_A) {
0dd25fb9 105 r = sd_bus_message_append(reply, "i", AF_INET);
8ba9fd9c
LP
106 if (r < 0)
107 return r;
108
109 r = sd_bus_message_append_array(reply, 'y', &rr->a.in_addr, sizeof(struct in_addr));
faa133f3
LP
110
111 } else if (rr->key->type == DNS_TYPE_AAAA) {
0dd25fb9 112 r = sd_bus_message_append(reply, "i", AF_INET6);
8ba9fd9c
LP
113 if (r < 0)
114 return r;
115
116 r = sd_bus_message_append_array(reply, 'y', &rr->aaaa.in6_addr, sizeof(struct in6_addr));
faa133f3
LP
117 } else
118 return -EAFNOSUPPORT;
119
8ba9fd9c
LP
120 if (r < 0)
121 return r;
122
8ba9fd9c
LP
123 r = sd_bus_message_close_container(reply);
124 if (r < 0)
125 return r;
126
127 return 0;
128}
129
ad867662 130static void bus_method_resolve_hostname_complete(DnsQuery *q) {
309e9d86 131 _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *cname = NULL, *canonical = NULL;
ad867662 132 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
faa133f3
LP
133 _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL;
134 unsigned added = 0, i;
51323288 135 int r;
74b2466e 136
ad867662 137 assert(q);
74b2466e 138
ec2c5e43 139 if (q->state != DNS_TRANSACTION_SUCCESS) {
ad867662
LP
140 r = reply_query_state(q);
141 goto finish;
142 }
74b2466e 143
ad867662
LP
144 r = sd_bus_message_new_method_return(q->request, &reply);
145 if (r < 0)
146 goto finish;
74b2466e 147
51323288 148 r = sd_bus_message_append(reply, "i", q->answer_ifindex);
ad867662
LP
149 if (r < 0)
150 goto finish;
74b2466e 151
51323288
LP
152 r = sd_bus_message_open_container(reply, 'a', "(iay)");
153 if (r < 0)
154 goto finish;
8ba9fd9c 155
3339cb71
LP
156 if (q->answer) {
157 answer = dns_answer_ref(q->answer);
158
159 for (i = 0; i < answer->n_rrs; i++) {
160 r = dns_question_matches_rr(q->question, answer->rrs[i]);
8ba9fd9c 161 if (r < 0)
2d4c5cbc 162 goto finish;
3339cb71
LP
163 if (r == 0) {
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]);
167 if (r < 0)
2d4c5cbc 168 goto finish;
3339cb71
LP
169 if (r > 0)
170 cname = dns_resource_record_ref(answer->rrs[i]);
74b2466e 171
3339cb71
LP
172 continue;
173 }
74b2466e 174
51323288 175 r = append_address(reply, answer->rrs[i]);
3339cb71
LP
176 if (r < 0)
177 goto finish;
74b2466e 178
3339cb71
LP
179 if (!canonical)
180 canonical = dns_resource_record_ref(answer->rrs[i]);
309e9d86 181
3339cb71
LP
182 added ++;
183 }
8ba9fd9c 184 }
74b2466e 185
657dbed2 186 if (added == 0) {
8ba9fd9c 187 if (!cname) {
309e9d86 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);
ad867662 189 goto finish;
8ba9fd9c 190 }
74b2466e 191
8ba9fd9c
LP
192 /* This has a cname? Then update the query with the
193 * new cname. */
322345fd 194 r = dns_query_cname_redirect(q, cname->cname.name);
8ba9fd9c
LP
195 if (r < 0) {
196 if (r == -ELOOP)
197 r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_CNAME_LOOP, "CNAME loop on '%s'", q->request_hostname);
198 else
199 r = sd_bus_reply_method_errno(q->request, -r, NULL);
74b2466e 200
74b2466e 201 goto finish;
8ba9fd9c 202 }
74b2466e 203
8ba9fd9c
LP
204 /* Before we restart the query, let's see if any of
205 * the RRs we already got already answers our query */
faa133f3
LP
206 for (i = 0; i < answer->n_rrs; i++) {
207 r = dns_question_matches_rr(q->question, answer->rrs[i]);
8ba9fd9c 208 if (r < 0)
2d4c5cbc 209 goto finish;
8ba9fd9c
LP
210 if (r == 0)
211 continue;
212
51323288 213 r = append_address(reply, answer->rrs[i]);
8ba9fd9c
LP
214 if (r < 0)
215 goto finish;
216
309e9d86 217 if (!canonical)
faa133f3 218 canonical = dns_resource_record_ref(answer->rrs[i]);
309e9d86 219
8ba9fd9c
LP
220 added++;
221 }
222
657dbed2
ZJS
223 // what about the cache?
224
8ba9fd9c
LP
225 /* If we didn't find anything, then let's restart the
226 * query, this time with the cname */
227 if (added <= 0) {
322345fd 228 r = dns_query_go(q);
309e9d86
LP
229 if (r == -ESRCH) {
230 r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_NO_NAME_SERVERS, "No appropriate name servers or networks for name found");
231 goto finish;
232 }
8ba9fd9c
LP
233 if (r < 0) {
234 r = sd_bus_reply_method_errno(q->request, -r, NULL);
235 goto finish;
236 }
2d4c5cbc 237
8ba9fd9c
LP
238 return;
239 }
74b2466e
LP
240 }
241
ad867662
LP
242 r = sd_bus_message_close_container(reply);
243 if (r < 0)
244 goto finish;
245
309e9d86
LP
246 /* Return the precise spelling and uppercasing reported by the server */
247 assert(canonical);
51323288 248 r = sd_bus_message_append(reply, "st", DNS_RESOURCE_KEY_NAME(canonical->key), SD_RESOLVED_FLAGS_MAKE(q->answer_protocol, q->answer_family));
309e9d86
LP
249 if (r < 0)
250 goto finish;
251
ad867662 252 r = sd_bus_send(q->manager->bus, reply, NULL);
ad867662 253
74b2466e 254finish:
2d4c5cbc 255 if (r < 0) {
da927ba9 256 log_error_errno(r, "Failed to send hostname reply: %m");
2d4c5cbc
LP
257 sd_bus_reply_method_errno(q->request, -r, NULL);
258 }
74b2466e
LP
259
260 dns_query_free(q);
261}
262
51323288
LP
263static int check_ifindex_flags(int ifindex, uint64_t *flags, sd_bus_error *error) {
264 assert(flags);
265
266 if (ifindex < 0)
267 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid interface index");
268
269 if (*flags & ~SD_RESOLVED_FLAGS_ALL)
270 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid flags parameter");
271
272 if (*flags == 0)
273 *flags = SD_RESOLVED_FLAGS_DEFAULT;
274
275 return 0;
276}
277
19070062 278static int bus_method_resolve_hostname(sd_bus_message *message, void *userdata, sd_bus_error *error) {
faa133f3 279 _cleanup_(dns_question_unrefp) DnsQuestion *question = NULL;
74b2466e
LP
280 Manager *m = userdata;
281 const char *hostname;
51323288
LP
282 int family, ifindex;
283 uint64_t flags;
74b2466e 284 DnsQuery *q;
74b2466e
LP
285 int r;
286
74b2466e
LP
287 assert(message);
288 assert(m);
289
51323288 290 r = sd_bus_message_read(message, "isit", &ifindex, &hostname, &family, &flags);
74b2466e
LP
291 if (r < 0)
292 return r;
293
294 if (!IN_SET(family, AF_INET, AF_INET6, AF_UNSPEC))
0dd25fb9 295 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown address family %i", family);
74b2466e 296
7b9f7afc
LP
297 r = dns_name_normalize(hostname, NULL);
298 if (r < 0)
74b2466e
LP
299 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid hostname '%s'", hostname);
300
51323288
LP
301 r = check_ifindex_flags(ifindex, &flags, error);
302 if (r < 0)
303 return r;
304
faa133f3
LP
305 question = dns_question_new(family == AF_UNSPEC ? 2 : 1);
306 if (!question)
307 return -ENOMEM;
308
74b2466e 309 if (family != AF_INET6) {
faa133f3
LP
310 _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
311
312 key = dns_resource_key_new(DNS_CLASS_IN, DNS_TYPE_A, hostname);
313 if (!key)
314 return -ENOMEM;
315
316 r = dns_question_add(question, key);
317 if (r < 0)
318 return r;
74b2466e
LP
319 }
320
321 if (family != AF_INET) {
faa133f3
LP
322 _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
323
324 key = dns_resource_key_new(DNS_CLASS_IN, DNS_TYPE_AAAA, hostname);
325 if (!key)
326 return -ENOMEM;
327
328 r = dns_question_add(question, key);
329 if (r < 0)
330 return r;
74b2466e
LP
331 }
332
51323288 333 r = dns_query_new(m, &q, question, ifindex, flags);
74b2466e
LP
334 if (r < 0)
335 return r;
336
337 q->request = sd_bus_message_ref(message);
338 q->request_family = family;
339 q->request_hostname = hostname;
340 q->complete = bus_method_resolve_hostname_complete;
341
966c66e3 342 r = dns_query_bus_track(q, message);
82bd6ddd
LP
343 if (r < 0)
344 return r;
345
322345fd 346 r = dns_query_go(q);
74b2466e
LP
347 if (r < 0) {
348 dns_query_free(q);
309e9d86
LP
349
350 if (r == -ESRCH)
351 sd_bus_error_setf(error, BUS_ERROR_NO_NAME_SERVERS, "No appropriate name servers or networks for name found");
352
74b2466e
LP
353 return r;
354 }
355
356 return 1;
357}
358
359static void bus_method_resolve_address_complete(DnsQuery *q) {
ad867662 360 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
faa133f3
LP
361 _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL;
362 unsigned added = 0, i;
363 int r;
74b2466e
LP
364
365 assert(q);
366
ec2c5e43 367 if (q->state != DNS_TRANSACTION_SUCCESS) {
ad867662
LP
368 r = reply_query_state(q);
369 goto finish;
370 }
74b2466e 371
ad867662
LP
372 r = sd_bus_message_new_method_return(q->request, &reply);
373 if (r < 0)
374 goto finish;
74b2466e 375
51323288
LP
376 r = sd_bus_message_append(reply, "i", q->answer_ifindex);
377 if (r < 0)
378 goto finish;
379
ad867662
LP
380 r = sd_bus_message_open_container(reply, 'a', "s");
381 if (r < 0)
382 goto finish;
74b2466e 383
3339cb71
LP
384 if (q->answer) {
385 answer = dns_answer_ref(q->answer);
faa133f3 386
3339cb71
LP
387 for (i = 0; i < answer->n_rrs; i++) {
388 r = dns_question_matches_rr(q->question, answer->rrs[i]);
389 if (r < 0)
2d4c5cbc 390 goto finish;
3339cb71
LP
391 if (r == 0)
392 continue;
74b2466e 393
3339cb71
LP
394 r = sd_bus_message_append(reply, "s", answer->rrs[i]->ptr.name);
395 if (r < 0)
396 goto finish;
74b2466e 397
3339cb71
LP
398 added ++;
399 }
ad867662 400 }
74b2466e 401
657dbed2 402 if (added == 0) {
ad867662 403 _cleanup_free_ char *ip = NULL;
74b2466e 404
ad867662 405 in_addr_to_string(q->request_family, &q->request_address, &ip);
74b2466e 406
309e9d86 407 r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_NO_SUCH_RR, "Address '%s' does not have any RR of requested type", ip);
ad867662 408 goto finish;
74b2466e
LP
409 }
410
ad867662
LP
411 r = sd_bus_message_close_container(reply);
412 if (r < 0)
413 goto finish;
74b2466e 414
51323288
LP
415 r = sd_bus_message_append(reply, "t", SD_RESOLVED_FLAGS_MAKE(q->answer_protocol, q->answer_family));
416 if (r < 0)
417 goto finish;
418
ad867662 419 r = sd_bus_send(q->manager->bus, reply, NULL);
74b2466e
LP
420
421finish:
2d4c5cbc 422 if (r < 0) {
da927ba9 423 log_error_errno(r, "Failed to send address reply: %m");
2d4c5cbc
LP
424 sd_bus_reply_method_errno(q->request, -r, NULL);
425 }
74b2466e
LP
426
427 dns_query_free(q);
428}
429
19070062 430static int bus_method_resolve_address(sd_bus_message *message, void *userdata, sd_bus_error *error) {
faa133f3
LP
431 _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
432 _cleanup_(dns_question_unrefp) DnsQuestion *question = NULL;
433 _cleanup_free_ char *reverse = NULL;
74b2466e 434 Manager *m = userdata;
faa133f3 435 int family, ifindex;
51323288 436 uint64_t flags;
74b2466e 437 const void *d;
74b2466e
LP
438 DnsQuery *q;
439 size_t sz;
440 int r;
441
74b2466e
LP
442 assert(message);
443 assert(m);
444
51323288 445 r = sd_bus_message_read(message, "ii", &ifindex, &family);
74b2466e
LP
446 if (r < 0)
447 return r;
448
449 if (!IN_SET(family, AF_INET, AF_INET6))
0dd25fb9 450 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown address family %i", family);
74b2466e
LP
451
452 r = sd_bus_message_read_array(message, 'y', &d, &sz);
453 if (r < 0)
454 return r;
455
0dd25fb9 456 if (sz != FAMILY_ADDRESS_SIZE(family))
74b2466e
LP
457 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid address size");
458
51323288
LP
459 r = sd_bus_message_read(message, "t", &flags);
460 if (r < 0)
461 return r;
462
463 r = check_ifindex_flags(ifindex, &flags, error);
74b2466e
LP
464 if (r < 0)
465 return r;
74b2466e 466
faa133f3
LP
467 r = dns_name_reverse(family, d, &reverse);
468 if (r < 0)
469 return r;
470
471 question = dns_question_new(1);
472 if (!question)
473 return -ENOMEM;
474
475 key = dns_resource_key_new_consume(DNS_CLASS_IN, DNS_TYPE_PTR, reverse);
476 if (!key)
477 return -ENOMEM;
478
479 reverse = NULL;
480
481 r = dns_question_add(question, key);
74b2466e
LP
482 if (r < 0)
483 return r;
484
51323288 485 r = dns_query_new(m, &q, question, ifindex, flags);
74b2466e
LP
486 if (r < 0)
487 return r;
488
489 q->request = sd_bus_message_ref(message);
490 q->request_family = family;
491 memcpy(&q->request_address, d, sz);
492 q->complete = bus_method_resolve_address_complete;
493
966c66e3 494 r = dns_query_bus_track(q, message);
82bd6ddd
LP
495 if (r < 0)
496 return r;
497
322345fd 498 r = dns_query_go(q);
74b2466e
LP
499 if (r < 0) {
500 dns_query_free(q);
faa133f3
LP
501
502 if (r == -ESRCH)
503 sd_bus_error_setf(error, BUS_ERROR_NO_NAME_SERVERS, "No appropriate name servers or networks for name found");
504
74b2466e
LP
505 return r;
506 }
507
508 return 1;
509}
510
2d4c5cbc
LP
511static void bus_method_resolve_record_complete(DnsQuery *q) {
512 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
513 _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL;
514 unsigned added = 0, i;
515 int r;
516
517 assert(q);
518
ec2c5e43 519 if (q->state != DNS_TRANSACTION_SUCCESS) {
2d4c5cbc
LP
520 r = reply_query_state(q);
521 goto finish;
522 }
523
524 r = sd_bus_message_new_method_return(q->request, &reply);
525 if (r < 0)
526 goto finish;
527
51323288
LP
528 r = sd_bus_message_append(reply, "i", q->answer_ifindex);
529 if (r < 0)
530 goto finish;
531
2d4c5cbc
LP
532 r = sd_bus_message_open_container(reply, 'a', "(qqay)");
533 if (r < 0)
534 goto finish;
535
536 if (q->answer) {
537 answer = dns_answer_ref(q->answer);
538
539 for (i = 0; i < answer->n_rrs; i++) {
540 _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
541 size_t start;
542
543 r = dns_question_matches_rr(q->question, answer->rrs[i]);
544 if (r < 0)
545 goto finish;
546 if (r == 0)
547 continue;
548
549 r = dns_packet_new(&p, DNS_PROTOCOL_DNS, 0);
550 if (r < 0)
551 goto finish;
552
553 r = dns_packet_append_rr(p, answer->rrs[i], &start);
554 if (r < 0)
555 goto finish;
556
557 r = sd_bus_message_open_container(reply, 'r', "qqay");
558 if (r < 0)
559 goto finish;
560
561 r = sd_bus_message_append(reply, "qq", answer->rrs[i]->key->class, answer->rrs[i]->key->type);
562 if (r < 0)
563 goto finish;
564
565 r = sd_bus_message_append_array(reply, 'y', DNS_PACKET_DATA(p) + start, p->size - start);
566 if (r < 0)
567 goto finish;
568
569 r = sd_bus_message_close_container(reply);
570 if (r < 0)
571 goto finish;
572
573 added ++;
574 }
575 }
576
577 if (added <= 0) {
578 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);
579 goto finish;
580 }
581
582 r = sd_bus_message_close_container(reply);
583 if (r < 0)
584 goto finish;
585
51323288
LP
586 r = sd_bus_message_append(reply, "t", SD_RESOLVED_FLAGS_MAKE(q->answer_protocol, q->answer_family));
587 if (r < 0)
588 goto finish;
589
2d4c5cbc
LP
590 r = sd_bus_send(q->manager->bus, reply, NULL);
591
592finish:
593 if (r < 0) {
da927ba9 594 log_error_errno(r, "Failed to send record reply: %m");
2d4c5cbc
LP
595 sd_bus_reply_method_errno(q->request, -r, NULL);
596 }
597
598 dns_query_free(q);
599}
600
19070062 601static int bus_method_resolve_record(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2d4c5cbc
LP
602 _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
603 _cleanup_(dns_question_unrefp) DnsQuestion *question = NULL;
2d4c5cbc 604 Manager *m = userdata;
2d4c5cbc
LP
605 uint16_t class, type;
606 const char *name;
51323288
LP
607 int r, ifindex;
608 uint64_t flags;
609 DnsQuery *q;
2d4c5cbc 610
2d4c5cbc
LP
611 assert(message);
612 assert(m);
613
51323288 614 r = sd_bus_message_read(message, "isqqt", &ifindex, &name, &class, &type, &flags);
2d4c5cbc
LP
615 if (r < 0)
616 return r;
617
7b9f7afc
LP
618 r = dns_name_normalize(name, NULL);
619 if (r < 0)
620 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid name '%s'", name);
621
51323288
LP
622 r = check_ifindex_flags(ifindex, &flags, error);
623 if (r < 0)
624 return r;
625
2d4c5cbc
LP
626 question = dns_question_new(1);
627 if (!question)
628 return -ENOMEM;
629
630 key = dns_resource_key_new(class, type, name);
631 if (!key)
632 return -ENOMEM;
633
634 r = dns_question_add(question, key);
635 if (r < 0)
636 return r;
637
51323288 638 r = dns_query_new(m, &q, question, ifindex, flags);
2d4c5cbc
LP
639 if (r < 0)
640 return r;
641
642 q->request = sd_bus_message_ref(message);
643 q->request_hostname = name;
644 q->complete = bus_method_resolve_record_complete;
645
966c66e3 646 r = dns_query_bus_track(q, message);
82bd6ddd
LP
647 if (r < 0)
648 return r;
649
2d4c5cbc
LP
650 r = dns_query_go(q);
651 if (r < 0) {
652 dns_query_free(q);
653
654 if (r == -ESRCH)
655 sd_bus_error_setf(error, BUS_ERROR_NO_NAME_SERVERS, "No appropriate name servers or networks for name found");
656
657 return r;
658 }
659
660 return 1;
661}
662
74b2466e
LP
663static const sd_bus_vtable resolve_vtable[] = {
664 SD_BUS_VTABLE_START(0),
51323288
LP
665 SD_BUS_METHOD("ResolveHostname", "isit", "ia(iay)st", bus_method_resolve_hostname, SD_BUS_VTABLE_UNPRIVILEGED),
666 SD_BUS_METHOD("ResolveAddress", "iiayt", "iast", bus_method_resolve_address, SD_BUS_VTABLE_UNPRIVILEGED),
667 SD_BUS_METHOD("ResolveRecord", "isqqt", "ia(qqay)t", bus_method_resolve_record, SD_BUS_VTABLE_UNPRIVILEGED),
74b2466e
LP
668 SD_BUS_VTABLE_END,
669};
670
671static int on_bus_retry(sd_event_source *s, usec_t usec, void *userdata) {
672 Manager *m = userdata;
673
674 assert(s);
675 assert(m);
676
677 m->bus_retry_event_source = sd_event_source_unref(m->bus_retry_event_source);
678
679 manager_connect_bus(m);
680 return 0;
681}
682
19070062 683static int match_prepare_for_sleep(sd_bus_message *message, void *userdata, sd_bus_error *ret_error) {
902bb5d8
LP
684 Manager *m = userdata;
685 int b, r;
686
19070062
LP
687 assert(message);
688 assert(m);
902bb5d8
LP
689
690 r = sd_bus_message_read(message, "b", &b);
691 if (r < 0) {
da927ba9 692 log_debug_errno(r, "Failed to parse PrepareForSleep signal: %m");
902bb5d8
LP
693 return 0;
694 }
695
696 if (b)
697 return 0;
698
699 log_debug("Coming back from suspend, verifying all RRs...");
700
701 manager_verify_all(m);
702 return 0;
703}
704
74b2466e
LP
705int manager_connect_bus(Manager *m) {
706 int r;
707
708 assert(m);
709
710 if (m->bus)
711 return 0;
712
713 r = sd_bus_default_system(&m->bus);
714 if (r < 0) {
715 /* We failed to connect? Yuck, we must be in early
716 * boot. Let's try in 5s again. As soon as we have
717 * kdbus we can stop doing this... */
718
da927ba9 719 log_debug_errno(r, "Failed to connect to bus, trying again in 5s: %m");
74b2466e
LP
720
721 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);
f647962d
MS
722 if (r < 0)
723 return log_error_errno(r, "Failed to install bus reconnect time event: %m");
74b2466e
LP
724
725 return 0;
726 }
727
4d1cf1e2 728 r = sd_bus_add_object_vtable(m->bus, NULL, "/org/freedesktop/resolve1", "org.freedesktop.resolve1.Manager", resolve_vtable, m);
f647962d
MS
729 if (r < 0)
730 return log_error_errno(r, "Failed to register object: %m");
74b2466e
LP
731
732 r = sd_bus_request_name(m->bus, "org.freedesktop.resolve1", 0);
f647962d
MS
733 if (r < 0)
734 return log_error_errno(r, "Failed to register name: %m");
74b2466e
LP
735
736 r = sd_bus_attach_event(m->bus, m->event, 0);
f647962d
MS
737 if (r < 0)
738 return log_error_errno(r, "Failed to attach bus to event loop: %m");
74b2466e 739
902bb5d8
LP
740 r = sd_bus_add_match(m->bus, &m->prepare_for_sleep_slot,
741 "type='signal',"
742 "sender='org.freedesktop.login1',"
743 "interface='org.freedesktop.login1.Manager',"
744 "member='PrepareForSleep',"
745 "path='/org/freedesktop/login1'",
746 match_prepare_for_sleep,
747 m);
748 if (r < 0)
da927ba9 749 log_error_errno(r, "Failed to add match for PrepareForSleep: %m");
902bb5d8 750
74b2466e
LP
751 return 0;
752}