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