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