]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/resolve/resolved-bus.c
dns-domain: add code for verifying validity of DNS-SD service names and types
[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
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
78c6a153 94static int append_address(sd_bus_message *reply, DnsResourceRecord *rr, int ifindex) {
8ba9fd9c
LP
95 int r;
96
97 assert(reply);
98 assert(rr);
99
78c6a153
LP
100 r = sd_bus_message_open_container(reply, 'r', "iiay");
101 if (r < 0)
102 return r;
103
104 r = sd_bus_message_append(reply, "i", ifindex);
8ba9fd9c
LP
105 if (r < 0)
106 return r;
107
faa133f3 108 if (rr->key->type == DNS_TYPE_A) {
0dd25fb9 109 r = sd_bus_message_append(reply, "i", AF_INET);
8ba9fd9c
LP
110 if (r < 0)
111 return r;
112
113 r = sd_bus_message_append_array(reply, 'y', &rr->a.in_addr, sizeof(struct in_addr));
faa133f3
LP
114
115 } else if (rr->key->type == DNS_TYPE_AAAA) {
0dd25fb9 116 r = sd_bus_message_append(reply, "i", AF_INET6);
8ba9fd9c
LP
117 if (r < 0)
118 return r;
119
120 r = sd_bus_message_append_array(reply, 'y', &rr->aaaa.in6_addr, sizeof(struct in6_addr));
faa133f3
LP
121 } else
122 return -EAFNOSUPPORT;
123
8ba9fd9c
LP
124 if (r < 0)
125 return r;
126
8ba9fd9c
LP
127 r = sd_bus_message_close_container(reply);
128 if (r < 0)
129 return r;
130
131 return 0;
132}
133
ad867662 134static void bus_method_resolve_hostname_complete(DnsQuery *q) {
309e9d86 135 _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *cname = NULL, *canonical = NULL;
ad867662 136 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
faa133f3
LP
137 _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL;
138 unsigned added = 0, i;
51323288 139 int r;
74b2466e 140
ad867662 141 assert(q);
74b2466e 142
ec2c5e43 143 if (q->state != DNS_TRANSACTION_SUCCESS) {
ad867662
LP
144 r = reply_query_state(q);
145 goto finish;
146 }
74b2466e 147
ad867662
LP
148 r = sd_bus_message_new_method_return(q->request, &reply);
149 if (r < 0)
150 goto finish;
74b2466e 151
78c6a153 152 r = sd_bus_message_open_container(reply, 'a', "(iiay)");
51323288
LP
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++) {
78c6a153 160 r = dns_question_matches_rr(q->question, answer->items[i].rr);
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 */
78c6a153 166 r = dns_question_matches_cname(q->question, answer->items[i].rr);
3339cb71 167 if (r < 0)
2d4c5cbc 168 goto finish;
3339cb71 169 if (r > 0)
78c6a153 170 cname = dns_resource_record_ref(answer->items[i].rr);
74b2466e 171
3339cb71
LP
172 continue;
173 }
74b2466e 174
78c6a153 175 r = append_address(reply, answer->items[i].rr, answer->items[i].ifindex);
3339cb71
LP
176 if (r < 0)
177 goto finish;
74b2466e 178
3339cb71 179 if (!canonical)
78c6a153 180 canonical = dns_resource_record_ref(answer->items[i].rr);
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. */
36d9205d 194 r = dns_query_cname_redirect(q, cname);
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 206 for (i = 0; i < answer->n_rrs; i++) {
78c6a153 207 r = dns_question_matches_rr(q->question, answer->items[i].rr);
8ba9fd9c 208 if (r < 0)
2d4c5cbc 209 goto finish;
8ba9fd9c
LP
210 if (r == 0)
211 continue;
212
78c6a153 213 r = append_address(reply, answer->items[i].rr, answer->items[i].ifindex);
8ba9fd9c
LP
214 if (r < 0)
215 goto finish;
216
309e9d86 217 if (!canonical)
78c6a153 218 canonical = dns_resource_record_ref(answer->items[i].rr);
309e9d86 219
8ba9fd9c
LP
220 added++;
221 }
222
223 /* If we didn't find anything, then let's restart the
224 * query, this time with the cname */
225 if (added <= 0) {
322345fd 226 r = dns_query_go(q);
8ba9fd9c
LP
227 if (r < 0) {
228 r = sd_bus_reply_method_errno(q->request, -r, NULL);
229 goto finish;
230 }
2d4c5cbc 231
8ba9fd9c
LP
232 return;
233 }
74b2466e
LP
234 }
235
ad867662
LP
236 r = sd_bus_message_close_container(reply);
237 if (r < 0)
238 goto finish;
239
309e9d86
LP
240 /* Return the precise spelling and uppercasing reported by the server */
241 assert(canonical);
51323288 242 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
243 if (r < 0)
244 goto finish;
245
ad867662 246 r = sd_bus_send(q->manager->bus, reply, NULL);
ad867662 247
74b2466e 248finish:
2d4c5cbc 249 if (r < 0) {
da927ba9 250 log_error_errno(r, "Failed to send hostname reply: %m");
2d4c5cbc
LP
251 sd_bus_reply_method_errno(q->request, -r, NULL);
252 }
74b2466e
LP
253
254 dns_query_free(q);
255}
256
51323288
LP
257static int check_ifindex_flags(int ifindex, uint64_t *flags, sd_bus_error *error) {
258 assert(flags);
259
260 if (ifindex < 0)
261 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid interface index");
262
263 if (*flags & ~SD_RESOLVED_FLAGS_ALL)
264 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid flags parameter");
265
266 if (*flags == 0)
267 *flags = SD_RESOLVED_FLAGS_DEFAULT;
268
269 return 0;
270}
271
19070062 272static int bus_method_resolve_hostname(sd_bus_message *message, void *userdata, sd_bus_error *error) {
faa133f3 273 _cleanup_(dns_question_unrefp) DnsQuestion *question = NULL;
74b2466e
LP
274 Manager *m = userdata;
275 const char *hostname;
51323288
LP
276 int family, ifindex;
277 uint64_t flags;
74b2466e 278 DnsQuery *q;
74b2466e
LP
279 int r;
280
74b2466e
LP
281 assert(message);
282 assert(m);
283
51323288 284 r = sd_bus_message_read(message, "isit", &ifindex, &hostname, &family, &flags);
74b2466e
LP
285 if (r < 0)
286 return r;
287
288 if (!IN_SET(family, AF_INET, AF_INET6, AF_UNSPEC))
0dd25fb9 289 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown address family %i", family);
74b2466e 290
7b9f7afc
LP
291 r = dns_name_normalize(hostname, NULL);
292 if (r < 0)
74b2466e
LP
293 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid hostname '%s'", hostname);
294
51323288
LP
295 r = check_ifindex_flags(ifindex, &flags, error);
296 if (r < 0)
297 return r;
298
faa133f3
LP
299 question = dns_question_new(family == AF_UNSPEC ? 2 : 1);
300 if (!question)
301 return -ENOMEM;
302
74b2466e 303 if (family != AF_INET6) {
faa133f3
LP
304 _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
305
306 key = dns_resource_key_new(DNS_CLASS_IN, DNS_TYPE_A, hostname);
307 if (!key)
308 return -ENOMEM;
309
310 r = dns_question_add(question, key);
311 if (r < 0)
312 return r;
74b2466e
LP
313 }
314
315 if (family != AF_INET) {
faa133f3
LP
316 _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
317
318 key = dns_resource_key_new(DNS_CLASS_IN, DNS_TYPE_AAAA, hostname);
319 if (!key)
320 return -ENOMEM;
321
322 r = dns_question_add(question, key);
323 if (r < 0)
324 return r;
74b2466e
LP
325 }
326
51323288 327 r = dns_query_new(m, &q, question, ifindex, flags);
74b2466e
LP
328 if (r < 0)
329 return r;
330
331 q->request = sd_bus_message_ref(message);
332 q->request_family = family;
333 q->request_hostname = hostname;
334 q->complete = bus_method_resolve_hostname_complete;
335
966c66e3 336 r = dns_query_bus_track(q, message);
82bd6ddd
LP
337 if (r < 0)
338 return r;
339
322345fd 340 r = dns_query_go(q);
74b2466e
LP
341 if (r < 0) {
342 dns_query_free(q);
343 return r;
344 }
345
346 return 1;
347}
348
349static void bus_method_resolve_address_complete(DnsQuery *q) {
ad867662 350 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
faa133f3
LP
351 _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL;
352 unsigned added = 0, i;
353 int r;
74b2466e
LP
354
355 assert(q);
356
ec2c5e43 357 if (q->state != DNS_TRANSACTION_SUCCESS) {
ad867662
LP
358 r = reply_query_state(q);
359 goto finish;
360 }
74b2466e 361
ad867662
LP
362 r = sd_bus_message_new_method_return(q->request, &reply);
363 if (r < 0)
364 goto finish;
74b2466e 365
78c6a153 366 r = sd_bus_message_open_container(reply, 'a', "(is)");
ad867662
LP
367 if (r < 0)
368 goto finish;
74b2466e 369
3339cb71
LP
370 if (q->answer) {
371 answer = dns_answer_ref(q->answer);
faa133f3 372
3339cb71 373 for (i = 0; i < answer->n_rrs; i++) {
78c6a153 374 r = dns_question_matches_rr(q->question, answer->items[i].rr);
3339cb71 375 if (r < 0)
2d4c5cbc 376 goto finish;
3339cb71
LP
377 if (r == 0)
378 continue;
74b2466e 379
78c6a153 380 r = sd_bus_message_append(reply, "(is)", answer->items[i].ifindex, answer->items[i].rr->ptr.name);
3339cb71
LP
381 if (r < 0)
382 goto finish;
74b2466e 383
3339cb71
LP
384 added ++;
385 }
ad867662 386 }
74b2466e 387
657dbed2 388 if (added == 0) {
ad867662 389 _cleanup_free_ char *ip = NULL;
74b2466e 390
ad867662 391 in_addr_to_string(q->request_family, &q->request_address, &ip);
74b2466e 392
309e9d86 393 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 394 goto finish;
74b2466e
LP
395 }
396
ad867662
LP
397 r = sd_bus_message_close_container(reply);
398 if (r < 0)
399 goto finish;
74b2466e 400
51323288
LP
401 r = sd_bus_message_append(reply, "t", SD_RESOLVED_FLAGS_MAKE(q->answer_protocol, q->answer_family));
402 if (r < 0)
403 goto finish;
404
ad867662 405 r = sd_bus_send(q->manager->bus, reply, NULL);
74b2466e
LP
406
407finish:
2d4c5cbc 408 if (r < 0) {
da927ba9 409 log_error_errno(r, "Failed to send address reply: %m");
2d4c5cbc
LP
410 sd_bus_reply_method_errno(q->request, -r, NULL);
411 }
74b2466e
LP
412
413 dns_query_free(q);
414}
415
19070062 416static int bus_method_resolve_address(sd_bus_message *message, void *userdata, sd_bus_error *error) {
faa133f3
LP
417 _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
418 _cleanup_(dns_question_unrefp) DnsQuestion *question = NULL;
419 _cleanup_free_ char *reverse = NULL;
74b2466e 420 Manager *m = userdata;
faa133f3 421 int family, ifindex;
51323288 422 uint64_t flags;
74b2466e 423 const void *d;
74b2466e
LP
424 DnsQuery *q;
425 size_t sz;
426 int r;
427
74b2466e
LP
428 assert(message);
429 assert(m);
430
51323288 431 r = sd_bus_message_read(message, "ii", &ifindex, &family);
74b2466e
LP
432 if (r < 0)
433 return r;
434
435 if (!IN_SET(family, AF_INET, AF_INET6))
0dd25fb9 436 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown address family %i", family);
74b2466e
LP
437
438 r = sd_bus_message_read_array(message, 'y', &d, &sz);
439 if (r < 0)
440 return r;
441
0dd25fb9 442 if (sz != FAMILY_ADDRESS_SIZE(family))
74b2466e
LP
443 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid address size");
444
51323288
LP
445 r = sd_bus_message_read(message, "t", &flags);
446 if (r < 0)
447 return r;
448
449 r = check_ifindex_flags(ifindex, &flags, error);
74b2466e
LP
450 if (r < 0)
451 return r;
74b2466e 452
faa133f3
LP
453 r = dns_name_reverse(family, d, &reverse);
454 if (r < 0)
455 return r;
456
457 question = dns_question_new(1);
458 if (!question)
459 return -ENOMEM;
460
461 key = dns_resource_key_new_consume(DNS_CLASS_IN, DNS_TYPE_PTR, reverse);
462 if (!key)
463 return -ENOMEM;
464
465 reverse = NULL;
466
467 r = dns_question_add(question, key);
74b2466e
LP
468 if (r < 0)
469 return r;
470
51323288 471 r = dns_query_new(m, &q, question, ifindex, flags);
74b2466e
LP
472 if (r < 0)
473 return r;
474
475 q->request = sd_bus_message_ref(message);
476 q->request_family = family;
477 memcpy(&q->request_address, d, sz);
478 q->complete = bus_method_resolve_address_complete;
479
966c66e3 480 r = dns_query_bus_track(q, message);
82bd6ddd
LP
481 if (r < 0)
482 return r;
483
322345fd 484 r = dns_query_go(q);
74b2466e
LP
485 if (r < 0) {
486 dns_query_free(q);
487 return r;
488 }
489
490 return 1;
491}
492
2d4c5cbc
LP
493static void bus_method_resolve_record_complete(DnsQuery *q) {
494 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
495 _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL;
496 unsigned added = 0, i;
497 int r;
498
499 assert(q);
500
ec2c5e43 501 if (q->state != DNS_TRANSACTION_SUCCESS) {
2d4c5cbc
LP
502 r = reply_query_state(q);
503 goto finish;
504 }
505
506 r = sd_bus_message_new_method_return(q->request, &reply);
507 if (r < 0)
508 goto finish;
509
78c6a153 510 r = sd_bus_message_open_container(reply, 'a', "(iqqay)");
2d4c5cbc
LP
511 if (r < 0)
512 goto finish;
513
514 if (q->answer) {
515 answer = dns_answer_ref(q->answer);
516
517 for (i = 0; i < answer->n_rrs; i++) {
518 _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
519 size_t start;
520
78c6a153 521 r = dns_question_matches_rr(q->question, answer->items[i].rr);
2d4c5cbc
LP
522 if (r < 0)
523 goto finish;
524 if (r == 0)
525 continue;
526
527 r = dns_packet_new(&p, DNS_PROTOCOL_DNS, 0);
528 if (r < 0)
529 goto finish;
530
f6a5fec6
LP
531 p->refuse_compression = true;
532
78c6a153 533 r = dns_packet_append_rr(p, answer->items[i].rr, &start);
2d4c5cbc
LP
534 if (r < 0)
535 goto finish;
536
78c6a153 537 r = sd_bus_message_open_container(reply, 'r', "iqqay");
2d4c5cbc
LP
538 if (r < 0)
539 goto finish;
540
78c6a153
LP
541 r = sd_bus_message_append(reply, "iqq",
542 answer->items[i].ifindex,
543 answer->items[i].rr->key->class,
544 answer->items[i].rr->key->type);
2d4c5cbc
LP
545 if (r < 0)
546 goto finish;
547
548 r = sd_bus_message_append_array(reply, 'y', DNS_PACKET_DATA(p) + start, p->size - start);
549 if (r < 0)
550 goto finish;
551
552 r = sd_bus_message_close_container(reply);
553 if (r < 0)
554 goto finish;
555
556 added ++;
557 }
558 }
559
560 if (added <= 0) {
561 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);
562 goto finish;
563 }
564
565 r = sd_bus_message_close_container(reply);
566 if (r < 0)
567 goto finish;
568
51323288
LP
569 r = sd_bus_message_append(reply, "t", SD_RESOLVED_FLAGS_MAKE(q->answer_protocol, q->answer_family));
570 if (r < 0)
571 goto finish;
572
2d4c5cbc
LP
573 r = sd_bus_send(q->manager->bus, reply, NULL);
574
575finish:
576 if (r < 0) {
da927ba9 577 log_error_errno(r, "Failed to send record reply: %m");
2d4c5cbc
LP
578 sd_bus_reply_method_errno(q->request, -r, NULL);
579 }
580
581 dns_query_free(q);
582}
583
19070062 584static int bus_method_resolve_record(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2d4c5cbc
LP
585 _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
586 _cleanup_(dns_question_unrefp) DnsQuestion *question = NULL;
2d4c5cbc 587 Manager *m = userdata;
2d4c5cbc
LP
588 uint16_t class, type;
589 const char *name;
51323288
LP
590 int r, ifindex;
591 uint64_t flags;
592 DnsQuery *q;
2d4c5cbc 593
2d4c5cbc
LP
594 assert(message);
595 assert(m);
596
51323288 597 r = sd_bus_message_read(message, "isqqt", &ifindex, &name, &class, &type, &flags);
2d4c5cbc
LP
598 if (r < 0)
599 return r;
600
7b9f7afc
LP
601 r = dns_name_normalize(name, NULL);
602 if (r < 0)
603 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid name '%s'", name);
604
51323288
LP
605 r = check_ifindex_flags(ifindex, &flags, error);
606 if (r < 0)
607 return r;
608
2d4c5cbc
LP
609 question = dns_question_new(1);
610 if (!question)
611 return -ENOMEM;
612
613 key = dns_resource_key_new(class, type, name);
614 if (!key)
615 return -ENOMEM;
616
617 r = dns_question_add(question, key);
618 if (r < 0)
619 return r;
620
51323288 621 r = dns_query_new(m, &q, question, ifindex, flags);
2d4c5cbc
LP
622 if (r < 0)
623 return r;
624
625 q->request = sd_bus_message_ref(message);
626 q->request_hostname = name;
627 q->complete = bus_method_resolve_record_complete;
628
966c66e3 629 r = dns_query_bus_track(q, message);
82bd6ddd
LP
630 if (r < 0)
631 return r;
632
2d4c5cbc
LP
633 r = dns_query_go(q);
634 if (r < 0) {
635 dns_query_free(q);
2d4c5cbc
LP
636 return r;
637 }
638
639 return 1;
640}
641
74b2466e
LP
642static const sd_bus_vtable resolve_vtable[] = {
643 SD_BUS_VTABLE_START(0),
78c6a153
LP
644 SD_BUS_METHOD("ResolveHostname", "isit", "a(iiay)st", bus_method_resolve_hostname, SD_BUS_VTABLE_UNPRIVILEGED),
645 SD_BUS_METHOD("ResolveAddress", "iiayt", "a(is)t", bus_method_resolve_address, SD_BUS_VTABLE_UNPRIVILEGED),
646 SD_BUS_METHOD("ResolveRecord", "isqqt", "a(iqqay)t", bus_method_resolve_record, SD_BUS_VTABLE_UNPRIVILEGED),
74b2466e
LP
647 SD_BUS_VTABLE_END,
648};
649
650static int on_bus_retry(sd_event_source *s, usec_t usec, void *userdata) {
651 Manager *m = userdata;
652
653 assert(s);
654 assert(m);
655
656 m->bus_retry_event_source = sd_event_source_unref(m->bus_retry_event_source);
657
658 manager_connect_bus(m);
659 return 0;
660}
661
19070062 662static int match_prepare_for_sleep(sd_bus_message *message, void *userdata, sd_bus_error *ret_error) {
902bb5d8
LP
663 Manager *m = userdata;
664 int b, r;
665
19070062
LP
666 assert(message);
667 assert(m);
902bb5d8
LP
668
669 r = sd_bus_message_read(message, "b", &b);
670 if (r < 0) {
da927ba9 671 log_debug_errno(r, "Failed to parse PrepareForSleep signal: %m");
902bb5d8
LP
672 return 0;
673 }
674
675 if (b)
676 return 0;
677
678 log_debug("Coming back from suspend, verifying all RRs...");
679
680 manager_verify_all(m);
681 return 0;
682}
683
74b2466e
LP
684int manager_connect_bus(Manager *m) {
685 int r;
686
687 assert(m);
688
689 if (m->bus)
690 return 0;
691
692 r = sd_bus_default_system(&m->bus);
693 if (r < 0) {
694 /* We failed to connect? Yuck, we must be in early
695 * boot. Let's try in 5s again. As soon as we have
696 * kdbus we can stop doing this... */
697
da927ba9 698 log_debug_errno(r, "Failed to connect to bus, trying again in 5s: %m");
74b2466e
LP
699
700 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
701 if (r < 0)
702 return log_error_errno(r, "Failed to install bus reconnect time event: %m");
74b2466e
LP
703
704 return 0;
705 }
706
4d1cf1e2 707 r = sd_bus_add_object_vtable(m->bus, NULL, "/org/freedesktop/resolve1", "org.freedesktop.resolve1.Manager", resolve_vtable, m);
f647962d
MS
708 if (r < 0)
709 return log_error_errno(r, "Failed to register object: %m");
74b2466e
LP
710
711 r = sd_bus_request_name(m->bus, "org.freedesktop.resolve1", 0);
f647962d
MS
712 if (r < 0)
713 return log_error_errno(r, "Failed to register name: %m");
74b2466e
LP
714
715 r = sd_bus_attach_event(m->bus, m->event, 0);
f647962d
MS
716 if (r < 0)
717 return log_error_errno(r, "Failed to attach bus to event loop: %m");
74b2466e 718
902bb5d8
LP
719 r = sd_bus_add_match(m->bus, &m->prepare_for_sleep_slot,
720 "type='signal',"
721 "sender='org.freedesktop.login1',"
722 "interface='org.freedesktop.login1.Manager',"
723 "member='PrepareForSleep',"
724 "path='/org/freedesktop/login1'",
725 match_prepare_for_sleep,
726 m);
727 if (r < 0)
da927ba9 728 log_error_errno(r, "Failed to add match for PrepareForSleep: %m");
902bb5d8 729
74b2466e
LP
730 return 0;
731}