]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/resolve/resolved-bus.c
resolved: rework what ResolveHostname() with family == AF_UNSPEC means
[thirdparty/systemd.git] / src / resolve / resolved-bus.c
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 "alloc-util.h"
23 #include "bus-common-errors.h"
24 #include "bus-util.h"
25 #include "dns-domain.h"
26 #include "resolved-bus.h"
27 #include "resolved-def.h"
28 #include "resolved-link-bus.h"
29
30 static int reply_query_state(DnsQuery *q) {
31
32 switch (q->state) {
33
34 case DNS_TRANSACTION_NO_SERVERS:
35 return sd_bus_reply_method_errorf(q->request, BUS_ERROR_NO_NAME_SERVERS, "No appropriate name servers or networks for name found");
36
37 case DNS_TRANSACTION_TIMEOUT:
38 return sd_bus_reply_method_errorf(q->request, SD_BUS_ERROR_TIMEOUT, "Query timed out");
39
40 case DNS_TRANSACTION_ATTEMPTS_MAX_REACHED:
41 return sd_bus_reply_method_errorf(q->request, SD_BUS_ERROR_TIMEOUT, "All attempts to contact name servers or networks failed");
42
43 case DNS_TRANSACTION_INVALID_REPLY:
44 return sd_bus_reply_method_errorf(q->request, BUS_ERROR_INVALID_REPLY, "Received invalid reply");
45
46 case DNS_TRANSACTION_ERRNO:
47 return sd_bus_reply_method_errnof(q->request, q->answer_errno, "Lookup failed due to system error: %m");
48
49 case DNS_TRANSACTION_ABORTED:
50 return sd_bus_reply_method_errorf(q->request, BUS_ERROR_ABORTED, "Query aborted");
51
52 case DNS_TRANSACTION_DNSSEC_FAILED:
53 return sd_bus_reply_method_errorf(q->request, BUS_ERROR_DNSSEC_FAILED, "DNSSEC validation failed: %s",
54 dnssec_result_to_string(q->answer_dnssec_result));
55
56 case DNS_TRANSACTION_NO_TRUST_ANCHOR:
57 return sd_bus_reply_method_errorf(q->request, BUS_ERROR_NO_TRUST_ANCHOR, "No suitable trust anchor known");
58
59 case DNS_TRANSACTION_RR_TYPE_UNSUPPORTED:
60 return sd_bus_reply_method_errorf(q->request, BUS_ERROR_RR_TYPE_UNSUPPORTED, "Server does not support requested resource record type");
61
62 case DNS_TRANSACTION_NETWORK_DOWN:
63 return sd_bus_reply_method_errorf(q->request, BUS_ERROR_NETWORK_DOWN, "Network is down");
64
65 case DNS_TRANSACTION_NOT_FOUND:
66 /* We return this as NXDOMAIN. This is only generated when a host doesn't implement LLMNR/TCP, and we
67 * thus quickly know that we cannot resolve an in-addr.arpa or ip6.arpa address. */
68 return sd_bus_reply_method_errorf(q->request, _BUS_ERROR_DNS "NXDOMAIN", "'%s' not found", dns_query_string(q));
69
70 case DNS_TRANSACTION_RCODE_FAILURE: {
71 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
72
73 if (q->answer_rcode == DNS_RCODE_NXDOMAIN)
74 sd_bus_error_setf(&error, _BUS_ERROR_DNS "NXDOMAIN", "'%s' not found", dns_query_string(q));
75 else {
76 const char *rc, *n;
77 char p[DECIMAL_STR_MAX(q->answer_rcode)];
78
79 rc = dns_rcode_to_string(q->answer_rcode);
80 if (!rc) {
81 sprintf(p, "%i", q->answer_rcode);
82 rc = p;
83 }
84
85 n = strjoina(_BUS_ERROR_DNS, rc);
86 sd_bus_error_setf(&error, n, "Could not resolve '%s', server or network returned error %s", dns_query_string(q), rc);
87 }
88
89 return sd_bus_reply_method_error(q->request, &error);
90 }
91
92 case DNS_TRANSACTION_NULL:
93 case DNS_TRANSACTION_PENDING:
94 case DNS_TRANSACTION_VALIDATING:
95 case DNS_TRANSACTION_SUCCESS:
96 default:
97 assert_not_reached("Impossible state");
98 }
99 }
100
101 static int append_address(sd_bus_message *reply, DnsResourceRecord *rr, int ifindex) {
102 int r;
103
104 assert(reply);
105 assert(rr);
106
107 r = sd_bus_message_open_container(reply, 'r', "iiay");
108 if (r < 0)
109 return r;
110
111 r = sd_bus_message_append(reply, "i", ifindex);
112 if (r < 0)
113 return r;
114
115 if (rr->key->type == DNS_TYPE_A) {
116 r = sd_bus_message_append(reply, "i", AF_INET);
117 if (r < 0)
118 return r;
119
120 r = sd_bus_message_append_array(reply, 'y', &rr->a.in_addr, sizeof(struct in_addr));
121
122 } else if (rr->key->type == DNS_TYPE_AAAA) {
123 r = sd_bus_message_append(reply, "i", AF_INET6);
124 if (r < 0)
125 return r;
126
127 r = sd_bus_message_append_array(reply, 'y', &rr->aaaa.in6_addr, sizeof(struct in6_addr));
128 } else
129 return -EAFNOSUPPORT;
130
131 if (r < 0)
132 return r;
133
134 r = sd_bus_message_close_container(reply);
135 if (r < 0)
136 return r;
137
138 return 0;
139 }
140
141 static void bus_method_resolve_hostname_complete(DnsQuery *q) {
142 _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *canonical = NULL;
143 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
144 DnsResourceRecord *rr;
145 unsigned added = 0;
146 int ifindex, r;
147
148 assert(q);
149
150 if (q->state != DNS_TRANSACTION_SUCCESS) {
151 r = reply_query_state(q);
152 goto finish;
153 }
154
155 r = dns_query_process_cname(q);
156 if (r == -ELOOP) {
157 r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_CNAME_LOOP, "CNAME loop detected, or CNAME resolving disabled on '%s'", dns_query_string(q));
158 goto finish;
159 }
160 if (r < 0)
161 goto finish;
162 if (r == DNS_QUERY_RESTARTED) /* This was a cname, and the query was restarted. */
163 return;
164
165 r = sd_bus_message_new_method_return(q->request, &reply);
166 if (r < 0)
167 goto finish;
168
169 r = sd_bus_message_open_container(reply, 'a', "(iiay)");
170 if (r < 0)
171 goto finish;
172
173 DNS_ANSWER_FOREACH_IFINDEX(rr, ifindex, q->answer) {
174 DnsQuestion *question;
175
176 question = dns_query_question_for_protocol(q, q->answer_protocol);
177
178 r = dns_question_matches_rr(question, rr, DNS_SEARCH_DOMAIN_NAME(q->answer_search_domain));
179 if (r < 0)
180 goto finish;
181 if (r == 0)
182 continue;
183
184 r = append_address(reply, rr, ifindex);
185 if (r < 0)
186 goto finish;
187
188 if (!canonical)
189 canonical = dns_resource_record_ref(rr);
190
191 added ++;
192 }
193
194 if (added <= 0) {
195 r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_NO_SUCH_RR, "'%s' does not have any RR of the requested type", dns_query_string(q));
196 goto finish;
197 }
198
199 r = sd_bus_message_close_container(reply);
200 if (r < 0)
201 goto finish;
202
203 /* Return the precise spelling and uppercasing and CNAME target reported by the server */
204 assert(canonical);
205 r = sd_bus_message_append(
206 reply, "st",
207 DNS_RESOURCE_KEY_NAME(canonical->key),
208 SD_RESOLVED_FLAGS_MAKE(q->answer_protocol, q->answer_family, q->answer_authenticated));
209 if (r < 0)
210 goto finish;
211
212 r = sd_bus_send(q->manager->bus, reply, NULL);
213
214 finish:
215 if (r < 0) {
216 log_error_errno(r, "Failed to send hostname reply: %m");
217 sd_bus_reply_method_errno(q->request, r, NULL);
218 }
219
220 dns_query_free(q);
221 }
222
223 static int check_ifindex_flags(int ifindex, uint64_t *flags, uint64_t ok, sd_bus_error *error) {
224 assert(flags);
225
226 if (ifindex < 0)
227 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid interface index");
228
229 if (*flags & ~(SD_RESOLVED_PROTOCOLS_ALL|SD_RESOLVED_NO_CNAME|ok))
230 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid flags parameter");
231
232 if ((*flags & SD_RESOLVED_PROTOCOLS_ALL) == 0) /* If no protocol is enabled, enable all */
233 *flags |= SD_RESOLVED_PROTOCOLS_ALL;
234
235 return 0;
236 }
237
238 static int bus_method_resolve_hostname(sd_bus_message *message, void *userdata, sd_bus_error *error) {
239 _cleanup_(dns_question_unrefp) DnsQuestion *question_idna = NULL, *question_utf8 = NULL;
240 Manager *m = userdata;
241 const char *hostname;
242 int family, ifindex;
243 uint64_t flags;
244 DnsQuery *q;
245 int r;
246
247 assert(message);
248 assert(m);
249
250 assert_cc(sizeof(int) == sizeof(int32_t));
251
252 r = sd_bus_message_read(message, "isit", &ifindex, &hostname, &family, &flags);
253 if (r < 0)
254 return r;
255
256 if (!IN_SET(family, AF_INET, AF_INET6, AF_UNSPEC))
257 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown address family %i", family);
258
259 r = dns_name_is_valid(hostname);
260 if (r < 0)
261 return r;
262 if (r == 0)
263 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid hostname '%s'", hostname);
264
265 r = check_ifindex_flags(ifindex, &flags, SD_RESOLVED_NO_SEARCH, error);
266 if (r < 0)
267 return r;
268
269 r = dns_question_new_address(&question_utf8, family, hostname, false);
270 if (r < 0)
271 return r;
272
273 r = dns_question_new_address(&question_idna, family, hostname, true);
274 if (r < 0)
275 return r;
276
277 r = dns_query_new(m, &q, question_utf8, question_idna, ifindex, flags);
278 if (r < 0)
279 return r;
280
281 q->request = sd_bus_message_ref(message);
282 q->request_family = family;
283 q->complete = bus_method_resolve_hostname_complete;
284 q->suppress_unroutable_family = family == AF_UNSPEC;
285
286 r = dns_query_bus_track(q, message);
287 if (r < 0)
288 goto fail;
289
290 r = dns_query_go(q);
291 if (r < 0)
292 goto fail;
293
294 return 1;
295
296 fail:
297 dns_query_free(q);
298 return r;
299 }
300
301 static void bus_method_resolve_address_complete(DnsQuery *q) {
302 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
303 DnsQuestion *question;
304 DnsResourceRecord *rr;
305 unsigned added = 0;
306 int ifindex, r;
307
308 assert(q);
309
310 if (q->state != DNS_TRANSACTION_SUCCESS) {
311 r = reply_query_state(q);
312 goto finish;
313 }
314
315 r = dns_query_process_cname(q);
316 if (r == -ELOOP) {
317 r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_CNAME_LOOP, "CNAME loop detected, or CNAME resolving disabled on '%s'", dns_query_string(q));
318 goto finish;
319 }
320 if (r < 0)
321 goto finish;
322 if (r == DNS_QUERY_RESTARTED) /* This was a cname, and the query was restarted. */
323 return;
324
325 r = sd_bus_message_new_method_return(q->request, &reply);
326 if (r < 0)
327 goto finish;
328
329 r = sd_bus_message_open_container(reply, 'a', "(is)");
330 if (r < 0)
331 goto finish;
332
333 question = dns_query_question_for_protocol(q, q->answer_protocol);
334
335 DNS_ANSWER_FOREACH_IFINDEX(rr, ifindex, q->answer) {
336 r = dns_question_matches_rr(question, rr, NULL);
337 if (r < 0)
338 goto finish;
339 if (r == 0)
340 continue;
341
342 r = sd_bus_message_append(reply, "(is)", ifindex, rr->ptr.name);
343 if (r < 0)
344 goto finish;
345
346 added ++;
347 }
348
349 if (added <= 0) {
350 _cleanup_free_ char *ip = NULL;
351
352 in_addr_to_string(q->request_family, &q->request_address, &ip);
353 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));
354 goto finish;
355 }
356
357 r = sd_bus_message_close_container(reply);
358 if (r < 0)
359 goto finish;
360
361 r = sd_bus_message_append(reply, "t", SD_RESOLVED_FLAGS_MAKE(q->answer_protocol, q->answer_family, q->answer_authenticated));
362 if (r < 0)
363 goto finish;
364
365 r = sd_bus_send(q->manager->bus, reply, NULL);
366
367 finish:
368 if (r < 0) {
369 log_error_errno(r, "Failed to send address reply: %m");
370 sd_bus_reply_method_errno(q->request, r, NULL);
371 }
372
373 dns_query_free(q);
374 }
375
376 static int bus_method_resolve_address(sd_bus_message *message, void *userdata, sd_bus_error *error) {
377 _cleanup_(dns_question_unrefp) DnsQuestion *question = NULL;
378 Manager *m = userdata;
379 int family, ifindex;
380 uint64_t flags;
381 const void *d;
382 DnsQuery *q;
383 size_t sz;
384 int r;
385
386 assert(message);
387 assert(m);
388
389 assert_cc(sizeof(int) == sizeof(int32_t));
390
391 r = sd_bus_message_read(message, "ii", &ifindex, &family);
392 if (r < 0)
393 return r;
394
395 if (!IN_SET(family, AF_INET, AF_INET6))
396 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown address family %i", family);
397
398 r = sd_bus_message_read_array(message, 'y', &d, &sz);
399 if (r < 0)
400 return r;
401
402 if (sz != FAMILY_ADDRESS_SIZE(family))
403 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid address size");
404
405 r = sd_bus_message_read(message, "t", &flags);
406 if (r < 0)
407 return r;
408
409 r = check_ifindex_flags(ifindex, &flags, 0, error);
410 if (r < 0)
411 return r;
412
413 r = dns_question_new_reverse(&question, family, d);
414 if (r < 0)
415 return r;
416
417 r = dns_query_new(m, &q, question, question, ifindex, flags|SD_RESOLVED_NO_SEARCH);
418 if (r < 0)
419 return r;
420
421 q->request = sd_bus_message_ref(message);
422 q->request_family = family;
423 memcpy(&q->request_address, d, sz);
424 q->complete = bus_method_resolve_address_complete;
425
426 r = dns_query_bus_track(q, message);
427 if (r < 0)
428 goto fail;
429
430 r = dns_query_go(q);
431 if (r < 0)
432 goto fail;
433
434 return 1;
435
436 fail:
437 dns_query_free(q);
438 return r;
439 }
440
441 static int bus_message_append_rr(sd_bus_message *m, DnsResourceRecord *rr, int ifindex) {
442 int r;
443
444 assert(m);
445 assert(rr);
446
447 r = sd_bus_message_open_container(m, 'r', "iqqay");
448 if (r < 0)
449 return r;
450
451 r = sd_bus_message_append(m, "iqq",
452 ifindex,
453 rr->key->class,
454 rr->key->type);
455 if (r < 0)
456 return r;
457
458 r = dns_resource_record_to_wire_format(rr, false);
459 if (r < 0)
460 return r;
461
462 r = sd_bus_message_append_array(m, 'y', rr->wire_format, rr->wire_format_size);
463 if (r < 0)
464 return r;
465
466 return sd_bus_message_close_container(m);
467 }
468
469 static void bus_method_resolve_record_complete(DnsQuery *q) {
470 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
471 DnsResourceRecord *rr;
472 DnsQuestion *question;
473 unsigned added = 0;
474 int ifindex;
475 int r;
476
477 assert(q);
478
479 if (q->state != DNS_TRANSACTION_SUCCESS) {
480 r = reply_query_state(q);
481 goto finish;
482 }
483
484 r = dns_query_process_cname(q);
485 if (r == -ELOOP) {
486 r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_CNAME_LOOP, "CNAME loop detected, or CNAME resolving disabled on '%s'", dns_query_string(q));
487 goto finish;
488 }
489 if (r < 0)
490 goto finish;
491 if (r == DNS_QUERY_RESTARTED) /* This was a cname, and the query was restarted. */
492 return;
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', "(iqqay)");
499 if (r < 0)
500 goto finish;
501
502 question = dns_query_question_for_protocol(q, q->answer_protocol);
503
504 DNS_ANSWER_FOREACH_IFINDEX(rr, ifindex, q->answer) {
505 r = dns_question_matches_rr(question, rr, NULL);
506 if (r < 0)
507 goto finish;
508 if (r == 0)
509 continue;
510
511 r = bus_message_append_rr(reply, rr, ifindex);
512 if (r < 0)
513 goto finish;
514
515 added ++;
516 }
517
518 if (added <= 0) {
519 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_query_string(q));
520 goto finish;
521 }
522
523 r = sd_bus_message_close_container(reply);
524 if (r < 0)
525 goto finish;
526
527 r = sd_bus_message_append(reply, "t", SD_RESOLVED_FLAGS_MAKE(q->answer_protocol, q->answer_family, q->answer_authenticated));
528 if (r < 0)
529 goto finish;
530
531 r = sd_bus_send(q->manager->bus, reply, NULL);
532
533 finish:
534 if (r < 0) {
535 log_error_errno(r, "Failed to send record reply: %m");
536 sd_bus_reply_method_errno(q->request, r, NULL);
537 }
538
539 dns_query_free(q);
540 }
541
542 static int bus_method_resolve_record(sd_bus_message *message, void *userdata, sd_bus_error *error) {
543 _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
544 _cleanup_(dns_question_unrefp) DnsQuestion *question = NULL;
545 Manager *m = userdata;
546 uint16_t class, type;
547 const char *name;
548 int r, ifindex;
549 uint64_t flags;
550 DnsQuery *q;
551
552 assert(message);
553 assert(m);
554
555 assert_cc(sizeof(int) == sizeof(int32_t));
556
557 r = sd_bus_message_read(message, "isqqt", &ifindex, &name, &class, &type, &flags);
558 if (r < 0)
559 return r;
560
561 r = dns_name_is_valid(name);
562 if (r < 0)
563 return r;
564 if (r == 0)
565 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid name '%s'", name);
566
567 if (!dns_type_is_valid_query(type))
568 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Specified resource record type %" PRIu16 " may not be used in a query.", type);
569 if (dns_type_is_obsolete(type))
570 return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Specified DNS resource record type %" PRIu16 " is obsolete.", type);
571
572 r = check_ifindex_flags(ifindex, &flags, 0, error);
573 if (r < 0)
574 return r;
575
576 question = dns_question_new(1);
577 if (!question)
578 return -ENOMEM;
579
580 key = dns_resource_key_new(class, type, name);
581 if (!key)
582 return -ENOMEM;
583
584 r = dns_question_add(question, key);
585 if (r < 0)
586 return r;
587
588 r = dns_query_new(m, &q, question, question, ifindex, flags|SD_RESOLVED_NO_SEARCH);
589 if (r < 0)
590 return r;
591
592 q->request = sd_bus_message_ref(message);
593 q->complete = bus_method_resolve_record_complete;
594
595 r = dns_query_bus_track(q, message);
596 if (r < 0)
597 goto fail;
598
599 r = dns_query_go(q);
600 if (r < 0)
601 goto fail;
602
603 return 1;
604
605 fail:
606 dns_query_free(q);
607 return r;
608 }
609
610 static int append_srv(DnsQuery *q, sd_bus_message *reply, DnsResourceRecord *rr) {
611 _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *canonical = NULL;
612 DnsQuery *aux;
613 int r;
614
615 assert(q);
616 assert(reply);
617 assert(rr);
618 assert(rr->key);
619
620 if (rr->key->type != DNS_TYPE_SRV)
621 return 0;
622
623 if ((q->flags & SD_RESOLVED_NO_ADDRESS) == 0) {
624 /* First, let's see if we could find an appropriate A or AAAA
625 * record for the SRV record */
626 LIST_FOREACH(auxiliary_queries, aux, q->auxiliary_queries) {
627 DnsResourceRecord *zz;
628 DnsQuestion *question;
629
630 if (aux->state != DNS_TRANSACTION_SUCCESS)
631 continue;
632 if (aux->auxiliary_result != 0)
633 continue;
634
635 question = dns_query_question_for_protocol(aux, aux->answer_protocol);
636
637 r = dns_name_equal(dns_question_first_name(question), rr->srv.name);
638 if (r < 0)
639 return r;
640 if (r == 0)
641 continue;
642
643 DNS_ANSWER_FOREACH(zz, aux->answer) {
644
645 r = dns_question_matches_rr(question, zz, NULL);
646 if (r < 0)
647 return r;
648 if (r == 0)
649 continue;
650
651 canonical = dns_resource_record_ref(zz);
652 break;
653 }
654
655 if (canonical)
656 break;
657 }
658
659 /* Is there are successful A/AAAA lookup for this SRV RR? If not, don't add it */
660 if (!canonical)
661 return 0;
662 }
663
664 r = sd_bus_message_open_container(reply, 'r', "qqqsa(iiay)s");
665 if (r < 0)
666 return r;
667
668 r = sd_bus_message_append(
669 reply,
670 "qqqs",
671 rr->srv.priority, rr->srv.weight, rr->srv.port, rr->srv.name);
672 if (r < 0)
673 return r;
674
675 r = sd_bus_message_open_container(reply, 'a', "(iiay)");
676 if (r < 0)
677 return r;
678
679 if ((q->flags & SD_RESOLVED_NO_ADDRESS) == 0) {
680 LIST_FOREACH(auxiliary_queries, aux, q->auxiliary_queries) {
681 DnsResourceRecord *zz;
682 DnsQuestion *question;
683 int ifindex;
684
685 if (aux->state != DNS_TRANSACTION_SUCCESS)
686 continue;
687 if (aux->auxiliary_result != 0)
688 continue;
689
690 question = dns_query_question_for_protocol(aux, aux->answer_protocol);
691
692 r = dns_name_equal(dns_question_first_name(question), rr->srv.name);
693 if (r < 0)
694 return r;
695 if (r == 0)
696 continue;
697
698 DNS_ANSWER_FOREACH_IFINDEX(zz, ifindex, aux->answer) {
699
700 r = dns_question_matches_rr(question, zz, NULL);
701 if (r < 0)
702 return r;
703 if (r == 0)
704 continue;
705
706 r = append_address(reply, zz, ifindex);
707 if (r < 0)
708 return r;
709 }
710 }
711 }
712
713 r = sd_bus_message_close_container(reply);
714 if (r < 0)
715 return r;
716
717 /* Note that above we appended the hostname as encoded in the
718 * SRV, and here the canonical hostname this maps to. */
719 r = sd_bus_message_append(reply, "s", canonical ? DNS_RESOURCE_KEY_NAME(canonical->key) : rr->srv.name);
720 if (r < 0)
721 return r;
722
723 r = sd_bus_message_close_container(reply);
724 if (r < 0)
725 return r;
726
727 return 1;
728 }
729
730 static int append_txt(sd_bus_message *reply, DnsResourceRecord *rr) {
731 DnsTxtItem *i;
732 int r;
733
734 assert(reply);
735 assert(rr);
736 assert(rr->key);
737
738 if (rr->key->type != DNS_TYPE_TXT)
739 return 0;
740
741 LIST_FOREACH(items, i, rr->txt.items) {
742
743 if (i->length <= 0)
744 continue;
745
746 r = sd_bus_message_append_array(reply, 'y', i->data, i->length);
747 if (r < 0)
748 return r;
749 }
750
751 return 1;
752 }
753
754 static void resolve_service_all_complete(DnsQuery *q) {
755 _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *canonical = NULL;
756 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
757 _cleanup_free_ char *name = NULL, *type = NULL, *domain = NULL;
758 DnsQuestion *question;
759 DnsResourceRecord *rr;
760 unsigned added = 0;
761 DnsQuery *aux;
762 int r;
763
764 assert(q);
765
766 if (q->block_all_complete > 0)
767 return;
768
769 if ((q->flags & SD_RESOLVED_NO_ADDRESS) == 0) {
770 DnsQuery *bad = NULL;
771 bool have_success = false;
772
773 LIST_FOREACH(auxiliary_queries, aux, q->auxiliary_queries) {
774
775 switch (aux->state) {
776
777 case DNS_TRANSACTION_PENDING:
778 /* If an auxiliary query is still pending, let's wait */
779 return;
780
781 case DNS_TRANSACTION_SUCCESS:
782 if (aux->auxiliary_result == 0)
783 have_success = true;
784 else
785 bad = aux;
786 break;
787
788 default:
789 bad = aux;
790 break;
791 }
792 }
793
794 if (!have_success) {
795 /* We can only return one error, hence pick the last error we encountered */
796
797 assert(bad);
798
799 if (bad->state == DNS_TRANSACTION_SUCCESS) {
800 assert(bad->auxiliary_result != 0);
801
802 if (bad->auxiliary_result == -ELOOP) {
803 r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_CNAME_LOOP, "CNAME loop detected, or CNAME resolving disabled on '%s'", dns_query_string(bad));
804 goto finish;
805 }
806
807 r = bad->auxiliary_result;
808 goto finish;
809 }
810
811 r = reply_query_state(bad);
812 goto finish;
813 }
814 }
815
816 r = sd_bus_message_new_method_return(q->request, &reply);
817 if (r < 0)
818 goto finish;
819
820 r = sd_bus_message_open_container(reply, 'a', "(qqqsa(iiay)s)");
821 if (r < 0)
822 goto finish;
823
824 question = dns_query_question_for_protocol(q, q->answer_protocol);
825 DNS_ANSWER_FOREACH(rr, q->answer) {
826 r = dns_question_matches_rr(question, rr, NULL);
827 if (r < 0)
828 goto finish;
829 if (r == 0)
830 continue;
831
832 r = append_srv(q, reply, rr);
833 if (r < 0)
834 goto finish;
835 if (r == 0) /* not an SRV record */
836 continue;
837
838 if (!canonical)
839 canonical = dns_resource_record_ref(rr);
840
841 added++;
842 }
843
844 if (added <= 0) {
845 r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_NO_SUCH_RR, "'%s' does not have any RR of the requested type", dns_query_string(q));
846 goto finish;
847 }
848
849 r = sd_bus_message_close_container(reply);
850 if (r < 0)
851 goto finish;
852
853 r = sd_bus_message_open_container(reply, 'a', "ay");
854 if (r < 0)
855 goto finish;
856
857 DNS_ANSWER_FOREACH(rr, q->answer) {
858 r = dns_question_matches_rr(question, rr, NULL);
859 if (r < 0)
860 goto finish;
861 if (r == 0)
862 continue;
863
864 r = append_txt(reply, rr);
865 if (r < 0)
866 goto finish;
867 }
868
869 r = sd_bus_message_close_container(reply);
870 if (r < 0)
871 goto finish;
872
873 assert(canonical);
874 r = dns_service_split(DNS_RESOURCE_KEY_NAME(canonical->key), &name, &type, &domain);
875 if (r < 0)
876 goto finish;
877
878 r = sd_bus_message_append(
879 reply,
880 "ssst",
881 name, type, domain,
882 SD_RESOLVED_FLAGS_MAKE(q->answer_protocol, q->answer_family, q->answer_authenticated));
883 if (r < 0)
884 goto finish;
885
886 r = sd_bus_send(q->manager->bus, reply, NULL);
887
888 finish:
889 if (r < 0) {
890 log_error_errno(r, "Failed to send service reply: %m");
891 sd_bus_reply_method_errno(q->request, r, NULL);
892 }
893
894 dns_query_free(q);
895 }
896
897 static void resolve_service_hostname_complete(DnsQuery *q) {
898 int r;
899
900 assert(q);
901 assert(q->auxiliary_for);
902
903 if (q->state != DNS_TRANSACTION_SUCCESS) {
904 resolve_service_all_complete(q->auxiliary_for);
905 return;
906 }
907
908 r = dns_query_process_cname(q);
909 if (r == DNS_QUERY_RESTARTED) /* This was a cname, and the query was restarted. */
910 return;
911
912 /* This auxiliary lookup is finished or failed, let's see if all are finished now. */
913 q->auxiliary_result = r;
914 resolve_service_all_complete(q->auxiliary_for);
915 }
916
917 static int resolve_service_hostname(DnsQuery *q, DnsResourceRecord *rr, int ifindex) {
918 _cleanup_(dns_question_unrefp) DnsQuestion *question = NULL;
919 DnsQuery *aux;
920 int r;
921
922 assert(q);
923 assert(rr);
924 assert(rr->key);
925 assert(rr->key->type == DNS_TYPE_SRV);
926
927 /* OK, we found an SRV record for the service. Let's resolve
928 * the hostname included in it */
929
930 r = dns_question_new_address(&question, q->request_family, rr->srv.name, false);
931 if (r < 0)
932 return r;
933
934 r = dns_query_new(q->manager, &aux, question, question, ifindex, q->flags|SD_RESOLVED_NO_SEARCH);
935 if (r < 0)
936 return r;
937
938 aux->request_family = q->request_family;
939 aux->complete = resolve_service_hostname_complete;
940
941 r = dns_query_make_auxiliary(aux, q);
942 if (r == -EAGAIN) {
943 /* Too many auxiliary lookups? If so, don't complain,
944 * let's just not add this one, we already have more
945 * than enough */
946
947 dns_query_free(aux);
948 return 0;
949 }
950 if (r < 0)
951 goto fail;
952
953 /* Note that auxiliary queries do not track the original bus
954 * client, only the primary request does that. */
955
956 r = dns_query_go(aux);
957 if (r < 0)
958 goto fail;
959
960 return 1;
961
962 fail:
963 dns_query_free(aux);
964 return r;
965 }
966
967 static void bus_method_resolve_service_complete(DnsQuery *q) {
968 bool has_root_domain = false;
969 DnsResourceRecord *rr;
970 DnsQuestion *question;
971 unsigned found = 0;
972 int ifindex, r;
973
974 assert(q);
975
976 if (q->state != DNS_TRANSACTION_SUCCESS) {
977 r = reply_query_state(q);
978 goto finish;
979 }
980
981 r = dns_query_process_cname(q);
982 if (r == -ELOOP) {
983 r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_CNAME_LOOP, "CNAME loop detected, or CNAME resolving disabled on '%s'", dns_query_string(q));
984 goto finish;
985 }
986 if (r < 0)
987 goto finish;
988 if (r == DNS_QUERY_RESTARTED) /* This was a cname, and the query was restarted. */
989 return;
990
991 question = dns_query_question_for_protocol(q, q->answer_protocol);
992
993 DNS_ANSWER_FOREACH_IFINDEX(rr, ifindex, q->answer) {
994 r = dns_question_matches_rr(question, rr, NULL);
995 if (r < 0)
996 goto finish;
997 if (r == 0)
998 continue;
999
1000 if (rr->key->type != DNS_TYPE_SRV)
1001 continue;
1002
1003 if (dns_name_is_root(rr->srv.name)) {
1004 has_root_domain = true;
1005 continue;
1006 }
1007
1008 if ((q->flags & SD_RESOLVED_NO_ADDRESS) == 0) {
1009 q->block_all_complete ++;
1010 r = resolve_service_hostname(q, rr, ifindex);
1011 q->block_all_complete --;
1012
1013 if (r < 0)
1014 goto finish;
1015 }
1016
1017 found++;
1018 }
1019
1020 if (has_root_domain && found <= 0) {
1021 /* If there's exactly one SRV RR and it uses
1022 * the root domain as host name, then the
1023 * service is explicitly not offered on the
1024 * domain. Report this as a recognizable
1025 * error. See RFC 2782, Section "Usage
1026 * Rules". */
1027 r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_NO_SUCH_SERVICE, "'%s' does not provide the requested service", dns_query_string(q));
1028 goto finish;
1029 }
1030
1031 if (found <= 0) {
1032 r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_NO_SUCH_RR, "'%s' does not have any RR of the requested type", dns_query_string(q));
1033 goto finish;
1034 }
1035
1036 /* Maybe we are already finished? check now... */
1037 resolve_service_all_complete(q);
1038 return;
1039
1040 finish:
1041 if (r < 0) {
1042 log_error_errno(r, "Failed to send service reply: %m");
1043 sd_bus_reply_method_errno(q->request, r, NULL);
1044 }
1045
1046 dns_query_free(q);
1047 }
1048
1049 static int bus_method_resolve_service(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1050 _cleanup_(dns_question_unrefp) DnsQuestion *question_idna = NULL, *question_utf8 = NULL;
1051 const char *name, *type, *domain;
1052 _cleanup_free_ char *n = NULL;
1053 Manager *m = userdata;
1054 int family, ifindex;
1055 uint64_t flags;
1056 DnsQuery *q;
1057 int r;
1058
1059 assert(message);
1060 assert(m);
1061
1062 assert_cc(sizeof(int) == sizeof(int32_t));
1063
1064 r = sd_bus_message_read(message, "isssit", &ifindex, &name, &type, &domain, &family, &flags);
1065 if (r < 0)
1066 return r;
1067
1068 if (!IN_SET(family, AF_INET, AF_INET6, AF_UNSPEC))
1069 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown address family %i", family);
1070
1071 if (isempty(name))
1072 name = NULL;
1073 else if (!dns_service_name_is_valid(name))
1074 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid service name '%s'", name);
1075
1076 if (isempty(type))
1077 type = NULL;
1078 else if (!dns_srv_type_is_valid(type))
1079 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid SRV service type '%s'", type);
1080
1081 r = dns_name_is_valid(domain);
1082 if (r < 0)
1083 return r;
1084 if (r == 0)
1085 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid domain '%s'", domain);
1086
1087 if (name && !type)
1088 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Service name cannot be specified without service type.");
1089
1090 r = check_ifindex_flags(ifindex, &flags, SD_RESOLVED_NO_TXT|SD_RESOLVED_NO_ADDRESS, error);
1091 if (r < 0)
1092 return r;
1093
1094 r = dns_question_new_service(&question_utf8, name, type, domain, !(flags & SD_RESOLVED_NO_TXT), false);
1095 if (r < 0)
1096 return r;
1097
1098 r = dns_question_new_service(&question_idna, name, type, domain, !(flags & SD_RESOLVED_NO_TXT), true);
1099 if (r < 0)
1100 return r;
1101
1102 r = dns_query_new(m, &q, question_utf8, question_idna, ifindex, flags|SD_RESOLVED_NO_SEARCH);
1103 if (r < 0)
1104 return r;
1105
1106 q->request = sd_bus_message_ref(message);
1107 q->request_family = family;
1108 q->complete = bus_method_resolve_service_complete;
1109
1110 r = dns_query_bus_track(q, message);
1111 if (r < 0)
1112 goto fail;
1113
1114 r = dns_query_go(q);
1115 if (r < 0)
1116 goto fail;
1117
1118 return 1;
1119
1120 fail:
1121 dns_query_free(q);
1122 return r;
1123 }
1124
1125 int bus_dns_server_append(sd_bus_message *reply, DnsServer *s, bool with_ifindex) {
1126 int r;
1127
1128 assert(reply);
1129 assert(s);
1130
1131 r = sd_bus_message_open_container(reply, 'r', with_ifindex ? "iiay" : "iay");
1132 if (r < 0)
1133 return r;
1134
1135 if (with_ifindex) {
1136 r = sd_bus_message_append(reply, "i", s->link ? s->link->ifindex : 0);
1137 if (r < 0)
1138 return r;
1139 }
1140
1141 r = sd_bus_message_append(reply, "i", s->family);
1142 if (r < 0)
1143 return r;
1144
1145 r = sd_bus_message_append_array(reply, 'y', &s->address, FAMILY_ADDRESS_SIZE(s->family));
1146 if (r < 0)
1147 return r;
1148
1149 return sd_bus_message_close_container(reply);
1150 }
1151
1152 static int bus_property_get_dns_servers(
1153 sd_bus *bus,
1154 const char *path,
1155 const char *interface,
1156 const char *property,
1157 sd_bus_message *reply,
1158 void *userdata,
1159 sd_bus_error *error) {
1160
1161 Manager *m = userdata;
1162 unsigned c = 0;
1163 DnsServer *s;
1164 Iterator i;
1165 Link *l;
1166 int r;
1167
1168 assert(reply);
1169 assert(m);
1170
1171 r = sd_bus_message_open_container(reply, 'a', "(iiay)");
1172 if (r < 0)
1173 return r;
1174
1175 LIST_FOREACH(servers, s, m->dns_servers) {
1176 r = bus_dns_server_append(reply, s, true);
1177 if (r < 0)
1178 return r;
1179
1180 c++;
1181 }
1182
1183 HASHMAP_FOREACH(l, m->links, i) {
1184 LIST_FOREACH(servers, s, l->dns_servers) {
1185 r = bus_dns_server_append(reply, s, true);
1186 if (r < 0)
1187 return r;
1188 c++;
1189 }
1190 }
1191
1192 if (c == 0) {
1193 LIST_FOREACH(servers, s, m->fallback_dns_servers) {
1194 r = bus_dns_server_append(reply, s, true);
1195 if (r < 0)
1196 return r;
1197 }
1198 }
1199
1200 return sd_bus_message_close_container(reply);
1201 }
1202
1203 static int bus_property_get_search_domains(
1204 sd_bus *bus,
1205 const char *path,
1206 const char *interface,
1207 const char *property,
1208 sd_bus_message *reply,
1209 void *userdata,
1210 sd_bus_error *error) {
1211
1212 Manager *m = userdata;
1213 DnsSearchDomain *d;
1214 Iterator i;
1215 Link *l;
1216 int r;
1217
1218 assert(reply);
1219 assert(m);
1220
1221 r = sd_bus_message_open_container(reply, 'a', "(isb)");
1222 if (r < 0)
1223 return r;
1224
1225 LIST_FOREACH(domains, d, m->search_domains) {
1226 r = sd_bus_message_append(reply, "(isb)", 0, d->name, d->route_only);
1227 if (r < 0)
1228 return r;
1229 }
1230
1231 HASHMAP_FOREACH(l, m->links, i) {
1232 LIST_FOREACH(domains, d, l->search_domains) {
1233 r = sd_bus_message_append(reply, "(isb)", l->ifindex, d->name, d->route_only);
1234 if (r < 0)
1235 return r;
1236 }
1237 }
1238
1239 return sd_bus_message_close_container(reply);
1240 }
1241
1242 static int bus_property_get_transaction_statistics(
1243 sd_bus *bus,
1244 const char *path,
1245 const char *interface,
1246 const char *property,
1247 sd_bus_message *reply,
1248 void *userdata,
1249 sd_bus_error *error) {
1250
1251 Manager *m = userdata;
1252
1253 assert(reply);
1254 assert(m);
1255
1256 return sd_bus_message_append(reply, "(tt)",
1257 (uint64_t) hashmap_size(m->dns_transactions),
1258 (uint64_t) m->n_transactions_total);
1259 }
1260
1261 static int bus_property_get_cache_statistics(
1262 sd_bus *bus,
1263 const char *path,
1264 const char *interface,
1265 const char *property,
1266 sd_bus_message *reply,
1267 void *userdata,
1268 sd_bus_error *error) {
1269
1270 uint64_t size = 0, hit = 0, miss = 0;
1271 Manager *m = userdata;
1272 DnsScope *s;
1273
1274 assert(reply);
1275 assert(m);
1276
1277 LIST_FOREACH(scopes, s, m->dns_scopes) {
1278 size += dns_cache_size(&s->cache);
1279 hit += s->cache.n_hit;
1280 miss += s->cache.n_miss;
1281 }
1282
1283 return sd_bus_message_append(reply, "(ttt)", size, hit, miss);
1284 }
1285
1286 static int bus_property_get_dnssec_statistics(
1287 sd_bus *bus,
1288 const char *path,
1289 const char *interface,
1290 const char *property,
1291 sd_bus_message *reply,
1292 void *userdata,
1293 sd_bus_error *error) {
1294
1295 Manager *m = userdata;
1296
1297 assert(reply);
1298 assert(m);
1299
1300 return sd_bus_message_append(reply, "(tttt)",
1301 (uint64_t) m->n_dnssec_verdict[DNSSEC_SECURE],
1302 (uint64_t) m->n_dnssec_verdict[DNSSEC_INSECURE],
1303 (uint64_t) m->n_dnssec_verdict[DNSSEC_BOGUS],
1304 (uint64_t) m->n_dnssec_verdict[DNSSEC_INDETERMINATE]);
1305 }
1306
1307 static int bus_property_get_dnssec_supported(
1308 sd_bus *bus,
1309 const char *path,
1310 const char *interface,
1311 const char *property,
1312 sd_bus_message *reply,
1313 void *userdata,
1314 sd_bus_error *error) {
1315
1316 Manager *m = userdata;
1317
1318 assert(reply);
1319 assert(m);
1320
1321 return sd_bus_message_append(reply, "b", manager_dnssec_supported(m));
1322 }
1323
1324 static int bus_method_reset_statistics(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1325 Manager *m = userdata;
1326 DnsScope *s;
1327
1328 assert(message);
1329 assert(m);
1330
1331 LIST_FOREACH(scopes, s, m->dns_scopes)
1332 s->cache.n_hit = s->cache.n_miss = 0;
1333
1334 m->n_transactions_total = 0;
1335 zero(m->n_dnssec_verdict);
1336
1337 return sd_bus_reply_method_return(message, NULL);
1338 }
1339
1340 static int get_any_link(Manager *m, int ifindex, Link **ret, sd_bus_error *error) {
1341 Link *l;
1342
1343 assert(m);
1344 assert(ret);
1345
1346 if (ifindex <= 0)
1347 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid interface index");
1348
1349 l = hashmap_get(m->links, INT_TO_PTR(ifindex));
1350 if (!l)
1351 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_LINK, "Link %i not known", ifindex);
1352
1353 *ret = l;
1354 return 0;
1355 }
1356
1357 static int get_unmanaged_link(Manager *m, int ifindex, Link **ret, sd_bus_error *error) {
1358 Link *l;
1359 int r;
1360
1361 assert(m);
1362 assert(ret);
1363
1364 r = get_any_link(m, ifindex, &l, error);
1365 if (r < 0)
1366 return r;
1367
1368 if (l->flags & IFF_LOOPBACK)
1369 return sd_bus_error_setf(error, BUS_ERROR_LINK_BUSY, "Link %s is loopback device.", l->name);
1370 if (l->is_managed)
1371 return sd_bus_error_setf(error, BUS_ERROR_LINK_BUSY, "Link %s is managed.", l->name);
1372
1373 *ret = l;
1374 return 0;
1375 }
1376
1377 static int call_link_method(Manager *m, sd_bus_message *message, sd_bus_message_handler_t handler, sd_bus_error *error) {
1378 int ifindex, r;
1379 Link *l;
1380
1381 assert(m);
1382 assert(message);
1383 assert(handler);
1384
1385 assert_cc(sizeof(int) == sizeof(int32_t));
1386 r = sd_bus_message_read(message, "i", &ifindex);
1387 if (r < 0)
1388 return r;
1389
1390 r = get_unmanaged_link(m, ifindex, &l, error);
1391 if (r < 0)
1392 return r;
1393
1394 return handler(message, l, error);
1395 }
1396
1397 static int bus_method_set_link_dns_servers(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1398 return call_link_method(userdata, message, bus_link_method_set_dns_servers, error);
1399 }
1400
1401 static int bus_method_set_link_search_domains(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1402 return call_link_method(userdata, message, bus_link_method_set_search_domains, error);
1403 }
1404
1405 static int bus_method_set_link_llmnr(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1406 return call_link_method(userdata, message, bus_link_method_set_llmnr, error);
1407 }
1408
1409 static int bus_method_set_link_mdns(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1410 return call_link_method(userdata, message, bus_link_method_set_mdns, error);
1411 }
1412
1413 static int bus_method_set_link_dnssec(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1414 return call_link_method(userdata, message, bus_link_method_set_dnssec, error);
1415 }
1416
1417 static int bus_method_set_link_dnssec_negative_trust_anchors(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1418 return call_link_method(userdata, message, bus_link_method_set_dnssec_negative_trust_anchors, error);
1419 }
1420
1421 static int bus_method_revert_link(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1422 return call_link_method(userdata, message, bus_link_method_revert, error);
1423 }
1424
1425 static int bus_method_get_link(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1426 _cleanup_free_ char *p = NULL;
1427 Manager *m = userdata;
1428 int r, ifindex;
1429 Link *l;
1430
1431 assert(message);
1432 assert(m);
1433
1434 assert_cc(sizeof(int) == sizeof(int32_t));
1435 r = sd_bus_message_read(message, "i", &ifindex);
1436 if (r < 0)
1437 return r;
1438
1439 r = get_any_link(m, ifindex, &l, error);
1440 if (r < 0)
1441 return r;
1442
1443 p = link_bus_path(l);
1444 if (!p)
1445 return -ENOMEM;
1446
1447 return sd_bus_reply_method_return(message, "o", p);
1448 }
1449
1450 static const sd_bus_vtable resolve_vtable[] = {
1451 SD_BUS_VTABLE_START(0),
1452 SD_BUS_PROPERTY("LLMNRHostname", "s", NULL, offsetof(Manager, llmnr_hostname), 0),
1453 SD_BUS_PROPERTY("DNS", "a(iiay)", bus_property_get_dns_servers, 0, 0),
1454 SD_BUS_PROPERTY("SearchDomains", "a(isb)", bus_property_get_search_domains, 0, 0),
1455 SD_BUS_PROPERTY("TransactionStatistics", "(tt)", bus_property_get_transaction_statistics, 0, 0),
1456 SD_BUS_PROPERTY("CacheStatistics", "(ttt)", bus_property_get_cache_statistics, 0, 0),
1457 SD_BUS_PROPERTY("DNSSECStatistics", "(tttt)", bus_property_get_dnssec_statistics, 0, 0),
1458 SD_BUS_PROPERTY("DNSSECSupported", "b", bus_property_get_dnssec_supported, 0, 0),
1459
1460 SD_BUS_METHOD("ResolveHostname", "isit", "a(iiay)st", bus_method_resolve_hostname, SD_BUS_VTABLE_UNPRIVILEGED),
1461 SD_BUS_METHOD("ResolveAddress", "iiayt", "a(is)t", bus_method_resolve_address, SD_BUS_VTABLE_UNPRIVILEGED),
1462 SD_BUS_METHOD("ResolveRecord", "isqqt", "a(iqqay)t", bus_method_resolve_record, SD_BUS_VTABLE_UNPRIVILEGED),
1463 SD_BUS_METHOD("ResolveService", "isssit", "a(qqqsa(iiay)s)aayssst", bus_method_resolve_service, SD_BUS_VTABLE_UNPRIVILEGED),
1464 SD_BUS_METHOD("ResetStatistics", NULL, NULL, bus_method_reset_statistics, 0),
1465 SD_BUS_METHOD("GetLink", "i", "o", bus_method_get_link, SD_BUS_VTABLE_UNPRIVILEGED),
1466 SD_BUS_METHOD("SetLinkDNS", "ia(iay)", NULL, bus_method_set_link_dns_servers, 0),
1467 SD_BUS_METHOD("SetLinkDomains", "ia(sb)", NULL, bus_method_set_link_search_domains, 0),
1468 SD_BUS_METHOD("SetLinkLLMNR", "is", NULL, bus_method_set_link_llmnr, 0),
1469 SD_BUS_METHOD("SetLinkMulticastDNS", "is", NULL, bus_method_set_link_mdns, 0),
1470 SD_BUS_METHOD("SetLinkDNSSEC", "is", NULL, bus_method_set_link_dnssec, 0),
1471 SD_BUS_METHOD("SetLinkDNSSECNegativeTrustAnchors", "ias", NULL, bus_method_set_link_dnssec_negative_trust_anchors, 0),
1472 SD_BUS_METHOD("RevertLink", "i", NULL, bus_method_revert_link, 0),
1473
1474 SD_BUS_VTABLE_END,
1475 };
1476
1477 static int on_bus_retry(sd_event_source *s, usec_t usec, void *userdata) {
1478 Manager *m = userdata;
1479
1480 assert(s);
1481 assert(m);
1482
1483 m->bus_retry_event_source = sd_event_source_unref(m->bus_retry_event_source);
1484
1485 manager_connect_bus(m);
1486 return 0;
1487 }
1488
1489 static int match_prepare_for_sleep(sd_bus_message *message, void *userdata, sd_bus_error *ret_error) {
1490 Manager *m = userdata;
1491 int b, r;
1492
1493 assert(message);
1494 assert(m);
1495
1496 r = sd_bus_message_read(message, "b", &b);
1497 if (r < 0) {
1498 log_debug_errno(r, "Failed to parse PrepareForSleep signal: %m");
1499 return 0;
1500 }
1501
1502 if (b)
1503 return 0;
1504
1505 log_debug("Coming back from suspend, verifying all RRs...");
1506
1507 manager_verify_all(m);
1508 return 0;
1509 }
1510
1511 int manager_connect_bus(Manager *m) {
1512 int r;
1513
1514 assert(m);
1515
1516 if (m->bus)
1517 return 0;
1518
1519 r = sd_bus_default_system(&m->bus);
1520 if (r < 0) {
1521 /* We failed to connect? Yuck, we must be in early
1522 * boot. Let's try in 5s again. As soon as we have
1523 * kdbus we can stop doing this... */
1524
1525 log_debug_errno(r, "Failed to connect to bus, trying again in 5s: %m");
1526
1527 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);
1528 if (r < 0)
1529 return log_error_errno(r, "Failed to install bus reconnect time event: %m");
1530
1531 (void) sd_event_source_set_description(m->bus_retry_event_source, "bus-retry");
1532 return 0;
1533 }
1534
1535 r = sd_bus_add_object_vtable(m->bus, NULL, "/org/freedesktop/resolve1", "org.freedesktop.resolve1.Manager", resolve_vtable, m);
1536 if (r < 0)
1537 return log_error_errno(r, "Failed to register object: %m");
1538
1539 r = sd_bus_add_fallback_vtable(m->bus, NULL, "/org/freedesktop/resolve1/link", "org.freedesktop.resolve1.Link", link_vtable, link_object_find, m);
1540 if (r < 0)
1541 return log_error_errno(r, "Failed to register link objects: %m");
1542
1543 r = sd_bus_add_node_enumerator(m->bus, NULL, "/org/freedesktop/resolve1/link", link_node_enumerator, m);
1544 if (r < 0)
1545 return log_error_errno(r, "Failed to register link enumerator: %m");
1546
1547 r = sd_bus_request_name(m->bus, "org.freedesktop.resolve1", 0);
1548 if (r < 0)
1549 return log_error_errno(r, "Failed to register name: %m");
1550
1551 r = sd_bus_attach_event(m->bus, m->event, 0);
1552 if (r < 0)
1553 return log_error_errno(r, "Failed to attach bus to event loop: %m");
1554
1555 r = sd_bus_add_match(m->bus, &m->prepare_for_sleep_slot,
1556 "type='signal',"
1557 "sender='org.freedesktop.login1',"
1558 "interface='org.freedesktop.login1.Manager',"
1559 "member='PrepareForSleep',"
1560 "path='/org/freedesktop/login1'",
1561 match_prepare_for_sleep,
1562 m);
1563 if (r < 0)
1564 log_error_errno(r, "Failed to add match for PrepareForSleep: %m");
1565
1566 return 0;
1567 }