]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/resolve/resolved-bus.c
resolved: cache stringified transaction key once per transaction
[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
b5efdb8a 22#include "alloc-util.h"
96aad8d1 23#include "bus-common-errors.h"
74b2466e 24#include "bus-util.h"
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
45ec7efb 34 if (q->request_address_valid) {
ad867662
LP
35 r = in_addr_to_string(q->request_family, &q->request_address, &ip);
36 if (r < 0)
37 return r;
74b2466e 38
ad867662 39 name = ip;
45ec7efb 40 } else
703e4f5e 41 name = dns_question_first_name(q->question);
ad867662
LP
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
547973de
LP
63 case DNS_TRANSACTION_DNSSEC_FAILED:
64 return sd_bus_reply_method_errorf(q->request, BUS_ERROR_ABORTED, "DNSSEC validation failed");
65
ec2c5e43 66 case DNS_TRANSACTION_FAILURE: {
4afd3348 67 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
74b2466e 68
faa133f3 69 if (q->answer_rcode == DNS_RCODE_NXDOMAIN)
ad867662 70 sd_bus_error_setf(&error, _BUS_ERROR_DNS "NXDOMAIN", "'%s' not found", name);
74b2466e
LP
71 else {
72 const char *rc, *n;
ad867662 73 char p[3]; /* the rcode is 4 bits long */
74b2466e 74
faa133f3 75 rc = dns_rcode_to_string(q->answer_rcode);
74b2466e 76 if (!rc) {
faa133f3 77 sprintf(p, "%i", q->answer_rcode);
74b2466e
LP
78 rc = p;
79 }
80
63c372cb 81 n = strjoina(_BUS_ERROR_DNS, rc);
ad867662 82 sd_bus_error_setf(&error, n, "Could not resolve '%s', server or network returned error %s", name, rc);
74b2466e
LP
83 }
84
ad867662 85 return sd_bus_reply_method_error(q->request, &error);
74b2466e
LP
86 }
87
ec2c5e43
LP
88 case DNS_TRANSACTION_NULL:
89 case DNS_TRANSACTION_PENDING:
90 case DNS_TRANSACTION_SUCCESS:
8ba9fd9c 91 default:
ad867662
LP
92 assert_not_reached("Impossible state");
93 }
94}
74b2466e 95
78c6a153 96static int append_address(sd_bus_message *reply, DnsResourceRecord *rr, int ifindex) {
8ba9fd9c
LP
97 int r;
98
99 assert(reply);
100 assert(rr);
101
78c6a153
LP
102 r = sd_bus_message_open_container(reply, 'r', "iiay");
103 if (r < 0)
104 return r;
105
106 r = sd_bus_message_append(reply, "i", ifindex);
8ba9fd9c
LP
107 if (r < 0)
108 return r;
109
faa133f3 110 if (rr->key->type == DNS_TYPE_A) {
0dd25fb9 111 r = sd_bus_message_append(reply, "i", AF_INET);
8ba9fd9c
LP
112 if (r < 0)
113 return r;
114
115 r = sd_bus_message_append_array(reply, 'y', &rr->a.in_addr, sizeof(struct in_addr));
faa133f3
LP
116
117 } else if (rr->key->type == DNS_TYPE_AAAA) {
0dd25fb9 118 r = sd_bus_message_append(reply, "i", AF_INET6);
8ba9fd9c
LP
119 if (r < 0)
120 return r;
121
122 r = sd_bus_message_append_array(reply, 'y', &rr->aaaa.in6_addr, sizeof(struct in6_addr));
faa133f3
LP
123 } else
124 return -EAFNOSUPPORT;
125
8ba9fd9c
LP
126 if (r < 0)
127 return r;
128
8ba9fd9c
LP
129 r = sd_bus_message_close_container(reply);
130 if (r < 0)
131 return r;
132
133 return 0;
134}
135
ad867662 136static void bus_method_resolve_hostname_complete(DnsQuery *q) {
45ec7efb 137 _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *canonical = NULL;
4afd3348 138 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
45ec7efb 139 unsigned added = 0;
51323288 140 int r;
74b2466e 141
ad867662 142 assert(q);
74b2466e 143
ec2c5e43 144 if (q->state != DNS_TRANSACTION_SUCCESS) {
ad867662
LP
145 r = reply_query_state(q);
146 goto finish;
147 }
74b2466e 148
45ec7efb
LP
149 r = dns_query_process_cname(q);
150 if (r == -ELOOP) {
703e4f5e 151 r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_CNAME_LOOP, "CNAME loop detected, or CNAME resolving disabled on '%s'", dns_question_first_name(q->question));
45ec7efb
LP
152 goto finish;
153 }
154 if (r < 0)
155 goto finish;
156 if (r > 0) /* This was a cname, and the query was restarted. */
157 return;
158
ad867662
LP
159 r = sd_bus_message_new_method_return(q->request, &reply);
160 if (r < 0)
161 goto finish;
74b2466e 162
78c6a153 163 r = sd_bus_message_open_container(reply, 'a', "(iiay)");
51323288
LP
164 if (r < 0)
165 goto finish;
8ba9fd9c 166
3339cb71 167 if (q->answer) {
45ec7efb
LP
168 DnsResourceRecord *rr;
169 int ifindex;
3339cb71 170
45ec7efb 171 DNS_ANSWER_FOREACH_IFINDEX(rr, ifindex, q->answer) {
801ad6a6 172 r = dns_question_matches_rr(q->question, rr, DNS_SEARCH_DOMAIN_NAME(q->answer_search_domain));
8ba9fd9c 173 if (r < 0)
2d4c5cbc 174 goto finish;
45ec7efb 175 if (r == 0)
3339cb71 176 continue;
74b2466e 177
45ec7efb 178 r = append_address(reply, rr, ifindex);
3339cb71
LP
179 if (r < 0)
180 goto finish;
74b2466e 181
3339cb71 182 if (!canonical)
45ec7efb 183 canonical = dns_resource_record_ref(rr);
309e9d86 184
3339cb71
LP
185 added ++;
186 }
8ba9fd9c 187 }
74b2466e 188
45ec7efb 189 if (added <= 0) {
703e4f5e 190 r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_NO_SUCH_RR, "'%s' does not have any RR of the requested type", dns_question_first_name(q->question));
45ec7efb 191 goto finish;
74b2466e
LP
192 }
193
ad867662
LP
194 r = sd_bus_message_close_container(reply);
195 if (r < 0)
196 goto finish;
197
45ec7efb 198 /* Return the precise spelling and uppercasing and CNAME target reported by the server */
309e9d86 199 assert(canonical);
45ec7efb
LP
200 r = sd_bus_message_append(
201 reply, "st",
202 DNS_RESOURCE_KEY_NAME(canonical->key),
931851e8 203 SD_RESOLVED_FLAGS_MAKE(q->answer_protocol, q->answer_family, q->answer_authenticated));
309e9d86
LP
204 if (r < 0)
205 goto finish;
206
ad867662 207 r = sd_bus_send(q->manager->bus, reply, NULL);
ad867662 208
74b2466e 209finish:
2d4c5cbc 210 if (r < 0) {
da927ba9 211 log_error_errno(r, "Failed to send hostname reply: %m");
45ec7efb 212 sd_bus_reply_method_errno(q->request, r, NULL);
2d4c5cbc 213 }
74b2466e
LP
214
215 dns_query_free(q);
216}
217
45ec7efb 218static int check_ifindex_flags(int ifindex, uint64_t *flags, uint64_t ok, sd_bus_error *error) {
51323288
LP
219 assert(flags);
220
221 if (ifindex < 0)
222 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid interface index");
223
45ec7efb 224 if (*flags & ~(SD_RESOLVED_PROTOCOLS_ALL|SD_RESOLVED_NO_CNAME|ok))
51323288
LP
225 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid flags parameter");
226
45ec7efb
LP
227 if ((*flags & SD_RESOLVED_PROTOCOLS_ALL) == 0) /* If no protocol is enabled, enable all */
228 *flags |= SD_RESOLVED_PROTOCOLS_ALL;
51323288
LP
229
230 return 0;
231}
232
19070062 233static int bus_method_resolve_hostname(sd_bus_message *message, void *userdata, sd_bus_error *error) {
faa133f3 234 _cleanup_(dns_question_unrefp) DnsQuestion *question = NULL;
74b2466e
LP
235 Manager *m = userdata;
236 const char *hostname;
51323288
LP
237 int family, ifindex;
238 uint64_t flags;
74b2466e 239 DnsQuery *q;
74b2466e
LP
240 int r;
241
74b2466e
LP
242 assert(message);
243 assert(m);
244
45ec7efb
LP
245 assert_cc(sizeof(int) == sizeof(int32_t));
246
51323288 247 r = sd_bus_message_read(message, "isit", &ifindex, &hostname, &family, &flags);
74b2466e
LP
248 if (r < 0)
249 return r;
250
251 if (!IN_SET(family, AF_INET, AF_INET6, AF_UNSPEC))
0dd25fb9 252 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown address family %i", family);
74b2466e 253
45ec7efb 254 r = dns_name_is_valid(hostname);
7b9f7afc 255 if (r < 0)
45ec7efb
LP
256 return r;
257 if (r == 0)
74b2466e
LP
258 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid hostname '%s'", hostname);
259
801ad6a6 260 r = check_ifindex_flags(ifindex, &flags, SD_RESOLVED_NO_SEARCH, error);
51323288
LP
261 if (r < 0)
262 return r;
263
45ec7efb
LP
264 r = dns_question_new_address(&question, family, hostname);
265 if (r < 0)
266 return r;
74b2466e 267
51323288 268 r = dns_query_new(m, &q, question, ifindex, flags);
74b2466e
LP
269 if (r < 0)
270 return r;
271
272 q->request = sd_bus_message_ref(message);
273 q->request_family = family;
74b2466e
LP
274 q->complete = bus_method_resolve_hostname_complete;
275
966c66e3 276 r = dns_query_bus_track(q, message);
82bd6ddd 277 if (r < 0)
45ec7efb 278 goto fail;
82bd6ddd 279
322345fd 280 r = dns_query_go(q);
45ec7efb
LP
281 if (r < 0)
282 goto fail;
74b2466e
LP
283
284 return 1;
45ec7efb
LP
285
286fail:
287 dns_query_free(q);
288 return r;
74b2466e
LP
289}
290
291static void bus_method_resolve_address_complete(DnsQuery *q) {
4afd3348 292 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
45ec7efb
LP
293 DnsResourceRecord *rr;
294 unsigned added = 0;
295 int ifindex, r;
74b2466e
LP
296
297 assert(q);
298
ec2c5e43 299 if (q->state != DNS_TRANSACTION_SUCCESS) {
ad867662
LP
300 r = reply_query_state(q);
301 goto finish;
302 }
74b2466e 303
95d46fca
TG
304 r = dns_query_process_cname(q);
305 if (r == -ELOOP) {
039a8725 306 r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_CNAME_LOOP, "CNAME loop detected, or CNAME resolving disabled on '%s'", dns_question_first_name(q->question));
95d46fca
TG
307 goto finish;
308 }
309 if (r < 0)
310 goto finish;
311 if (r > 0) /* This was a cname, and the query was restarted. */
312 return;
45ec7efb 313
ad867662
LP
314 r = sd_bus_message_new_method_return(q->request, &reply);
315 if (r < 0)
316 goto finish;
74b2466e 317
78c6a153 318 r = sd_bus_message_open_container(reply, 'a', "(is)");
ad867662
LP
319 if (r < 0)
320 goto finish;
74b2466e 321
3339cb71 322 if (q->answer) {
45ec7efb 323 DNS_ANSWER_FOREACH_IFINDEX(rr, ifindex, q->answer) {
801ad6a6 324 r = dns_question_matches_rr(q->question, rr, NULL);
3339cb71 325 if (r < 0)
2d4c5cbc 326 goto finish;
3339cb71
LP
327 if (r == 0)
328 continue;
74b2466e 329
45ec7efb 330 r = sd_bus_message_append(reply, "(is)", ifindex, rr->ptr.name);
3339cb71
LP
331 if (r < 0)
332 goto finish;
74b2466e 333
3339cb71
LP
334 added ++;
335 }
ad867662 336 }
74b2466e 337
45ec7efb 338 if (added <= 0) {
ad867662 339 _cleanup_free_ char *ip = NULL;
74b2466e 340
ad867662 341 in_addr_to_string(q->request_family, &q->request_address, &ip);
45ec7efb 342 r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_NO_SUCH_RR, "Address '%s' does not have any RR of requested type", strna(ip));
ad867662 343 goto finish;
74b2466e
LP
344 }
345
ad867662
LP
346 r = sd_bus_message_close_container(reply);
347 if (r < 0)
348 goto finish;
74b2466e 349
931851e8 350 r = sd_bus_message_append(reply, "t", SD_RESOLVED_FLAGS_MAKE(q->answer_protocol, q->answer_family, q->answer_authenticated));
51323288
LP
351 if (r < 0)
352 goto finish;
353
ad867662 354 r = sd_bus_send(q->manager->bus, reply, NULL);
74b2466e
LP
355
356finish:
2d4c5cbc 357 if (r < 0) {
da927ba9 358 log_error_errno(r, "Failed to send address reply: %m");
45ec7efb 359 sd_bus_reply_method_errno(q->request, r, NULL);
2d4c5cbc 360 }
74b2466e
LP
361
362 dns_query_free(q);
363}
364
19070062 365static int bus_method_resolve_address(sd_bus_message *message, void *userdata, sd_bus_error *error) {
faa133f3 366 _cleanup_(dns_question_unrefp) DnsQuestion *question = NULL;
74b2466e 367 Manager *m = userdata;
faa133f3 368 int family, ifindex;
51323288 369 uint64_t flags;
74b2466e 370 const void *d;
74b2466e
LP
371 DnsQuery *q;
372 size_t sz;
373 int r;
374
74b2466e
LP
375 assert(message);
376 assert(m);
377
45ec7efb
LP
378 assert_cc(sizeof(int) == sizeof(int32_t));
379
51323288 380 r = sd_bus_message_read(message, "ii", &ifindex, &family);
74b2466e
LP
381 if (r < 0)
382 return r;
383
384 if (!IN_SET(family, AF_INET, AF_INET6))
0dd25fb9 385 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown address family %i", family);
74b2466e
LP
386
387 r = sd_bus_message_read_array(message, 'y', &d, &sz);
388 if (r < 0)
389 return r;
390
0dd25fb9 391 if (sz != FAMILY_ADDRESS_SIZE(family))
74b2466e
LP
392 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid address size");
393
51323288
LP
394 r = sd_bus_message_read(message, "t", &flags);
395 if (r < 0)
396 return r;
397
45ec7efb 398 r = check_ifindex_flags(ifindex, &flags, 0, error);
faa133f3
LP
399 if (r < 0)
400 return r;
401
45ec7efb 402 r = dns_question_new_reverse(&question, family, d);
74b2466e
LP
403 if (r < 0)
404 return r;
405
801ad6a6 406 r = dns_query_new(m, &q, question, ifindex, flags|SD_RESOLVED_NO_SEARCH);
74b2466e
LP
407 if (r < 0)
408 return r;
409
410 q->request = sd_bus_message_ref(message);
411 q->request_family = family;
412 memcpy(&q->request_address, d, sz);
413 q->complete = bus_method_resolve_address_complete;
414
966c66e3 415 r = dns_query_bus_track(q, message);
82bd6ddd 416 if (r < 0)
45ec7efb 417 goto fail;
82bd6ddd 418
322345fd 419 r = dns_query_go(q);
45ec7efb
LP
420 if (r < 0)
421 goto fail;
74b2466e
LP
422
423 return 1;
45ec7efb
LP
424
425fail:
426 dns_query_free(q);
427 return r;
428}
429
430static int bus_message_append_rr(sd_bus_message *m, DnsResourceRecord *rr, int ifindex) {
45ec7efb
LP
431 int r;
432
433 assert(m);
434 assert(rr);
435
436 r = sd_bus_message_open_container(m, 'r', "iqqay");
437 if (r < 0)
438 return r;
439
440 r = sd_bus_message_append(m, "iqq",
441 ifindex,
442 rr->key->class,
443 rr->key->type);
444 if (r < 0)
445 return r;
446
4e2d538f 447 r = dns_resource_record_to_wire_format(rr, false);
45ec7efb
LP
448 if (r < 0)
449 return r;
450
4e2d538f 451 r = sd_bus_message_append_array(m, 'y', rr->wire_format, rr->wire_format_size);
45ec7efb
LP
452 if (r < 0)
453 return r;
454
455 return sd_bus_message_close_container(m);
74b2466e
LP
456}
457
2d4c5cbc 458static void bus_method_resolve_record_complete(DnsQuery *q) {
4afd3348 459 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
45ec7efb 460 unsigned added = 0;
2d4c5cbc
LP
461 int r;
462
463 assert(q);
464
ec2c5e43 465 if (q->state != DNS_TRANSACTION_SUCCESS) {
2d4c5cbc
LP
466 r = reply_query_state(q);
467 goto finish;
468 }
469
45ec7efb
LP
470 r = dns_query_process_cname(q);
471 if (r == -ELOOP) {
703e4f5e 472 r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_CNAME_LOOP, "CNAME loop detected, or CNAME resolving disabled on '%s'", dns_question_first_name(q->question));
45ec7efb
LP
473 goto finish;
474 }
475 if (r < 0)
476 goto finish;
477 if (r > 0) /* Following a CNAME */
478 return;
479
2d4c5cbc
LP
480 r = sd_bus_message_new_method_return(q->request, &reply);
481 if (r < 0)
482 goto finish;
483
78c6a153 484 r = sd_bus_message_open_container(reply, 'a', "(iqqay)");
2d4c5cbc
LP
485 if (r < 0)
486 goto finish;
487
488 if (q->answer) {
45ec7efb
LP
489 DnsResourceRecord *rr;
490 int ifindex;
2d4c5cbc 491
45ec7efb 492 DNS_ANSWER_FOREACH_IFINDEX(rr, ifindex, q->answer) {
801ad6a6 493 r = dns_question_matches_rr(q->question, rr, NULL);
2d4c5cbc
LP
494 if (r < 0)
495 goto finish;
496 if (r == 0)
497 continue;
498
45ec7efb 499 r = bus_message_append_rr(reply, rr, ifindex);
2d4c5cbc
LP
500 if (r < 0)
501 goto finish;
502
503 added ++;
504 }
505 }
506
507 if (added <= 0) {
703e4f5e 508 r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_NO_SUCH_RR, "Name '%s' does not have any RR of the requested type", dns_question_first_name(q->question));
2d4c5cbc
LP
509 goto finish;
510 }
511
512 r = sd_bus_message_close_container(reply);
513 if (r < 0)
514 goto finish;
515
931851e8 516 r = sd_bus_message_append(reply, "t", SD_RESOLVED_FLAGS_MAKE(q->answer_protocol, q->answer_family, q->answer_authenticated));
51323288
LP
517 if (r < 0)
518 goto finish;
519
2d4c5cbc
LP
520 r = sd_bus_send(q->manager->bus, reply, NULL);
521
522finish:
523 if (r < 0) {
da927ba9 524 log_error_errno(r, "Failed to send record reply: %m");
45ec7efb 525 sd_bus_reply_method_errno(q->request, r, NULL);
2d4c5cbc
LP
526 }
527
528 dns_query_free(q);
529}
530
19070062 531static int bus_method_resolve_record(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2d4c5cbc
LP
532 _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
533 _cleanup_(dns_question_unrefp) DnsQuestion *question = NULL;
2d4c5cbc 534 Manager *m = userdata;
2d4c5cbc
LP
535 uint16_t class, type;
536 const char *name;
51323288
LP
537 int r, ifindex;
538 uint64_t flags;
539 DnsQuery *q;
2d4c5cbc 540
2d4c5cbc
LP
541 assert(message);
542 assert(m);
543
45ec7efb
LP
544 assert_cc(sizeof(int) == sizeof(int32_t));
545
51323288 546 r = sd_bus_message_read(message, "isqqt", &ifindex, &name, &class, &type, &flags);
2d4c5cbc
LP
547 if (r < 0)
548 return r;
549
45ec7efb 550 r = dns_name_is_valid(name);
7b9f7afc 551 if (r < 0)
45ec7efb
LP
552 return r;
553 if (r == 0)
7b9f7afc
LP
554 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid name '%s'", name);
555
c463eb78
LP
556 if (!dns_type_is_valid_query(type))
557 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid RR type for query %" PRIu16, type);
558
45ec7efb 559 r = check_ifindex_flags(ifindex, &flags, 0, error);
51323288
LP
560 if (r < 0)
561 return r;
562
2d4c5cbc
LP
563 question = dns_question_new(1);
564 if (!question)
565 return -ENOMEM;
566
567 key = dns_resource_key_new(class, type, name);
568 if (!key)
569 return -ENOMEM;
570
571 r = dns_question_add(question, key);
572 if (r < 0)
573 return r;
574
801ad6a6 575 r = dns_query_new(m, &q, question, ifindex, flags|SD_RESOLVED_NO_SEARCH);
2d4c5cbc
LP
576 if (r < 0)
577 return r;
578
579 q->request = sd_bus_message_ref(message);
2d4c5cbc
LP
580 q->complete = bus_method_resolve_record_complete;
581
966c66e3 582 r = dns_query_bus_track(q, message);
82bd6ddd 583 if (r < 0)
45ec7efb 584 goto fail;
82bd6ddd 585
2d4c5cbc 586 r = dns_query_go(q);
45ec7efb
LP
587 if (r < 0)
588 goto fail;
589
590 return 1;
591
592fail:
593 dns_query_free(q);
594 return r;
595}
596
597static int append_srv(DnsQuery *q, sd_bus_message *reply, DnsResourceRecord *rr) {
598 _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *canonical = NULL;
599 DnsQuery *aux;
600 int r;
601
602 assert(q);
603 assert(reply);
604 assert(rr);
605 assert(rr->key);
606
607 if (rr->key->type != DNS_TYPE_SRV)
608 return 0;
609
610 if ((q->flags & SD_RESOLVED_NO_ADDRESS) == 0) {
611 /* First, let's see if we could find an appropriate A or AAAA
612 * record for the SRV record */
613 LIST_FOREACH(auxiliary_queries, aux, q->auxiliary_queries) {
614 DnsResourceRecord *zz;
615
616 if (aux->state != DNS_TRANSACTION_SUCCESS)
617 continue;
618 if (aux->auxiliary_result != 0)
619 continue;
620
703e4f5e 621 r = dns_name_equal(dns_question_first_name(aux->question), rr->srv.name);
45ec7efb
LP
622 if (r < 0)
623 return r;
624 if (r == 0)
625 continue;
626
627 DNS_ANSWER_FOREACH(zz, aux->answer) {
628
801ad6a6 629 r = dns_question_matches_rr(aux->question, zz, NULL);
45ec7efb
LP
630 if (r < 0)
631 return r;
632 if (r == 0)
633 continue;
634
635 canonical = dns_resource_record_ref(zz);
636 break;
637 }
638
639 if (canonical)
640 break;
641 }
642
643 /* Is there are successful A/AAAA lookup for this SRV RR? If not, don't add it */
644 if (!canonical)
645 return 0;
646 }
647
648 r = sd_bus_message_open_container(reply, 'r', "qqqsa(iiay)s");
649 if (r < 0)
650 return r;
651
652 r = sd_bus_message_append(
653 reply,
654 "qqqs",
655 rr->srv.priority, rr->srv.weight, rr->srv.port, rr->srv.name);
656 if (r < 0)
657 return r;
658
659 r = sd_bus_message_open_container(reply, 'a', "(iiay)");
660 if (r < 0)
661 return r;
662
663 if ((q->flags & SD_RESOLVED_NO_ADDRESS) == 0) {
664 LIST_FOREACH(auxiliary_queries, aux, q->auxiliary_queries) {
665 DnsResourceRecord *zz;
666 int ifindex;
667
668 if (aux->state != DNS_TRANSACTION_SUCCESS)
669 continue;
670 if (aux->auxiliary_result != 0)
671 continue;
672
703e4f5e 673 r = dns_name_equal(dns_question_first_name(aux->question), rr->srv.name);
45ec7efb
LP
674 if (r < 0)
675 return r;
676 if (r == 0)
677 continue;
678
679 DNS_ANSWER_FOREACH_IFINDEX(zz, ifindex, aux->answer) {
680
801ad6a6 681 r = dns_question_matches_rr(aux->question, zz, NULL);
45ec7efb
LP
682 if (r < 0)
683 return r;
684 if (r == 0)
685 continue;
686
687 r = append_address(reply, zz, ifindex);
688 if (r < 0)
689 return r;
690 }
691 }
692 }
693
694 r = sd_bus_message_close_container(reply);
695 if (r < 0)
696 return r;
697
698 /* Note that above we appended the hostname as encoded in the
699 * SRV, and here the canonical hostname this maps to. */
700 r = sd_bus_message_append(reply, "s", canonical ? DNS_RESOURCE_KEY_NAME(canonical->key) : rr->srv.name);
701 if (r < 0)
702 return r;
703
704 r = sd_bus_message_close_container(reply);
705 if (r < 0)
706 return r;
707
708 return 1;
709}
710
711static int append_txt(sd_bus_message *reply, DnsResourceRecord *rr) {
712 DnsTxtItem *i;
713 int r;
714
715 assert(reply);
716 assert(rr);
717 assert(rr->key);
718
719 if (rr->key->type != DNS_TYPE_TXT)
720 return 0;
721
722 LIST_FOREACH(items, i, rr->txt.items) {
723
724 if (i->length <= 0)
725 continue;
726
727 r = sd_bus_message_append_array(reply, 'y', i->data, i->length);
728 if (r < 0)
729 return r;
730 }
731
732 return 1;
733}
734
735static void resolve_service_all_complete(DnsQuery *q) {
736 _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *canonical = NULL;
737 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
738 _cleanup_free_ char *name = NULL, *type = NULL, *domain = NULL;
739 DnsQuery *aux;
740 unsigned added = false;
741 int r;
742
743 assert(q);
744
745 if (q->block_all_complete > 0)
746 return;
747
748 if ((q->flags & SD_RESOLVED_NO_ADDRESS) == 0) {
749 DnsQuery *bad = NULL;
750 bool have_success = false;
751
752 LIST_FOREACH(auxiliary_queries, aux, q->auxiliary_queries) {
753
754 switch (aux->state) {
755
756 case DNS_TRANSACTION_PENDING:
757 /* If an auxiliary query is still pending, let's wait */
758 return;
759
760 case DNS_TRANSACTION_SUCCESS:
761 if (aux->auxiliary_result == 0)
762 have_success = true;
763 else
764 bad = aux;
765 break;
766
767 default:
768 bad = aux;
769 break;
770 }
771 }
772
773 if (!have_success) {
774 /* We can only return one error, hence pick the last error we encountered */
775
776 assert(bad);
777
778 if (bad->state == DNS_TRANSACTION_SUCCESS) {
779 assert(bad->auxiliary_result != 0);
780
781 if (bad->auxiliary_result == -ELOOP) {
703e4f5e 782 r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_CNAME_LOOP, "CNAME loop detected, or CNAME resolving disabled on '%s'", dns_question_first_name(bad->question));
45ec7efb
LP
783 goto finish;
784 }
785
786 r = bad->auxiliary_result;
787 goto finish;
788 }
789
790 r = reply_query_state(bad);
791 goto finish;
792 }
793 }
794
795 r = sd_bus_message_new_method_return(q->request, &reply);
796 if (r < 0)
797 goto finish;
798
799 r = sd_bus_message_open_container(reply, 'a', "(qqqsa(iiay)s)");
800 if (r < 0)
801 goto finish;
802
803 if (q->answer) {
804 DnsResourceRecord *rr;
805
806 DNS_ANSWER_FOREACH(rr, q->answer) {
801ad6a6 807 r = dns_question_matches_rr(q->question, rr, NULL);
45ec7efb
LP
808 if (r < 0)
809 goto finish;
810 if (r == 0)
811 continue;
812
813 r = append_srv(q, reply, rr);
814 if (r < 0)
815 goto finish;
816 if (r == 0) /* not an SRV record */
817 continue;
818
819 if (!canonical)
820 canonical = dns_resource_record_ref(rr);
821
822 added++;
823 }
824 }
825
826 if (added <= 0) {
703e4f5e 827 r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_NO_SUCH_RR, "'%s' does not have any RR of the requested type", dns_question_first_name(q->question));
45ec7efb
LP
828 goto finish;
829 }
830
831 r = sd_bus_message_close_container(reply);
832 if (r < 0)
833 goto finish;
834
835 r = sd_bus_message_open_container(reply, 'a', "ay");
836 if (r < 0)
837 goto finish;
838
839 if (q->answer) {
840 DnsResourceRecord *rr;
841
842 DNS_ANSWER_FOREACH(rr, q->answer) {
801ad6a6 843 r = dns_question_matches_rr(q->question, rr, NULL);
45ec7efb
LP
844 if (r < 0)
845 goto finish;
846 if (r == 0)
847 continue;
848
849 r = append_txt(reply, rr);
850 if (r < 0)
851 goto finish;
852 }
853 }
854
855 r = sd_bus_message_close_container(reply);
856 if (r < 0)
857 goto finish;
858
859 assert(canonical);
860 r = dns_service_split(DNS_RESOURCE_KEY_NAME(canonical->key), &name, &type, &domain);
861 if (r < 0)
862 goto finish;
863
864 r = sd_bus_message_append(
865 reply,
866 "ssst",
867 name, type, domain,
931851e8 868 SD_RESOLVED_FLAGS_MAKE(q->answer_protocol, q->answer_family, q->answer_authenticated));
45ec7efb
LP
869 if (r < 0)
870 goto finish;
871
872 r = sd_bus_send(q->manager->bus, reply, NULL);
873
874finish:
875 if (r < 0) {
876 log_error_errno(r, "Failed to send service reply: %m");
877 sd_bus_reply_method_errno(q->request, r, NULL);
878 }
879
880 dns_query_free(q);
881}
882
883static void resolve_service_hostname_complete(DnsQuery *q) {
884 int r;
885
886 assert(q);
887 assert(q->auxiliary_for);
888
889 if (q->state != DNS_TRANSACTION_SUCCESS) {
890 resolve_service_all_complete(q->auxiliary_for);
891 return;
892 }
893
894 r = dns_query_process_cname(q);
895 if (r > 0) /* This was a cname, and the query was restarted. */
896 return;
897
898 /* This auxiliary lookup is finished or failed, let's see if all are finished now. */
899 q->auxiliary_result = r;
900 resolve_service_all_complete(q->auxiliary_for);
901}
902
903static int resolve_service_hostname(DnsQuery *q, DnsResourceRecord *rr, int ifindex) {
904 _cleanup_(dns_question_unrefp) DnsQuestion *question = NULL;
905 DnsQuery *aux;
906 int r;
907
908 assert(q);
909 assert(rr);
910 assert(rr->key);
911 assert(rr->key->type == DNS_TYPE_SRV);
912
913 /* OK, we found an SRV record for the service. Let's resolve
914 * the hostname included in it */
915
916 r = dns_question_new_address(&question, q->request_family, rr->srv.name);
917 if (r < 0)
918 return r;
919
801ad6a6 920 r = dns_query_new(q->manager, &aux, question, ifindex, q->flags|SD_RESOLVED_NO_SEARCH);
45ec7efb
LP
921 if (r < 0)
922 return r;
923
924 aux->request_family = q->request_family;
925 aux->complete = resolve_service_hostname_complete;
926
927 r = dns_query_make_auxiliary(aux, q);
928 if (r == -EAGAIN) {
929 /* Too many auxiliary lookups? If so, don't complain,
930 * let's just not add this one, we already have more
931 * than enough */
932
933 dns_query_free(aux);
934 return 0;
935 }
936 if (r < 0)
937 goto fail;
938
939 /* Note that auxiliary queries do not track the original bus
940 * client, only the primary request does that. */
941
942 r = dns_query_go(aux);
943 if (r < 0)
944 goto fail;
945
946 return 1;
947
948fail:
949 dns_query_free(aux);
950 return r;
951}
952
953static void bus_method_resolve_service_complete(DnsQuery *q) {
954 unsigned found = 0;
955 int r;
956
957 assert(q);
958
959 if (q->state != DNS_TRANSACTION_SUCCESS) {
960 r = reply_query_state(q);
961 goto finish;
962 }
963
964 r = dns_query_process_cname(q);
965 if (r == -ELOOP) {
703e4f5e 966 r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_CNAME_LOOP, "CNAME loop detected, or CNAME resolving disabled on '%s'", dns_question_first_name(q->question));
45ec7efb
LP
967 goto finish;
968 }
969 if (r < 0)
970 goto finish;
971 if (r > 0) /* This was a cname, and the query was restarted. */
972 return;
973
974 if (q->answer) {
975 DnsResourceRecord *rr;
976 int ifindex;
977
978 DNS_ANSWER_FOREACH_IFINDEX(rr, ifindex, q->answer) {
801ad6a6 979 r = dns_question_matches_rr(q->question, rr, NULL);
45ec7efb
LP
980 if (r < 0)
981 goto finish;
982 if (r == 0)
983 continue;
984
985 if (rr->key->type != DNS_TYPE_SRV)
986 continue;
987
988 if ((q->flags & SD_RESOLVED_NO_ADDRESS) == 0) {
989 q->block_all_complete ++;
990 r = resolve_service_hostname(q, rr, ifindex);
991 q->block_all_complete --;
992
993 if (r < 0)
994 goto finish;
995 }
996
997 found++;
998 }
999 }
1000
1001 if (found <= 0) {
703e4f5e 1002 r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_NO_SUCH_RR, "'%s' does not have any RR of the requested type", dns_question_first_name(q->question));
45ec7efb
LP
1003 goto finish;
1004 }
1005
1006 /* Maybe we are already finished? check now... */
1007 resolve_service_all_complete(q);
1008 return;
1009
1010finish:
2d4c5cbc 1011 if (r < 0) {
45ec7efb
LP
1012 log_error_errno(r, "Failed to send service reply: %m");
1013 sd_bus_reply_method_errno(q->request, r, NULL);
1014 }
1015
1016 dns_query_free(q);
1017}
1018
1019static int bus_method_resolve_service(sd_bus_message *message, void *userdata, sd_bus_error *error) {
45ec7efb
LP
1020 _cleanup_(dns_question_unrefp) DnsQuestion *question = NULL;
1021 const char *name, *type, *domain, *joined;
1022 _cleanup_free_ char *n = NULL;
1023 Manager *m = userdata;
1024 int family, ifindex;
1025 uint64_t flags;
1026 DnsQuery *q;
1027 int r;
1028
1029 assert(message);
1030 assert(m);
1031
1032 assert_cc(sizeof(int) == sizeof(int32_t));
1033
1034 r = sd_bus_message_read(message, "isssit", &ifindex, &name, &type, &domain, &family, &flags);
1035 if (r < 0)
2d4c5cbc 1036 return r;
45ec7efb
LP
1037
1038 if (!IN_SET(family, AF_INET, AF_INET6, AF_UNSPEC))
1039 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown address family %i", family);
1040
1041 if (isempty(name))
1042 name = NULL;
1043 else {
1044 if (!dns_service_name_is_valid(name))
1045 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid service name '%s'", name);
2d4c5cbc
LP
1046 }
1047
45ec7efb
LP
1048 if (isempty(type))
1049 type = NULL;
7e8131e9
LP
1050 else if (!dns_srv_type_is_valid(type))
1051 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid SRV service type '%s'", type);
45ec7efb
LP
1052
1053 r = dns_name_is_valid(domain);
1054 if (r < 0)
1055 return r;
1056 if (r == 0)
1057 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid domain '%s'", domain);
1058
1059 if (name && !type)
1060 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Service name cannot be specified without service type.");
1061
1062 r = check_ifindex_flags(ifindex, &flags, SD_RESOLVED_NO_TXT|SD_RESOLVED_NO_ADDRESS, error);
1063 if (r < 0)
1064 return r;
1065
1066 if (type) {
1067 /* If the type is specified, we generate the full domain name to look up ourselves */
1068 r = dns_service_join(name, type, domain, &n);
1069 if (r < 0)
1070 return r;
1071
1072 joined = n;
1073 } else
1074 /* If no type is specified, we assume the domain
1075 * contains the full domain name to lookup already */
1076 joined = domain;
1077
1078 r = dns_question_new_service(&question, joined, !(flags & SD_RESOLVED_NO_TXT));
1079 if (r < 0)
1080 return r;
1081
801ad6a6 1082 r = dns_query_new(m, &q, question, ifindex, flags|SD_RESOLVED_NO_SEARCH);
45ec7efb
LP
1083 if (r < 0)
1084 return r;
1085
1086 q->request = sd_bus_message_ref(message);
1087 q->request_family = family;
1088 q->complete = bus_method_resolve_service_complete;
1089
1090 r = dns_query_bus_track(q, message);
1091 if (r < 0)
1092 goto fail;
1093
1094 r = dns_query_go(q);
1095 if (r < 0)
1096 goto fail;
1097
2d4c5cbc 1098 return 1;
45ec7efb
LP
1099
1100fail:
1101 dns_query_free(q);
1102 return r;
2d4c5cbc
LP
1103}
1104
7f220d94
LP
1105static int append_dns_server(sd_bus_message *reply, DnsServer *s) {
1106 int r;
1107
1108 assert(reply);
1109 assert(s);
1110
1111 r = sd_bus_message_open_container(reply, 'r', "iiay");
1112 if (r < 0)
1113 return r;
1114
1115 r = sd_bus_message_append(reply, "ii", s->link ? s->link->ifindex : 0, s->family);
1116 if (r < 0)
1117 return r;
1118
1119 r = sd_bus_message_append_array(reply, 'y', &s->address, FAMILY_ADDRESS_SIZE(s->family));
1120 if (r < 0)
1121 return r;
1122
1123 return sd_bus_message_close_container(reply);
1124}
1125
1126static int bus_property_get_dns_servers(
1127 sd_bus *bus,
1128 const char *path,
1129 const char *interface,
1130 const char *property,
1131 sd_bus_message *reply,
1132 void *userdata,
1133 sd_bus_error *error) {
1134
1135 Manager *m = userdata;
1136 unsigned c = 0;
1137 DnsServer *s;
1138 Iterator i;
1139 Link *l;
1140 int r;
1141
1142 assert(reply);
1143 assert(m);
1144
1145 r = sd_bus_message_open_container(reply, 'a', "(iiay)");
1146 if (r < 0)
1147 return r;
1148
1149 LIST_FOREACH(servers, s, m->dns_servers) {
1150 r = append_dns_server(reply, s);
1151 if (r < 0)
1152 return r;
1153
1154 c++;
1155 }
1156
1157 HASHMAP_FOREACH(l, m->links, i) {
1158 LIST_FOREACH(servers, s, l->dns_servers) {
1159 r = append_dns_server(reply, s);
1160 if (r < 0)
1161 return r;
1162 c++;
1163 }
1164 }
1165
1166 if (c == 0) {
1167 LIST_FOREACH(servers, s, m->fallback_dns_servers) {
1168 r = append_dns_server(reply, s);
1169 if (r < 0)
1170 return r;
1171 }
1172 }
1173
1174 return sd_bus_message_close_container(reply);
1175}
1176
1177static int bus_property_get_search_domains(
1178 sd_bus *bus,
1179 const char *path,
1180 const char *interface,
1181 const char *property,
1182 sd_bus_message *reply,
1183 void *userdata,
1184 sd_bus_error *error) {
1185
1186 Manager *m = userdata;
1187 DnsSearchDomain *d;
1188 Iterator i;
1189 Link *l;
1190 int r;
1191
1192 assert(reply);
1193 assert(m);
1194
1195 r = sd_bus_message_open_container(reply, 'a', "(is)");
1196 if (r < 0)
1197 return r;
1198
1199 LIST_FOREACH(domains, d, m->search_domains) {
1200 r = sd_bus_message_append(reply, "(is)", 0, d->name);
1201 if (r < 0)
1202 return r;
1203 }
1204
1205 HASHMAP_FOREACH(l, m->links, i) {
1206 LIST_FOREACH(domains, d, l->search_domains) {
1207 r = sd_bus_message_append(reply, "is", l->ifindex, d->name);
1208 if (r < 0)
1209 return r;
1210 }
1211 }
1212
1213 return sd_bus_message_close_container(reply);
1214}
1215
74b2466e
LP
1216static const sd_bus_vtable resolve_vtable[] = {
1217 SD_BUS_VTABLE_START(0),
7f220d94
LP
1218 SD_BUS_PROPERTY("LLMNRHostname", "s", NULL, offsetof(Manager, llmnr_hostname), 0),
1219 SD_BUS_PROPERTY("DNSServers", "a(iiay)", bus_property_get_dns_servers, 0, 0),
1220 SD_BUS_PROPERTY("SearchDomains", "a(is)", bus_property_get_search_domains, 0, 0),
1221
78c6a153
LP
1222 SD_BUS_METHOD("ResolveHostname", "isit", "a(iiay)st", bus_method_resolve_hostname, SD_BUS_VTABLE_UNPRIVILEGED),
1223 SD_BUS_METHOD("ResolveAddress", "iiayt", "a(is)t", bus_method_resolve_address, SD_BUS_VTABLE_UNPRIVILEGED),
1224 SD_BUS_METHOD("ResolveRecord", "isqqt", "a(iqqay)t", bus_method_resolve_record, SD_BUS_VTABLE_UNPRIVILEGED),
45ec7efb 1225 SD_BUS_METHOD("ResolveService", "isssit", "a(qqqsa(iiay)s)aayssst", bus_method_resolve_service, SD_BUS_VTABLE_UNPRIVILEGED),
74b2466e
LP
1226 SD_BUS_VTABLE_END,
1227};
1228
1229static int on_bus_retry(sd_event_source *s, usec_t usec, void *userdata) {
1230 Manager *m = userdata;
1231
1232 assert(s);
1233 assert(m);
1234
1235 m->bus_retry_event_source = sd_event_source_unref(m->bus_retry_event_source);
1236
1237 manager_connect_bus(m);
1238 return 0;
1239}
1240
19070062 1241static int match_prepare_for_sleep(sd_bus_message *message, void *userdata, sd_bus_error *ret_error) {
902bb5d8
LP
1242 Manager *m = userdata;
1243 int b, r;
1244
19070062
LP
1245 assert(message);
1246 assert(m);
902bb5d8
LP
1247
1248 r = sd_bus_message_read(message, "b", &b);
1249 if (r < 0) {
da927ba9 1250 log_debug_errno(r, "Failed to parse PrepareForSleep signal: %m");
902bb5d8
LP
1251 return 0;
1252 }
1253
1254 if (b)
1255 return 0;
1256
1257 log_debug("Coming back from suspend, verifying all RRs...");
1258
1259 manager_verify_all(m);
1260 return 0;
1261}
1262
74b2466e
LP
1263int manager_connect_bus(Manager *m) {
1264 int r;
1265
1266 assert(m);
1267
1268 if (m->bus)
1269 return 0;
1270
1271 r = sd_bus_default_system(&m->bus);
1272 if (r < 0) {
1273 /* We failed to connect? Yuck, we must be in early
1274 * boot. Let's try in 5s again. As soon as we have
1275 * kdbus we can stop doing this... */
1276
da927ba9 1277 log_debug_errno(r, "Failed to connect to bus, trying again in 5s: %m");
74b2466e
LP
1278
1279 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
1280 if (r < 0)
1281 return log_error_errno(r, "Failed to install bus reconnect time event: %m");
74b2466e
LP
1282
1283 return 0;
1284 }
1285
4d1cf1e2 1286 r = sd_bus_add_object_vtable(m->bus, NULL, "/org/freedesktop/resolve1", "org.freedesktop.resolve1.Manager", resolve_vtable, m);
f647962d
MS
1287 if (r < 0)
1288 return log_error_errno(r, "Failed to register object: %m");
74b2466e
LP
1289
1290 r = sd_bus_request_name(m->bus, "org.freedesktop.resolve1", 0);
f647962d
MS
1291 if (r < 0)
1292 return log_error_errno(r, "Failed to register name: %m");
74b2466e
LP
1293
1294 r = sd_bus_attach_event(m->bus, m->event, 0);
f647962d
MS
1295 if (r < 0)
1296 return log_error_errno(r, "Failed to attach bus to event loop: %m");
74b2466e 1297
902bb5d8
LP
1298 r = sd_bus_add_match(m->bus, &m->prepare_for_sleep_slot,
1299 "type='signal',"
1300 "sender='org.freedesktop.login1',"
1301 "interface='org.freedesktop.login1.Manager',"
1302 "member='PrepareForSleep',"
1303 "path='/org/freedesktop/login1'",
1304 match_prepare_for_sleep,
1305 m);
1306 if (r < 0)
da927ba9 1307 log_error_errno(r, "Failed to add match for PrepareForSleep: %m");
902bb5d8 1308
74b2466e
LP
1309 return 0;
1310}