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