]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/resolve/resolved-bus.c
tree-wide: use "hostname" spelling everywhere
[thirdparty/systemd.git] / src / resolve / resolved-bus.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
2
3 #include "alloc-util.h"
4 #include "bus-common-errors.h"
5 #include "bus-polkit.h"
6 #include "bus-util.h"
7 #include "dns-domain.h"
8 #include "memory-util.h"
9 #include "missing_capability.h"
10 #include "resolved-bus.h"
11 #include "resolved-def.h"
12 #include "resolved-dns-synthesize.h"
13 #include "resolved-dnssd-bus.h"
14 #include "resolved-dnssd.h"
15 #include "resolved-link-bus.h"
16 #include "socket-netlink.h"
17 #include "stdio-util.h"
18 #include "strv.h"
19 #include "syslog-util.h"
20 #include "user-util.h"
21 #include "utf8.h"
22
23 BUS_DEFINE_PROPERTY_GET_ENUM(bus_property_get_resolve_support, resolve_support, ResolveSupport);
24
25 static int reply_query_state(DnsQuery *q) {
26
27 switch (q->state) {
28
29 case DNS_TRANSACTION_NO_SERVERS:
30 return sd_bus_reply_method_errorf(q->request, BUS_ERROR_NO_NAME_SERVERS, "No appropriate name servers or networks for name found");
31
32 case DNS_TRANSACTION_TIMEOUT:
33 return sd_bus_reply_method_errorf(q->request, SD_BUS_ERROR_TIMEOUT, "Query timed out");
34
35 case DNS_TRANSACTION_ATTEMPTS_MAX_REACHED:
36 return sd_bus_reply_method_errorf(q->request, SD_BUS_ERROR_TIMEOUT, "All attempts to contact name servers or networks failed");
37
38 case DNS_TRANSACTION_INVALID_REPLY:
39 return sd_bus_reply_method_errorf(q->request, BUS_ERROR_INVALID_REPLY, "Received invalid reply");
40
41 case DNS_TRANSACTION_ERRNO:
42 return sd_bus_reply_method_errnof(q->request, q->answer_errno, "Lookup failed due to system error: %m");
43
44 case DNS_TRANSACTION_ABORTED:
45 return sd_bus_reply_method_errorf(q->request, BUS_ERROR_ABORTED, "Query aborted");
46
47 case DNS_TRANSACTION_DNSSEC_FAILED:
48 return sd_bus_reply_method_errorf(q->request, BUS_ERROR_DNSSEC_FAILED, "DNSSEC validation failed: %s",
49 dnssec_result_to_string(q->answer_dnssec_result));
50
51 case DNS_TRANSACTION_NO_TRUST_ANCHOR:
52 return sd_bus_reply_method_errorf(q->request, BUS_ERROR_NO_TRUST_ANCHOR, "No suitable trust anchor known");
53
54 case DNS_TRANSACTION_RR_TYPE_UNSUPPORTED:
55 return sd_bus_reply_method_errorf(q->request, BUS_ERROR_RR_TYPE_UNSUPPORTED, "Server does not support requested resource record type");
56
57 case DNS_TRANSACTION_NETWORK_DOWN:
58 return sd_bus_reply_method_errorf(q->request, BUS_ERROR_NETWORK_DOWN, "Network is down");
59
60 case DNS_TRANSACTION_NOT_FOUND:
61 /* We return this as NXDOMAIN. This is only generated when a host doesn't implement LLMNR/TCP, and we
62 * thus quickly know that we cannot resolve an in-addr.arpa or ip6.arpa address. */
63 return sd_bus_reply_method_errorf(q->request, _BUS_ERROR_DNS "NXDOMAIN", "'%s' not found", dns_query_string(q));
64
65 case DNS_TRANSACTION_RCODE_FAILURE: {
66 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
67
68 if (q->answer_rcode == DNS_RCODE_NXDOMAIN)
69 sd_bus_error_setf(&error, _BUS_ERROR_DNS "NXDOMAIN", "'%s' not found", dns_query_string(q));
70 else {
71 const char *rc, *n;
72 char p[DECIMAL_STR_MAX(q->answer_rcode)];
73
74 rc = dns_rcode_to_string(q->answer_rcode);
75 if (!rc) {
76 xsprintf(p, "%i", q->answer_rcode);
77 rc = p;
78 }
79
80 n = strjoina(_BUS_ERROR_DNS, rc);
81 sd_bus_error_setf(&error, n, "Could not resolve '%s', server or network returned error %s", dns_query_string(q), rc);
82 }
83
84 return sd_bus_reply_method_error(q->request, &error);
85 }
86
87 case DNS_TRANSACTION_NULL:
88 case DNS_TRANSACTION_PENDING:
89 case DNS_TRANSACTION_VALIDATING:
90 case DNS_TRANSACTION_SUCCESS:
91 default:
92 assert_not_reached("Impossible state");
93 }
94 }
95
96 static int append_address(sd_bus_message *reply, DnsResourceRecord *rr, int ifindex) {
97 int r;
98
99 assert(reply);
100 assert(rr);
101
102 r = sd_bus_message_open_container(reply, 'r', "iiay");
103 if (r < 0)
104 return r;
105
106 r = sd_bus_message_append(reply, "i", ifindex);
107 if (r < 0)
108 return r;
109
110 if (rr->key->type == DNS_TYPE_A) {
111 r = sd_bus_message_append(reply, "i", AF_INET);
112 if (r < 0)
113 return r;
114
115 r = sd_bus_message_append_array(reply, 'y', &rr->a.in_addr, sizeof(struct in_addr));
116
117 } else if (rr->key->type == DNS_TYPE_AAAA) {
118 r = sd_bus_message_append(reply, "i", AF_INET6);
119 if (r < 0)
120 return r;
121
122 r = sd_bus_message_append_array(reply, 'y', &rr->aaaa.in6_addr, sizeof(struct in6_addr));
123 } else
124 return -EAFNOSUPPORT;
125
126 if (r < 0)
127 return r;
128
129 r = sd_bus_message_close_container(reply);
130 if (r < 0)
131 return r;
132
133 return 0;
134 }
135
136 static void bus_method_resolve_hostname_complete(DnsQuery *q) {
137 _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *canonical = NULL;
138 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
139 _cleanup_free_ char *normalized = NULL;
140 DnsResourceRecord *rr;
141 unsigned added = 0;
142 int ifindex, r;
143
144 assert(q);
145
146 if (q->state != DNS_TRANSACTION_SUCCESS) {
147 r = reply_query_state(q);
148 goto finish;
149 }
150
151 r = dns_query_process_cname(q);
152 if (r == -ELOOP) {
153 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));
154 goto finish;
155 }
156 if (r < 0)
157 goto finish;
158 if (r == DNS_QUERY_RESTARTED) /* This was a cname, and the query was restarted. */
159 return;
160
161 r = sd_bus_message_new_method_return(q->request, &reply);
162 if (r < 0)
163 goto finish;
164
165 r = sd_bus_message_open_container(reply, 'a', "(iiay)");
166 if (r < 0)
167 goto finish;
168
169 DNS_ANSWER_FOREACH_IFINDEX(rr, ifindex, q->answer) {
170 DnsQuestion *question;
171
172 question = dns_query_question_for_protocol(q, q->answer_protocol);
173
174 r = dns_question_matches_rr(question, rr, DNS_SEARCH_DOMAIN_NAME(q->answer_search_domain));
175 if (r < 0)
176 goto finish;
177 if (r == 0)
178 continue;
179
180 r = append_address(reply, rr, ifindex);
181 if (r < 0)
182 goto finish;
183
184 if (!canonical)
185 canonical = dns_resource_record_ref(rr);
186
187 added++;
188 }
189
190 if (added <= 0) {
191 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));
192 goto finish;
193 }
194
195 r = sd_bus_message_close_container(reply);
196 if (r < 0)
197 goto finish;
198
199 /* The key names are not necessarily normalized, make sure that they are when we return them to our bus
200 * clients. */
201 r = dns_name_normalize(dns_resource_key_name(canonical->key), 0, &normalized);
202 if (r < 0)
203 goto finish;
204
205 /* Return the precise spelling and uppercasing and CNAME target reported by the server */
206 assert(canonical);
207 r = sd_bus_message_append(
208 reply, "st",
209 normalized,
210 SD_RESOLVED_FLAGS_MAKE(q->answer_protocol, q->answer_family, dns_query_fully_authenticated(q)));
211 if (r < 0)
212 goto finish;
213
214 r = sd_bus_send(q->manager->bus, reply, NULL);
215
216 finish:
217 if (r < 0) {
218 log_error_errno(r, "Failed to send hostname reply: %m");
219 sd_bus_reply_method_errno(q->request, r, NULL);
220 }
221
222 dns_query_free(q);
223 }
224
225 static int check_ifindex_flags(int ifindex, uint64_t *flags, uint64_t ok, sd_bus_error *error) {
226 assert(flags);
227
228 if (ifindex < 0)
229 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid interface index");
230
231 if (*flags & ~(SD_RESOLVED_PROTOCOLS_ALL|SD_RESOLVED_NO_CNAME|ok))
232 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid flags parameter");
233
234 if ((*flags & SD_RESOLVED_PROTOCOLS_ALL) == 0) /* If no protocol is enabled, enable all */
235 *flags |= SD_RESOLVED_PROTOCOLS_ALL;
236
237 return 0;
238 }
239
240 static int parse_as_address(sd_bus_message *m, int ifindex, const char *hostname, int family, uint64_t flags) {
241 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
242 _cleanup_free_ char *canonical = NULL;
243 union in_addr_union parsed;
244 int r, ff, parsed_ifindex = 0;
245
246 /* Check if the hostname is actually already an IP address formatted as string. In that case just parse it,
247 * let's not attempt to look it up. */
248
249 r = in_addr_ifindex_from_string_auto(hostname, &ff, &parsed, &parsed_ifindex);
250 if (r < 0) /* not an address */
251 return 0;
252
253 if (family != AF_UNSPEC && ff != family)
254 return sd_bus_reply_method_errorf(m, BUS_ERROR_NO_SUCH_RR, "The specified address is not of the requested family.");
255 if (ifindex > 0 && parsed_ifindex > 0 && parsed_ifindex != ifindex)
256 return sd_bus_reply_method_errorf(m, BUS_ERROR_NO_SUCH_RR, "The specified address interface index does not match requested interface.");
257
258 if (parsed_ifindex > 0)
259 ifindex = parsed_ifindex;
260
261 r = sd_bus_message_new_method_return(m, &reply);
262 if (r < 0)
263 return r;
264
265 r = sd_bus_message_open_container(reply, 'a', "(iiay)");
266 if (r < 0)
267 return r;
268
269 r = sd_bus_message_open_container(reply, 'r', "iiay");
270 if (r < 0)
271 return r;
272
273 r = sd_bus_message_append(reply, "ii", ifindex, ff);
274 if (r < 0)
275 return r;
276
277 r = sd_bus_message_append_array(reply, 'y', &parsed, FAMILY_ADDRESS_SIZE(ff));
278 if (r < 0)
279 return r;
280
281 r = sd_bus_message_close_container(reply);
282 if (r < 0)
283 return r;
284
285 r = sd_bus_message_close_container(reply);
286 if (r < 0)
287 return r;
288
289 /* When an IP address is specified we just return it as canonical name, in order to avoid a DNS
290 * look-up. However, we reformat it to make sure it's in a truly canonical form (i.e. on IPv6 the inner
291 * omissions are always done the same way). */
292 r = in_addr_ifindex_to_string(ff, &parsed, ifindex, &canonical);
293 if (r < 0)
294 return r;
295
296 r = sd_bus_message_append(reply, "st", canonical,
297 SD_RESOLVED_FLAGS_MAKE(dns_synthesize_protocol(flags), ff, true));
298 if (r < 0)
299 return r;
300
301 return sd_bus_send(sd_bus_message_get_bus(m), reply, NULL);
302 }
303
304 static int bus_method_resolve_hostname(sd_bus_message *message, void *userdata, sd_bus_error *error) {
305 _cleanup_(dns_question_unrefp) DnsQuestion *question_idna = NULL, *question_utf8 = NULL;
306 Manager *m = userdata;
307 const char *hostname;
308 int family, ifindex;
309 uint64_t flags;
310 DnsQuery *q;
311 int r;
312
313 assert(message);
314 assert(m);
315
316 assert_cc(sizeof(int) == sizeof(int32_t));
317
318 r = sd_bus_message_read(message, "isit", &ifindex, &hostname, &family, &flags);
319 if (r < 0)
320 return r;
321
322 if (!IN_SET(family, AF_INET, AF_INET6, AF_UNSPEC))
323 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown address family %i", family);
324
325 r = check_ifindex_flags(ifindex, &flags, SD_RESOLVED_NO_SEARCH, error);
326 if (r < 0)
327 return r;
328
329 r = parse_as_address(message, ifindex, hostname, family, flags);
330 if (r != 0)
331 return r;
332
333 r = dns_name_is_valid(hostname);
334 if (r < 0)
335 return r;
336 if (r == 0)
337 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid hostname '%s'", hostname);
338
339 r = dns_question_new_address(&question_utf8, family, hostname, false);
340 if (r < 0)
341 return r;
342
343 r = dns_question_new_address(&question_idna, family, hostname, true);
344 if (r < 0 && r != -EALREADY)
345 return r;
346
347 r = dns_query_new(m, &q, question_utf8, question_idna ?: question_utf8, ifindex, flags);
348 if (r < 0)
349 return r;
350
351 q->request = sd_bus_message_ref(message);
352 q->request_family = family;
353 q->complete = bus_method_resolve_hostname_complete;
354 q->suppress_unroutable_family = family == AF_UNSPEC;
355
356 r = dns_query_bus_track(q, message);
357 if (r < 0)
358 goto fail;
359
360 r = dns_query_go(q);
361 if (r < 0)
362 goto fail;
363
364 return 1;
365
366 fail:
367 dns_query_free(q);
368 return r;
369 }
370
371 static void bus_method_resolve_address_complete(DnsQuery *q) {
372 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
373 DnsQuestion *question;
374 DnsResourceRecord *rr;
375 unsigned added = 0;
376 int ifindex, r;
377
378 assert(q);
379
380 if (q->state != DNS_TRANSACTION_SUCCESS) {
381 r = reply_query_state(q);
382 goto finish;
383 }
384
385 r = dns_query_process_cname(q);
386 if (r == -ELOOP) {
387 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));
388 goto finish;
389 }
390 if (r < 0)
391 goto finish;
392 if (r == DNS_QUERY_RESTARTED) /* This was a cname, and the query was restarted. */
393 return;
394
395 r = sd_bus_message_new_method_return(q->request, &reply);
396 if (r < 0)
397 goto finish;
398
399 r = sd_bus_message_open_container(reply, 'a', "(is)");
400 if (r < 0)
401 goto finish;
402
403 question = dns_query_question_for_protocol(q, q->answer_protocol);
404
405 DNS_ANSWER_FOREACH_IFINDEX(rr, ifindex, q->answer) {
406 _cleanup_free_ char *normalized = NULL;
407
408 r = dns_question_matches_rr(question, rr, NULL);
409 if (r < 0)
410 goto finish;
411 if (r == 0)
412 continue;
413
414 r = dns_name_normalize(rr->ptr.name, 0, &normalized);
415 if (r < 0)
416 goto finish;
417
418 r = sd_bus_message_append(reply, "(is)", ifindex, normalized);
419 if (r < 0)
420 goto finish;
421
422 added++;
423 }
424
425 if (added <= 0) {
426 _cleanup_free_ char *ip = NULL;
427
428 (void) in_addr_to_string(q->request_family, &q->request_address, &ip);
429 r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_NO_SUCH_RR,
430 "Address '%s' does not have any RR of requested type", strnull(ip));
431 goto finish;
432 }
433
434 r = sd_bus_message_close_container(reply);
435 if (r < 0)
436 goto finish;
437
438 r = sd_bus_message_append(reply, "t", SD_RESOLVED_FLAGS_MAKE(q->answer_protocol, q->answer_family, dns_query_fully_authenticated(q)));
439 if (r < 0)
440 goto finish;
441
442 r = sd_bus_send(q->manager->bus, reply, NULL);
443
444 finish:
445 if (r < 0) {
446 log_error_errno(r, "Failed to send address reply: %m");
447 sd_bus_reply_method_errno(q->request, r, NULL);
448 }
449
450 dns_query_free(q);
451 }
452
453 static int bus_method_resolve_address(sd_bus_message *message, void *userdata, sd_bus_error *error) {
454 _cleanup_(dns_question_unrefp) DnsQuestion *question = NULL;
455 Manager *m = userdata;
456 int family, ifindex;
457 uint64_t flags;
458 const void *d;
459 DnsQuery *q;
460 size_t sz;
461 int r;
462
463 assert(message);
464 assert(m);
465
466 assert_cc(sizeof(int) == sizeof(int32_t));
467
468 r = sd_bus_message_read(message, "ii", &ifindex, &family);
469 if (r < 0)
470 return r;
471
472 if (!IN_SET(family, AF_INET, AF_INET6))
473 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown address family %i", family);
474
475 r = sd_bus_message_read_array(message, 'y', &d, &sz);
476 if (r < 0)
477 return r;
478
479 if (sz != FAMILY_ADDRESS_SIZE(family))
480 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid address size");
481
482 r = sd_bus_message_read(message, "t", &flags);
483 if (r < 0)
484 return r;
485
486 r = check_ifindex_flags(ifindex, &flags, 0, error);
487 if (r < 0)
488 return r;
489
490 r = dns_question_new_reverse(&question, family, d);
491 if (r < 0)
492 return r;
493
494 r = dns_query_new(m, &q, question, question, ifindex, flags|SD_RESOLVED_NO_SEARCH);
495 if (r < 0)
496 return r;
497
498 q->request = sd_bus_message_ref(message);
499 q->request_family = family;
500 memcpy(&q->request_address, d, sz);
501 q->complete = bus_method_resolve_address_complete;
502
503 r = dns_query_bus_track(q, message);
504 if (r < 0)
505 goto fail;
506
507 r = dns_query_go(q);
508 if (r < 0)
509 goto fail;
510
511 return 1;
512
513 fail:
514 dns_query_free(q);
515 return r;
516 }
517
518 static int bus_message_append_rr(sd_bus_message *m, DnsResourceRecord *rr, int ifindex) {
519 int r;
520
521 assert(m);
522 assert(rr);
523
524 r = sd_bus_message_open_container(m, 'r', "iqqay");
525 if (r < 0)
526 return r;
527
528 r = sd_bus_message_append(m, "iqq",
529 ifindex,
530 rr->key->class,
531 rr->key->type);
532 if (r < 0)
533 return r;
534
535 r = dns_resource_record_to_wire_format(rr, false);
536 if (r < 0)
537 return r;
538
539 r = sd_bus_message_append_array(m, 'y', rr->wire_format, rr->wire_format_size);
540 if (r < 0)
541 return r;
542
543 return sd_bus_message_close_container(m);
544 }
545
546 static void bus_method_resolve_record_complete(DnsQuery *q) {
547 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
548 DnsResourceRecord *rr;
549 DnsQuestion *question;
550 unsigned added = 0;
551 int ifindex;
552 int r;
553
554 assert(q);
555
556 if (q->state != DNS_TRANSACTION_SUCCESS) {
557 r = reply_query_state(q);
558 goto finish;
559 }
560
561 r = dns_query_process_cname(q);
562 if (r == -ELOOP) {
563 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));
564 goto finish;
565 }
566 if (r < 0)
567 goto finish;
568 if (r == DNS_QUERY_RESTARTED) /* This was a cname, and the query was restarted. */
569 return;
570
571 r = sd_bus_message_new_method_return(q->request, &reply);
572 if (r < 0)
573 goto finish;
574
575 r = sd_bus_message_open_container(reply, 'a', "(iqqay)");
576 if (r < 0)
577 goto finish;
578
579 question = dns_query_question_for_protocol(q, q->answer_protocol);
580
581 DNS_ANSWER_FOREACH_IFINDEX(rr, ifindex, q->answer) {
582 r = dns_question_matches_rr(question, rr, NULL);
583 if (r < 0)
584 goto finish;
585 if (r == 0)
586 continue;
587
588 r = bus_message_append_rr(reply, rr, ifindex);
589 if (r < 0)
590 goto finish;
591
592 added++;
593 }
594
595 if (added <= 0) {
596 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));
597 goto finish;
598 }
599
600 r = sd_bus_message_close_container(reply);
601 if (r < 0)
602 goto finish;
603
604 r = sd_bus_message_append(reply, "t", SD_RESOLVED_FLAGS_MAKE(q->answer_protocol, q->answer_family, dns_query_fully_authenticated(q)));
605 if (r < 0)
606 goto finish;
607
608 r = sd_bus_send(q->manager->bus, reply, NULL);
609
610 finish:
611 if (r < 0) {
612 log_error_errno(r, "Failed to send record reply: %m");
613 sd_bus_reply_method_errno(q->request, r, NULL);
614 }
615
616 dns_query_free(q);
617 }
618
619 static int bus_method_resolve_record(sd_bus_message *message, void *userdata, sd_bus_error *error) {
620 _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
621 _cleanup_(dns_question_unrefp) DnsQuestion *question = NULL;
622 Manager *m = userdata;
623 uint16_t class, type;
624 const char *name;
625 int r, ifindex;
626 uint64_t flags;
627 DnsQuery *q;
628
629 assert(message);
630 assert(m);
631
632 assert_cc(sizeof(int) == sizeof(int32_t));
633
634 r = sd_bus_message_read(message, "isqqt", &ifindex, &name, &class, &type, &flags);
635 if (r < 0)
636 return r;
637
638 r = dns_name_is_valid(name);
639 if (r < 0)
640 return r;
641 if (r == 0)
642 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid name '%s'", name);
643
644 if (!dns_type_is_valid_query(type))
645 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Specified resource record type %" PRIu16 " may not be used in a query.", type);
646 if (dns_type_is_zone_transer(type))
647 return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Zone transfers not permitted via this programming interface.");
648 if (dns_type_is_obsolete(type))
649 return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Specified DNS resource record type %" PRIu16 " is obsolete.", type);
650
651 r = check_ifindex_flags(ifindex, &flags, 0, error);
652 if (r < 0)
653 return r;
654
655 question = dns_question_new(1);
656 if (!question)
657 return -ENOMEM;
658
659 key = dns_resource_key_new(class, type, name);
660 if (!key)
661 return -ENOMEM;
662
663 r = dns_question_add(question, key);
664 if (r < 0)
665 return r;
666
667 r = dns_query_new(m, &q, question, question, ifindex, flags|SD_RESOLVED_NO_SEARCH);
668 if (r < 0)
669 return r;
670
671 /* Let's request that the TTL is fixed up for locally cached entries, after all we return it in the wire format
672 * blob */
673 q->clamp_ttl = true;
674
675 q->request = sd_bus_message_ref(message);
676 q->complete = bus_method_resolve_record_complete;
677
678 r = dns_query_bus_track(q, message);
679 if (r < 0)
680 goto fail;
681
682 r = dns_query_go(q);
683 if (r < 0)
684 goto fail;
685
686 return 1;
687
688 fail:
689 dns_query_free(q);
690 return r;
691 }
692
693 static int append_srv(DnsQuery *q, sd_bus_message *reply, DnsResourceRecord *rr) {
694 _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *canonical = NULL;
695 _cleanup_free_ char *normalized = NULL;
696 DnsQuery *aux;
697 int r;
698
699 assert(q);
700 assert(reply);
701 assert(rr);
702 assert(rr->key);
703
704 if (rr->key->type != DNS_TYPE_SRV)
705 return 0;
706
707 if ((q->flags & SD_RESOLVED_NO_ADDRESS) == 0) {
708 /* First, let's see if we could find an appropriate A or AAAA
709 * record for the SRV record */
710 LIST_FOREACH(auxiliary_queries, aux, q->auxiliary_queries) {
711 DnsResourceRecord *zz;
712 DnsQuestion *question;
713
714 if (aux->state != DNS_TRANSACTION_SUCCESS)
715 continue;
716 if (aux->auxiliary_result != 0)
717 continue;
718
719 question = dns_query_question_for_protocol(aux, aux->answer_protocol);
720
721 r = dns_name_equal(dns_question_first_name(question), rr->srv.name);
722 if (r < 0)
723 return r;
724 if (r == 0)
725 continue;
726
727 DNS_ANSWER_FOREACH(zz, aux->answer) {
728
729 r = dns_question_matches_rr(question, zz, NULL);
730 if (r < 0)
731 return r;
732 if (r == 0)
733 continue;
734
735 canonical = dns_resource_record_ref(zz);
736 break;
737 }
738
739 if (canonical)
740 break;
741 }
742
743 /* Is there are successful A/AAAA lookup for this SRV RR? If not, don't add it */
744 if (!canonical)
745 return 0;
746 }
747
748 r = sd_bus_message_open_container(reply, 'r', "qqqsa(iiay)s");
749 if (r < 0)
750 return r;
751
752 r = dns_name_normalize(rr->srv.name, 0, &normalized);
753 if (r < 0)
754 return r;
755
756 r = sd_bus_message_append(
757 reply,
758 "qqqs",
759 rr->srv.priority, rr->srv.weight, rr->srv.port, normalized);
760 if (r < 0)
761 return r;
762
763 r = sd_bus_message_open_container(reply, 'a', "(iiay)");
764 if (r < 0)
765 return r;
766
767 if ((q->flags & SD_RESOLVED_NO_ADDRESS) == 0) {
768 LIST_FOREACH(auxiliary_queries, aux, q->auxiliary_queries) {
769 DnsResourceRecord *zz;
770 DnsQuestion *question;
771 int ifindex;
772
773 if (aux->state != DNS_TRANSACTION_SUCCESS)
774 continue;
775 if (aux->auxiliary_result != 0)
776 continue;
777
778 question = dns_query_question_for_protocol(aux, aux->answer_protocol);
779
780 r = dns_name_equal(dns_question_first_name(question), rr->srv.name);
781 if (r < 0)
782 return r;
783 if (r == 0)
784 continue;
785
786 DNS_ANSWER_FOREACH_IFINDEX(zz, ifindex, aux->answer) {
787
788 r = dns_question_matches_rr(question, zz, NULL);
789 if (r < 0)
790 return r;
791 if (r == 0)
792 continue;
793
794 r = append_address(reply, zz, ifindex);
795 if (r < 0)
796 return r;
797 }
798 }
799 }
800
801 r = sd_bus_message_close_container(reply);
802 if (r < 0)
803 return r;
804
805 if (canonical) {
806 normalized = mfree(normalized);
807
808 r = dns_name_normalize(dns_resource_key_name(canonical->key), 0, &normalized);
809 if (r < 0)
810 return r;
811 }
812
813 /* Note that above we appended the hostname as encoded in the
814 * SRV, and here the canonical hostname this maps to. */
815 r = sd_bus_message_append(reply, "s", normalized);
816 if (r < 0)
817 return r;
818
819 r = sd_bus_message_close_container(reply);
820 if (r < 0)
821 return r;
822
823 return 1;
824 }
825
826 static int append_txt(sd_bus_message *reply, DnsResourceRecord *rr) {
827 DnsTxtItem *i;
828 int r;
829
830 assert(reply);
831 assert(rr);
832 assert(rr->key);
833
834 if (rr->key->type != DNS_TYPE_TXT)
835 return 0;
836
837 LIST_FOREACH(items, i, rr->txt.items) {
838
839 if (i->length <= 0)
840 continue;
841
842 r = sd_bus_message_append_array(reply, 'y', i->data, i->length);
843 if (r < 0)
844 return r;
845 }
846
847 return 1;
848 }
849
850 static void resolve_service_all_complete(DnsQuery *q) {
851 _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *canonical = NULL;
852 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
853 _cleanup_free_ char *name = NULL, *type = NULL, *domain = NULL;
854 DnsQuestion *question;
855 DnsResourceRecord *rr;
856 unsigned added = 0;
857 DnsQuery *aux;
858 int r;
859
860 assert(q);
861
862 if (q->block_all_complete > 0)
863 return;
864
865 if ((q->flags & SD_RESOLVED_NO_ADDRESS) == 0) {
866 DnsQuery *bad = NULL;
867 bool have_success = false;
868
869 LIST_FOREACH(auxiliary_queries, aux, q->auxiliary_queries) {
870
871 switch (aux->state) {
872
873 case DNS_TRANSACTION_PENDING:
874 /* If an auxiliary query is still pending, let's wait */
875 return;
876
877 case DNS_TRANSACTION_SUCCESS:
878 if (aux->auxiliary_result == 0)
879 have_success = true;
880 else
881 bad = aux;
882 break;
883
884 default:
885 bad = aux;
886 break;
887 }
888 }
889
890 if (!have_success) {
891 /* We can only return one error, hence pick the last error we encountered */
892
893 assert(bad);
894
895 if (bad->state == DNS_TRANSACTION_SUCCESS) {
896 assert(bad->auxiliary_result != 0);
897
898 if (bad->auxiliary_result == -ELOOP) {
899 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));
900 goto finish;
901 }
902
903 r = bad->auxiliary_result;
904 goto finish;
905 }
906
907 r = reply_query_state(bad);
908 goto finish;
909 }
910 }
911
912 r = sd_bus_message_new_method_return(q->request, &reply);
913 if (r < 0)
914 goto finish;
915
916 r = sd_bus_message_open_container(reply, 'a', "(qqqsa(iiay)s)");
917 if (r < 0)
918 goto finish;
919
920 question = dns_query_question_for_protocol(q, q->answer_protocol);
921 DNS_ANSWER_FOREACH(rr, q->answer) {
922 r = dns_question_matches_rr(question, rr, NULL);
923 if (r < 0)
924 goto finish;
925 if (r == 0)
926 continue;
927
928 r = append_srv(q, reply, rr);
929 if (r < 0)
930 goto finish;
931 if (r == 0) /* not an SRV record */
932 continue;
933
934 if (!canonical)
935 canonical = dns_resource_record_ref(rr);
936
937 added++;
938 }
939
940 if (added <= 0) {
941 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));
942 goto finish;
943 }
944
945 r = sd_bus_message_close_container(reply);
946 if (r < 0)
947 goto finish;
948
949 r = sd_bus_message_open_container(reply, 'a', "ay");
950 if (r < 0)
951 goto finish;
952
953 DNS_ANSWER_FOREACH(rr, q->answer) {
954 r = dns_question_matches_rr(question, rr, NULL);
955 if (r < 0)
956 goto finish;
957 if (r == 0)
958 continue;
959
960 r = append_txt(reply, rr);
961 if (r < 0)
962 goto finish;
963 }
964
965 r = sd_bus_message_close_container(reply);
966 if (r < 0)
967 goto finish;
968
969 assert(canonical);
970 r = dns_service_split(dns_resource_key_name(canonical->key), &name, &type, &domain);
971 if (r < 0)
972 goto finish;
973
974 r = sd_bus_message_append(
975 reply,
976 "ssst",
977 name, type, domain,
978 SD_RESOLVED_FLAGS_MAKE(q->answer_protocol, q->answer_family, dns_query_fully_authenticated(q)));
979 if (r < 0)
980 goto finish;
981
982 r = sd_bus_send(q->manager->bus, reply, NULL);
983
984 finish:
985 if (r < 0) {
986 log_error_errno(r, "Failed to send service reply: %m");
987 sd_bus_reply_method_errno(q->request, r, NULL);
988 }
989
990 dns_query_free(q);
991 }
992
993 static void resolve_service_hostname_complete(DnsQuery *q) {
994 int r;
995
996 assert(q);
997 assert(q->auxiliary_for);
998
999 if (q->state != DNS_TRANSACTION_SUCCESS) {
1000 resolve_service_all_complete(q->auxiliary_for);
1001 return;
1002 }
1003
1004 r = dns_query_process_cname(q);
1005 if (r == DNS_QUERY_RESTARTED) /* This was a cname, and the query was restarted. */
1006 return;
1007
1008 /* This auxiliary lookup is finished or failed, let's see if all are finished now. */
1009 q->auxiliary_result = r;
1010 resolve_service_all_complete(q->auxiliary_for);
1011 }
1012
1013 static int resolve_service_hostname(DnsQuery *q, DnsResourceRecord *rr, int ifindex) {
1014 _cleanup_(dns_question_unrefp) DnsQuestion *question = NULL;
1015 DnsQuery *aux;
1016 int r;
1017
1018 assert(q);
1019 assert(rr);
1020 assert(rr->key);
1021 assert(rr->key->type == DNS_TYPE_SRV);
1022
1023 /* OK, we found an SRV record for the service. Let's resolve
1024 * the hostname included in it */
1025
1026 r = dns_question_new_address(&question, q->request_family, rr->srv.name, false);
1027 if (r < 0)
1028 return r;
1029
1030 r = dns_query_new(q->manager, &aux, question, question, ifindex, q->flags|SD_RESOLVED_NO_SEARCH);
1031 if (r < 0)
1032 return r;
1033
1034 aux->request_family = q->request_family;
1035 aux->complete = resolve_service_hostname_complete;
1036
1037 r = dns_query_make_auxiliary(aux, q);
1038 if (r == -EAGAIN) {
1039 /* Too many auxiliary lookups? If so, don't complain,
1040 * let's just not add this one, we already have more
1041 * than enough */
1042
1043 dns_query_free(aux);
1044 return 0;
1045 }
1046 if (r < 0)
1047 goto fail;
1048
1049 /* Note that auxiliary queries do not track the original bus
1050 * client, only the primary request does that. */
1051
1052 r = dns_query_go(aux);
1053 if (r < 0)
1054 goto fail;
1055
1056 return 1;
1057
1058 fail:
1059 dns_query_free(aux);
1060 return r;
1061 }
1062
1063 static void bus_method_resolve_service_complete(DnsQuery *q) {
1064 bool has_root_domain = false;
1065 DnsResourceRecord *rr;
1066 DnsQuestion *question;
1067 unsigned found = 0;
1068 int ifindex, r;
1069
1070 assert(q);
1071
1072 if (q->state != DNS_TRANSACTION_SUCCESS) {
1073 r = reply_query_state(q);
1074 goto finish;
1075 }
1076
1077 r = dns_query_process_cname(q);
1078 if (r == -ELOOP) {
1079 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));
1080 goto finish;
1081 }
1082 if (r < 0)
1083 goto finish;
1084 if (r == DNS_QUERY_RESTARTED) /* This was a cname, and the query was restarted. */
1085 return;
1086
1087 question = dns_query_question_for_protocol(q, q->answer_protocol);
1088
1089 DNS_ANSWER_FOREACH_IFINDEX(rr, ifindex, q->answer) {
1090 r = dns_question_matches_rr(question, rr, NULL);
1091 if (r < 0)
1092 goto finish;
1093 if (r == 0)
1094 continue;
1095
1096 if (rr->key->type != DNS_TYPE_SRV)
1097 continue;
1098
1099 if (dns_name_is_root(rr->srv.name)) {
1100 has_root_domain = true;
1101 continue;
1102 }
1103
1104 if ((q->flags & SD_RESOLVED_NO_ADDRESS) == 0) {
1105 q->block_all_complete++;
1106 r = resolve_service_hostname(q, rr, ifindex);
1107 q->block_all_complete--;
1108
1109 if (r < 0)
1110 goto finish;
1111 }
1112
1113 found++;
1114 }
1115
1116 if (has_root_domain && found <= 0) {
1117 /* If there's exactly one SRV RR and it uses
1118 * the root domain as hostname, then the
1119 * service is explicitly not offered on the
1120 * domain. Report this as a recognizable
1121 * error. See RFC 2782, Section "Usage
1122 * Rules". */
1123 r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_NO_SUCH_SERVICE, "'%s' does not provide the requested service", dns_query_string(q));
1124 goto finish;
1125 }
1126
1127 if (found <= 0) {
1128 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));
1129 goto finish;
1130 }
1131
1132 /* Maybe we are already finished? check now... */
1133 resolve_service_all_complete(q);
1134 return;
1135
1136 finish:
1137 if (r < 0) {
1138 log_error_errno(r, "Failed to send service reply: %m");
1139 sd_bus_reply_method_errno(q->request, r, NULL);
1140 }
1141
1142 dns_query_free(q);
1143 }
1144
1145 static int bus_method_resolve_service(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1146 _cleanup_(dns_question_unrefp) DnsQuestion *question_idna = NULL, *question_utf8 = NULL;
1147 const char *name, *type, *domain;
1148 Manager *m = userdata;
1149 int family, ifindex;
1150 uint64_t flags;
1151 DnsQuery *q;
1152 int r;
1153
1154 assert(message);
1155 assert(m);
1156
1157 assert_cc(sizeof(int) == sizeof(int32_t));
1158
1159 r = sd_bus_message_read(message, "isssit", &ifindex, &name, &type, &domain, &family, &flags);
1160 if (r < 0)
1161 return r;
1162
1163 if (!IN_SET(family, AF_INET, AF_INET6, AF_UNSPEC))
1164 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown address family %i", family);
1165
1166 if (isempty(name))
1167 name = NULL;
1168 else if (!dns_service_name_is_valid(name))
1169 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid service name '%s'", name);
1170
1171 if (isempty(type))
1172 type = NULL;
1173 else if (!dns_srv_type_is_valid(type))
1174 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid SRV service type '%s'", type);
1175
1176 r = dns_name_is_valid(domain);
1177 if (r < 0)
1178 return r;
1179 if (r == 0)
1180 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid domain '%s'", domain);
1181
1182 if (name && !type)
1183 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Service name cannot be specified without service type.");
1184
1185 r = check_ifindex_flags(ifindex, &flags, SD_RESOLVED_NO_TXT|SD_RESOLVED_NO_ADDRESS, error);
1186 if (r < 0)
1187 return r;
1188
1189 r = dns_question_new_service(&question_utf8, name, type, domain, !(flags & SD_RESOLVED_NO_TXT), false);
1190 if (r < 0)
1191 return r;
1192
1193 r = dns_question_new_service(&question_idna, name, type, domain, !(flags & SD_RESOLVED_NO_TXT), true);
1194 if (r < 0)
1195 return r;
1196
1197 r = dns_query_new(m, &q, question_utf8, question_idna, ifindex, flags|SD_RESOLVED_NO_SEARCH);
1198 if (r < 0)
1199 return r;
1200
1201 q->request = sd_bus_message_ref(message);
1202 q->request_family = family;
1203 q->complete = bus_method_resolve_service_complete;
1204
1205 r = dns_query_bus_track(q, message);
1206 if (r < 0)
1207 goto fail;
1208
1209 r = dns_query_go(q);
1210 if (r < 0)
1211 goto fail;
1212
1213 return 1;
1214
1215 fail:
1216 dns_query_free(q);
1217 return r;
1218 }
1219
1220 int bus_dns_server_append(sd_bus_message *reply, DnsServer *s, bool with_ifindex) {
1221 int r;
1222
1223 assert(reply);
1224
1225 if (!s) {
1226 if (with_ifindex)
1227 return sd_bus_message_append(reply, "(iiay)", 0, AF_UNSPEC, 0);
1228 else
1229 return sd_bus_message_append(reply, "(iay)", AF_UNSPEC, 0);
1230 }
1231
1232 r = sd_bus_message_open_container(reply, 'r', with_ifindex ? "iiay" : "iay");
1233 if (r < 0)
1234 return r;
1235
1236 if (with_ifindex) {
1237 r = sd_bus_message_append(reply, "i", dns_server_ifindex(s));
1238 if (r < 0)
1239 return r;
1240 }
1241
1242 r = sd_bus_message_append(reply, "i", s->family);
1243 if (r < 0)
1244 return r;
1245
1246 r = sd_bus_message_append_array(reply, 'y', &s->address, FAMILY_ADDRESS_SIZE(s->family));
1247 if (r < 0)
1248 return r;
1249
1250 return sd_bus_message_close_container(reply);
1251 }
1252
1253 static int bus_property_get_dns_servers(
1254 sd_bus *bus,
1255 const char *path,
1256 const char *interface,
1257 const char *property,
1258 sd_bus_message *reply,
1259 void *userdata,
1260 sd_bus_error *error) {
1261
1262 Manager *m = userdata;
1263 DnsServer *s;
1264 Iterator i;
1265 Link *l;
1266 int r;
1267
1268 assert(reply);
1269 assert(m);
1270
1271 r = sd_bus_message_open_container(reply, 'a', "(iiay)");
1272 if (r < 0)
1273 return r;
1274
1275 LIST_FOREACH(servers, s, m->dns_servers) {
1276 r = bus_dns_server_append(reply, s, true);
1277 if (r < 0)
1278 return r;
1279 }
1280
1281 HASHMAP_FOREACH(l, m->links, i)
1282 LIST_FOREACH(servers, s, l->dns_servers) {
1283 r = bus_dns_server_append(reply, s, true);
1284 if (r < 0)
1285 return r;
1286 }
1287
1288 return sd_bus_message_close_container(reply);
1289 }
1290
1291 static int bus_property_get_fallback_dns_servers(
1292 sd_bus *bus,
1293 const char *path,
1294 const char *interface,
1295 const char *property,
1296 sd_bus_message *reply,
1297 void *userdata,
1298 sd_bus_error *error) {
1299
1300 DnsServer *s, **f = userdata;
1301 int r;
1302
1303 assert(reply);
1304 assert(f);
1305
1306 r = sd_bus_message_open_container(reply, 'a', "(iiay)");
1307 if (r < 0)
1308 return r;
1309
1310 LIST_FOREACH(servers, s, *f) {
1311 r = bus_dns_server_append(reply, s, true);
1312 if (r < 0)
1313 return r;
1314 }
1315
1316 return sd_bus_message_close_container(reply);
1317 }
1318
1319 static int bus_property_get_current_dns_server(
1320 sd_bus *bus,
1321 const char *path,
1322 const char *interface,
1323 const char *property,
1324 sd_bus_message *reply,
1325 void *userdata,
1326 sd_bus_error *error) {
1327
1328 DnsServer *s;
1329
1330 assert(reply);
1331 assert(userdata);
1332
1333 s = *(DnsServer **) userdata;
1334
1335 return bus_dns_server_append(reply, s, true);
1336 }
1337
1338 static int bus_property_get_domains(
1339 sd_bus *bus,
1340 const char *path,
1341 const char *interface,
1342 const char *property,
1343 sd_bus_message *reply,
1344 void *userdata,
1345 sd_bus_error *error) {
1346
1347 Manager *m = userdata;
1348 DnsSearchDomain *d;
1349 Iterator i;
1350 Link *l;
1351 int r;
1352
1353 assert(reply);
1354 assert(m);
1355
1356 r = sd_bus_message_open_container(reply, 'a', "(isb)");
1357 if (r < 0)
1358 return r;
1359
1360 LIST_FOREACH(domains, d, m->search_domains) {
1361 r = sd_bus_message_append(reply, "(isb)", 0, d->name, d->route_only);
1362 if (r < 0)
1363 return r;
1364 }
1365
1366 HASHMAP_FOREACH(l, m->links, i) {
1367 LIST_FOREACH(domains, d, l->search_domains) {
1368 r = sd_bus_message_append(reply, "(isb)", l->ifindex, d->name, d->route_only);
1369 if (r < 0)
1370 return r;
1371 }
1372 }
1373
1374 return sd_bus_message_close_container(reply);
1375 }
1376
1377 static int bus_property_get_transaction_statistics(
1378 sd_bus *bus,
1379 const char *path,
1380 const char *interface,
1381 const char *property,
1382 sd_bus_message *reply,
1383 void *userdata,
1384 sd_bus_error *error) {
1385
1386 Manager *m = userdata;
1387
1388 assert(reply);
1389 assert(m);
1390
1391 return sd_bus_message_append(reply, "(tt)",
1392 (uint64_t) hashmap_size(m->dns_transactions),
1393 (uint64_t) m->n_transactions_total);
1394 }
1395
1396 static int bus_property_get_cache_statistics(
1397 sd_bus *bus,
1398 const char *path,
1399 const char *interface,
1400 const char *property,
1401 sd_bus_message *reply,
1402 void *userdata,
1403 sd_bus_error *error) {
1404
1405 uint64_t size = 0, hit = 0, miss = 0;
1406 Manager *m = userdata;
1407 DnsScope *s;
1408
1409 assert(reply);
1410 assert(m);
1411
1412 LIST_FOREACH(scopes, s, m->dns_scopes) {
1413 size += dns_cache_size(&s->cache);
1414 hit += s->cache.n_hit;
1415 miss += s->cache.n_miss;
1416 }
1417
1418 return sd_bus_message_append(reply, "(ttt)", size, hit, miss);
1419 }
1420
1421 static int bus_property_get_dnssec_statistics(
1422 sd_bus *bus,
1423 const char *path,
1424 const char *interface,
1425 const char *property,
1426 sd_bus_message *reply,
1427 void *userdata,
1428 sd_bus_error *error) {
1429
1430 Manager *m = userdata;
1431
1432 assert(reply);
1433 assert(m);
1434
1435 return sd_bus_message_append(reply, "(tttt)",
1436 (uint64_t) m->n_dnssec_verdict[DNSSEC_SECURE],
1437 (uint64_t) m->n_dnssec_verdict[DNSSEC_INSECURE],
1438 (uint64_t) m->n_dnssec_verdict[DNSSEC_BOGUS],
1439 (uint64_t) m->n_dnssec_verdict[DNSSEC_INDETERMINATE]);
1440 }
1441
1442 static int bus_property_get_ntas(
1443 sd_bus *bus,
1444 const char *path,
1445 const char *interface,
1446 const char *property,
1447 sd_bus_message *reply,
1448 void *userdata,
1449 sd_bus_error *error) {
1450
1451 Manager *m = userdata;
1452 const char *domain;
1453 Iterator i;
1454 int r;
1455
1456 assert(reply);
1457 assert(m);
1458
1459 r = sd_bus_message_open_container(reply, 'a', "s");
1460 if (r < 0)
1461 return r;
1462
1463 SET_FOREACH(domain, m->trust_anchor.negative_by_name, i) {
1464 r = sd_bus_message_append(reply, "s", domain);
1465 if (r < 0)
1466 return r;
1467 }
1468
1469 return sd_bus_message_close_container(reply);
1470 }
1471
1472 static BUS_DEFINE_PROPERTY_GET_ENUM(bus_property_get_dns_stub_listener_mode, dns_stub_listener_mode, DnsStubListenerMode);
1473 static BUS_DEFINE_PROPERTY_GET(bus_property_get_dnssec_supported, "b", Manager, manager_dnssec_supported);
1474 static BUS_DEFINE_PROPERTY_GET2(bus_property_get_dnssec_mode, "s", Manager, manager_get_dnssec_mode, dnssec_mode_to_string);
1475 static BUS_DEFINE_PROPERTY_GET2(bus_property_get_dns_over_tls_mode, "s", Manager, manager_get_dns_over_tls_mode, dns_over_tls_mode_to_string);
1476
1477 static int bus_method_reset_statistics(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1478 Manager *m = userdata;
1479 DnsScope *s;
1480
1481 assert(message);
1482 assert(m);
1483
1484 LIST_FOREACH(scopes, s, m->dns_scopes)
1485 s->cache.n_hit = s->cache.n_miss = 0;
1486
1487 m->n_transactions_total = 0;
1488 zero(m->n_dnssec_verdict);
1489
1490 return sd_bus_reply_method_return(message, NULL);
1491 }
1492
1493 static int get_any_link(Manager *m, int ifindex, Link **ret, sd_bus_error *error) {
1494 Link *l;
1495
1496 assert(m);
1497 assert(ret);
1498
1499 if (ifindex <= 0)
1500 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid interface index");
1501
1502 l = hashmap_get(m->links, INT_TO_PTR(ifindex));
1503 if (!l)
1504 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_LINK, "Link %i not known", ifindex);
1505
1506 *ret = l;
1507 return 0;
1508 }
1509
1510 static int call_link_method(Manager *m, sd_bus_message *message, sd_bus_message_handler_t handler, sd_bus_error *error) {
1511 int ifindex, r;
1512 Link *l;
1513
1514 assert(m);
1515 assert(message);
1516 assert(handler);
1517
1518 assert_cc(sizeof(int) == sizeof(int32_t));
1519 r = sd_bus_message_read(message, "i", &ifindex);
1520 if (r < 0)
1521 return r;
1522
1523 r = get_any_link(m, ifindex, &l, error);
1524 if (r < 0)
1525 return r;
1526
1527 return handler(message, l, error);
1528 }
1529
1530 static int bus_method_set_link_dns_servers(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1531 return call_link_method(userdata, message, bus_link_method_set_dns_servers, error);
1532 }
1533
1534 static int bus_method_set_link_domains(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1535 return call_link_method(userdata, message, bus_link_method_set_domains, error);
1536 }
1537
1538 static int bus_method_set_link_default_route(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1539 return call_link_method(userdata, message, bus_link_method_set_default_route, error);
1540 }
1541
1542 static int bus_method_set_link_llmnr(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1543 return call_link_method(userdata, message, bus_link_method_set_llmnr, error);
1544 }
1545
1546 static int bus_method_set_link_mdns(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1547 return call_link_method(userdata, message, bus_link_method_set_mdns, error);
1548 }
1549
1550 static int bus_method_set_link_dns_over_tls(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1551 return call_link_method(userdata, message, bus_link_method_set_dns_over_tls, error);
1552 }
1553
1554 static int bus_method_set_link_dnssec(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1555 return call_link_method(userdata, message, bus_link_method_set_dnssec, error);
1556 }
1557
1558 static int bus_method_set_link_dnssec_negative_trust_anchors(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1559 return call_link_method(userdata, message, bus_link_method_set_dnssec_negative_trust_anchors, error);
1560 }
1561
1562 static int bus_method_revert_link(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1563 return call_link_method(userdata, message, bus_link_method_revert, error);
1564 }
1565
1566 static int bus_method_get_link(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1567 _cleanup_free_ char *p = NULL;
1568 Manager *m = userdata;
1569 int r, ifindex;
1570 Link *l;
1571
1572 assert(message);
1573 assert(m);
1574
1575 assert_cc(sizeof(int) == sizeof(int32_t));
1576 r = sd_bus_message_read(message, "i", &ifindex);
1577 if (r < 0)
1578 return r;
1579
1580 r = get_any_link(m, ifindex, &l, error);
1581 if (r < 0)
1582 return r;
1583
1584 p = link_bus_path(l);
1585 if (!p)
1586 return -ENOMEM;
1587
1588 return sd_bus_reply_method_return(message, "o", p);
1589 }
1590
1591 static int bus_method_flush_caches(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1592 Manager *m = userdata;
1593
1594 assert(message);
1595 assert(m);
1596
1597 manager_flush_caches(m);
1598
1599 return sd_bus_reply_method_return(message, NULL);
1600 }
1601
1602 static int bus_method_reset_server_features(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1603 Manager *m = userdata;
1604
1605 assert(message);
1606 assert(m);
1607
1608 manager_reset_server_features(m);
1609
1610 return sd_bus_reply_method_return(message, NULL);
1611 }
1612
1613 static int on_bus_track(sd_bus_track *t, void *userdata) {
1614 DnssdService *s = userdata;
1615
1616 assert(t);
1617 assert(s);
1618
1619 log_debug("Client of active request vanished, destroying DNS-SD service.");
1620 dnssd_service_free(s);
1621
1622 return 0;
1623 }
1624
1625 static int bus_method_register_service(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1626 _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
1627 _cleanup_(dnssd_service_freep) DnssdService *service = NULL;
1628 _cleanup_(sd_bus_track_unrefp) sd_bus_track *bus_track = NULL;
1629 _cleanup_free_ char *path = NULL;
1630 _cleanup_free_ char *instance_name = NULL;
1631 Manager *m = userdata;
1632 DnssdService *s = NULL;
1633 const char *name;
1634 const char *name_template;
1635 const char *type;
1636 uid_t euid;
1637 int r;
1638
1639 assert(message);
1640 assert(m);
1641
1642 if (m->mdns_support != RESOLVE_SUPPORT_YES)
1643 return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Support for MulticastDNS is disabled");
1644
1645 service = new0(DnssdService, 1);
1646 if (!service)
1647 return log_oom();
1648
1649 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID, &creds);
1650 if (r < 0)
1651 return r;
1652
1653 r = sd_bus_creds_get_euid(creds, &euid);
1654 if (r < 0)
1655 return r;
1656 service->originator = euid;
1657
1658 r = sd_bus_message_read(message, "sssqqq", &name, &name_template, &type,
1659 &service->port, &service->priority,
1660 &service->weight);
1661 if (r < 0)
1662 return r;
1663
1664 s = hashmap_get(m->dnssd_services, name);
1665 if (s)
1666 return sd_bus_error_setf(error, BUS_ERROR_DNSSD_SERVICE_EXISTS, "DNS-SD service '%s' exists already", name);
1667
1668 if (!dnssd_srv_type_is_valid(type))
1669 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "DNS-SD service type '%s' is invalid", type);
1670
1671 service->name = strdup(name);
1672 if (!service->name)
1673 return log_oom();
1674
1675 service->name_template = strdup(name_template);
1676 if (!service->name_template)
1677 return log_oom();
1678
1679 service->type = strdup(type);
1680 if (!service->type)
1681 return log_oom();
1682
1683 r = dnssd_render_instance_name(service, &instance_name);
1684 if (r < 0)
1685 return r;
1686
1687 r = sd_bus_message_enter_container(message, SD_BUS_TYPE_ARRAY, "a{say}");
1688 if (r < 0)
1689 return r;
1690
1691 while ((r = sd_bus_message_enter_container(message, SD_BUS_TYPE_ARRAY, "{say}")) > 0) {
1692 _cleanup_(dnssd_txtdata_freep) DnssdTxtData *txt_data = NULL;
1693 DnsTxtItem *last = NULL;
1694
1695 txt_data = new0(DnssdTxtData, 1);
1696 if (!txt_data)
1697 return log_oom();
1698
1699 while ((r = sd_bus_message_enter_container(message, SD_BUS_TYPE_DICT_ENTRY, "say")) > 0) {
1700 const char *key;
1701 const void *value;
1702 size_t size;
1703 DnsTxtItem *i;
1704
1705 r = sd_bus_message_read(message, "s", &key);
1706 if (r < 0)
1707 return r;
1708
1709 if (isempty(key))
1710 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Keys in DNS-SD TXT RRs can't be empty");
1711
1712 if (!ascii_is_valid(key))
1713 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "TXT key '%s' contains non-ASCII symbols", key);
1714
1715 r = sd_bus_message_read_array(message, 'y', &value, &size);
1716 if (r < 0)
1717 return r;
1718
1719 r = dnssd_txt_item_new_from_data(key, value, size, &i);
1720 if (r < 0)
1721 return r;
1722
1723 LIST_INSERT_AFTER(items, txt_data->txt, last, i);
1724 last = i;
1725
1726 r = sd_bus_message_exit_container(message);
1727 if (r < 0)
1728 return r;
1729
1730 }
1731 if (r < 0)
1732 return r;
1733
1734 r = sd_bus_message_exit_container(message);
1735 if (r < 0)
1736 return r;
1737
1738 if (txt_data->txt) {
1739 LIST_PREPEND(items, service->txt_data_items, txt_data);
1740 txt_data = NULL;
1741 }
1742 }
1743 if (r < 0)
1744 return r;
1745
1746 r = sd_bus_message_exit_container(message);
1747 if (r < 0)
1748 return r;
1749
1750 if (!service->txt_data_items) {
1751 _cleanup_(dnssd_txtdata_freep) DnssdTxtData *txt_data = NULL;
1752
1753 txt_data = new0(DnssdTxtData, 1);
1754 if (!txt_data)
1755 return log_oom();
1756
1757 r = dns_txt_item_new_empty(&txt_data->txt);
1758 if (r < 0)
1759 return r;
1760
1761 LIST_PREPEND(items, service->txt_data_items, txt_data);
1762 txt_data = NULL;
1763 }
1764
1765 r = sd_bus_path_encode("/org/freedesktop/resolve1/dnssd", service->name, &path);
1766 if (r < 0)
1767 return r;
1768
1769 r = bus_verify_polkit_async(message, CAP_SYS_ADMIN,
1770 "org.freedesktop.resolve1.register-service",
1771 NULL, false, UID_INVALID,
1772 &m->polkit_registry, error);
1773 if (r < 0)
1774 return r;
1775 if (r == 0)
1776 return 1; /* Polkit will call us back */
1777
1778 r = hashmap_ensure_allocated(&m->dnssd_services, &string_hash_ops);
1779 if (r < 0)
1780 return r;
1781
1782 r = hashmap_put(m->dnssd_services, service->name, service);
1783 if (r < 0)
1784 return r;
1785
1786 r = sd_bus_track_new(sd_bus_message_get_bus(message), &bus_track, on_bus_track, service);
1787 if (r < 0)
1788 return r;
1789
1790 r = sd_bus_track_add_sender(bus_track, message);
1791 if (r < 0)
1792 return r;
1793
1794 service->manager = m;
1795
1796 service = NULL;
1797
1798 manager_refresh_rrs(m);
1799
1800 return sd_bus_reply_method_return(message, "o", path);
1801 }
1802
1803 static int call_dnssd_method(Manager *m, sd_bus_message *message, sd_bus_message_handler_t handler, sd_bus_error *error) {
1804 _cleanup_free_ char *name = NULL;
1805 DnssdService *s = NULL;
1806 const char *path;
1807 int r;
1808
1809 assert(m);
1810 assert(message);
1811 assert(handler);
1812
1813 r = sd_bus_message_read(message, "o", &path);
1814 if (r < 0)
1815 return r;
1816
1817 r = sd_bus_path_decode(path, "/org/freedesktop/resolve1/dnssd", &name);
1818 if (r == 0)
1819 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_DNSSD_SERVICE, "DNS-SD service with object path '%s' does not exist", path);
1820 if (r < 0)
1821 return r;
1822
1823 s = hashmap_get(m->dnssd_services, name);
1824 if (!s)
1825 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_DNSSD_SERVICE, "DNS-SD service '%s' not known", name);
1826
1827 return handler(message, s, error);
1828 }
1829
1830 static int bus_method_unregister_service(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1831 Manager *m = userdata;
1832
1833 assert(message);
1834 assert(m);
1835
1836 return call_dnssd_method(m, message, bus_dnssd_method_unregister, error);
1837 }
1838
1839 static int property_get_log_level(
1840 sd_bus *bus,
1841 const char *path,
1842 const char *interface,
1843 const char *property,
1844 sd_bus_message *reply,
1845 void *userdata,
1846 sd_bus_error *error) {
1847
1848 _cleanup_free_ char *t = NULL;
1849 int r;
1850
1851 assert(bus);
1852 assert(reply);
1853
1854 r = log_level_to_string_alloc(log_get_max_level(), &t);
1855 if (r < 0)
1856 return r;
1857
1858 return sd_bus_message_append(reply, "s", t);
1859 }
1860
1861 static int property_set_log_level(
1862 sd_bus *bus,
1863 const char *path,
1864 const char *interface,
1865 const char *property,
1866 sd_bus_message *value,
1867 void *userdata,
1868 sd_bus_error *error) {
1869
1870 const char *t;
1871 int r;
1872
1873 assert(bus);
1874 assert(value);
1875
1876 r = sd_bus_message_read(value, "s", &t);
1877 if (r < 0)
1878 return r;
1879
1880 r = log_level_from_string(t);
1881 if (r < 0)
1882 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid log level '%s'", t);
1883
1884 log_info("Setting log level to %s.", t);
1885 log_set_max_level(r);
1886
1887 return 0;
1888 }
1889
1890 static const sd_bus_vtable resolve_vtable[] = {
1891 SD_BUS_VTABLE_START(0),
1892 SD_BUS_PROPERTY("LLMNRHostname", "s", NULL, offsetof(Manager, llmnr_hostname), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
1893 SD_BUS_PROPERTY("LLMNR", "s", bus_property_get_resolve_support, offsetof(Manager, llmnr_support), 0),
1894 SD_BUS_PROPERTY("MulticastDNS", "s", bus_property_get_resolve_support, offsetof(Manager, mdns_support), 0),
1895 SD_BUS_PROPERTY("DNSOverTLS", "s", bus_property_get_dns_over_tls_mode, 0, 0),
1896 SD_BUS_PROPERTY("DNS", "a(iiay)", bus_property_get_dns_servers, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
1897 SD_BUS_PROPERTY("FallbackDNS", "a(iiay)", bus_property_get_fallback_dns_servers, offsetof(Manager, fallback_dns_servers), SD_BUS_VTABLE_PROPERTY_CONST),
1898 SD_BUS_PROPERTY("CurrentDNSServer", "(iiay)", bus_property_get_current_dns_server, offsetof(Manager, current_dns_server), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
1899 SD_BUS_PROPERTY("Domains", "a(isb)", bus_property_get_domains, 0, 0),
1900 SD_BUS_PROPERTY("TransactionStatistics", "(tt)", bus_property_get_transaction_statistics, 0, 0),
1901 SD_BUS_PROPERTY("CacheStatistics", "(ttt)", bus_property_get_cache_statistics, 0, 0),
1902 SD_BUS_PROPERTY("DNSSEC", "s", bus_property_get_dnssec_mode, 0, 0),
1903 SD_BUS_PROPERTY("DNSSECStatistics", "(tttt)", bus_property_get_dnssec_statistics, 0, 0),
1904 SD_BUS_PROPERTY("DNSSECSupported", "b", bus_property_get_dnssec_supported, 0, 0),
1905 SD_BUS_PROPERTY("DNSSECNegativeTrustAnchors", "as", bus_property_get_ntas, 0, 0),
1906 SD_BUS_PROPERTY("DNSStubListener", "s", bus_property_get_dns_stub_listener_mode, offsetof(Manager, dns_stub_listener_mode), 0),
1907
1908 SD_BUS_WRITABLE_PROPERTY("LogLevel", "s", property_get_log_level, property_set_log_level, 0, 0),
1909
1910 SD_BUS_METHOD_WITH_NAMES("ResolveHostname",
1911 "isit",
1912 SD_BUS_PARAM(ifindex)
1913 SD_BUS_PARAM(name)
1914 SD_BUS_PARAM(family)
1915 SD_BUS_PARAM(flags),
1916 "a(iiay)st",
1917 SD_BUS_PARAM(addresses)
1918 SD_BUS_PARAM(canonical)
1919 SD_BUS_PARAM(flags),
1920 bus_method_resolve_hostname,
1921 SD_BUS_VTABLE_UNPRIVILEGED),
1922 SD_BUS_METHOD_WITH_NAMES("ResolveAddress",
1923 "iiayt",
1924 SD_BUS_PARAM(ifindex)
1925 SD_BUS_PARAM(family)
1926 SD_BUS_PARAM(address)
1927 SD_BUS_PARAM(flags),
1928 "a(is)t",
1929 SD_BUS_PARAM(names)
1930 SD_BUS_PARAM(flags),
1931 bus_method_resolve_address,
1932 SD_BUS_VTABLE_UNPRIVILEGED),
1933 SD_BUS_METHOD_WITH_NAMES("ResolveRecord",
1934 "isqqt",
1935 SD_BUS_PARAM(ifindex)
1936 SD_BUS_PARAM(name)
1937 SD_BUS_PARAM(class)
1938 SD_BUS_PARAM(type)
1939 SD_BUS_PARAM(flags),
1940 "a(iqqay)t",
1941 SD_BUS_PARAM(records)
1942 SD_BUS_PARAM(flags),
1943 bus_method_resolve_record,
1944 SD_BUS_VTABLE_UNPRIVILEGED),
1945 SD_BUS_METHOD_WITH_NAMES("ResolveService",
1946 "isssit",
1947 SD_BUS_PARAM(ifindex)
1948 SD_BUS_PARAM(name)
1949 SD_BUS_PARAM(type)
1950 SD_BUS_PARAM(domain)
1951 SD_BUS_PARAM(family)
1952 SD_BUS_PARAM(flags),
1953 "a(qqqsa(iiay)s)aayssst",
1954 SD_BUS_PARAM(srv_data)
1955 SD_BUS_PARAM(txt_data)
1956 SD_BUS_PARAM(canonical_name)
1957 SD_BUS_PARAM(canonical_type)
1958 SD_BUS_PARAM(canonical_domain)
1959 SD_BUS_PARAM(flags),
1960 bus_method_resolve_service,
1961 SD_BUS_VTABLE_UNPRIVILEGED),
1962 SD_BUS_METHOD_WITH_NAMES("GetLink",
1963 "i",
1964 SD_BUS_PARAM(ifindex),
1965 "o",
1966 SD_BUS_PARAM(path),
1967 bus_method_get_link,
1968 SD_BUS_VTABLE_UNPRIVILEGED),
1969 SD_BUS_METHOD_WITH_NAMES("SetLinkDNS",
1970 "ia(iay)",
1971 SD_BUS_PARAM(ifindex)
1972 SD_BUS_PARAM(addresses),
1973 NULL,,
1974 bus_method_set_link_dns_servers,
1975 SD_BUS_VTABLE_UNPRIVILEGED),
1976 SD_BUS_METHOD_WITH_NAMES("SetLinkDomains",
1977 "ia(sb)",
1978 SD_BUS_PARAM(ifindex)
1979 SD_BUS_PARAM(domains),
1980 NULL,,
1981 bus_method_set_link_domains,
1982 SD_BUS_VTABLE_UNPRIVILEGED),
1983 SD_BUS_METHOD_WITH_NAMES("SetLinkDefaultRoute",
1984 "ib",
1985 SD_BUS_PARAM(ifindex)
1986 SD_BUS_PARAM(enable),
1987 NULL,,
1988 bus_method_set_link_default_route,
1989 SD_BUS_VTABLE_UNPRIVILEGED),
1990 SD_BUS_METHOD_WITH_NAMES("SetLinkLLMNR",
1991 "is",
1992 SD_BUS_PARAM(ifindex)
1993 SD_BUS_PARAM(mode),
1994 NULL,,
1995 bus_method_set_link_llmnr,
1996 SD_BUS_VTABLE_UNPRIVILEGED),
1997 SD_BUS_METHOD_WITH_NAMES("SetLinkMulticastDNS",
1998 "is",
1999 SD_BUS_PARAM(ifindex)
2000 SD_BUS_PARAM(mode),
2001 NULL,,
2002 bus_method_set_link_mdns,
2003 SD_BUS_VTABLE_UNPRIVILEGED),
2004 SD_BUS_METHOD_WITH_NAMES("SetLinkDNSOverTLS",
2005 "is",
2006 SD_BUS_PARAM(ifindex)
2007 SD_BUS_PARAM(mode),
2008 NULL,,
2009 bus_method_set_link_dns_over_tls,
2010 SD_BUS_VTABLE_UNPRIVILEGED),
2011 SD_BUS_METHOD_WITH_NAMES("SetLinkDNSSEC",
2012 "is",
2013 SD_BUS_PARAM(ifindex)
2014 SD_BUS_PARAM(mode),
2015 NULL,,
2016 bus_method_set_link_dnssec,
2017 SD_BUS_VTABLE_UNPRIVILEGED),
2018 SD_BUS_METHOD_WITH_NAMES("SetLinkDNSSECNegativeTrustAnchors",
2019 "ias",
2020 SD_BUS_PARAM(ifindex)
2021 SD_BUS_PARAM(names),
2022 NULL,,
2023 bus_method_set_link_dnssec_negative_trust_anchors,
2024 SD_BUS_VTABLE_UNPRIVILEGED),
2025 SD_BUS_METHOD_WITH_NAMES("RevertLink",
2026 "i",
2027 SD_BUS_PARAM(ifindex),
2028 NULL,,
2029 bus_method_revert_link,
2030 SD_BUS_VTABLE_UNPRIVILEGED),
2031 SD_BUS_METHOD_WITH_NAMES("RegisterService",
2032 "sssqqqaa{say}",
2033 SD_BUS_PARAM(name)
2034 SD_BUS_PARAM(name_template)
2035 SD_BUS_PARAM(type)
2036 SD_BUS_PARAM(service_port)
2037 SD_BUS_PARAM(service_priority)
2038 SD_BUS_PARAM(serwise_weight)
2039 SD_BUS_PARAM(txt_datas),
2040 "o",
2041 SD_BUS_PARAM(service_path),
2042 bus_method_register_service,
2043 SD_BUS_VTABLE_UNPRIVILEGED),
2044 SD_BUS_METHOD_WITH_NAMES("UnregisterService",
2045 "o",
2046 SD_BUS_PARAM(service_path),
2047 NULL,,
2048 bus_method_unregister_service,
2049 SD_BUS_VTABLE_UNPRIVILEGED),
2050
2051 SD_BUS_METHOD("ResetStatistics",
2052 NULL,
2053 NULL,
2054 bus_method_reset_statistics,
2055 SD_BUS_VTABLE_UNPRIVILEGED),
2056 SD_BUS_METHOD("FlushCaches",
2057 NULL,
2058 NULL,
2059 bus_method_flush_caches,
2060 SD_BUS_VTABLE_UNPRIVILEGED),
2061 SD_BUS_METHOD("ResetServerFeatures",
2062 NULL,
2063 NULL,
2064 bus_method_reset_server_features,
2065 SD_BUS_VTABLE_UNPRIVILEGED),
2066
2067 SD_BUS_VTABLE_END,
2068 };
2069
2070 static int match_prepare_for_sleep(sd_bus_message *message, void *userdata, sd_bus_error *ret_error) {
2071 Manager *m = userdata;
2072 int b, r;
2073
2074 assert(message);
2075 assert(m);
2076
2077 r = sd_bus_message_read(message, "b", &b);
2078 if (r < 0) {
2079 log_debug_errno(r, "Failed to parse PrepareForSleep signal: %m");
2080 return 0;
2081 }
2082
2083 if (b)
2084 return 0;
2085
2086 log_debug("Coming back from suspend, verifying all RRs...");
2087
2088 manager_verify_all(m);
2089 return 0;
2090 }
2091
2092 int manager_connect_bus(Manager *m) {
2093 int r;
2094
2095 assert(m);
2096
2097 if (m->bus)
2098 return 0;
2099
2100 r = bus_open_system_watch_bind_with_description(&m->bus, "bus-api-resolve");
2101 if (r < 0)
2102 return log_error_errno(r, "Failed to connect to system bus: %m");
2103
2104 r = sd_bus_add_object_vtable(m->bus, NULL, "/org/freedesktop/resolve1", "org.freedesktop.resolve1.Manager", resolve_vtable, m);
2105 if (r < 0)
2106 return log_error_errno(r, "Failed to register object: %m");
2107
2108 r = sd_bus_add_fallback_vtable(m->bus, NULL, "/org/freedesktop/resolve1/link", "org.freedesktop.resolve1.Link", link_vtable, link_object_find, m);
2109 if (r < 0)
2110 return log_error_errno(r, "Failed to register link objects: %m");
2111
2112 r = sd_bus_add_node_enumerator(m->bus, NULL, "/org/freedesktop/resolve1/link", link_node_enumerator, m);
2113 if (r < 0)
2114 return log_error_errno(r, "Failed to register link enumerator: %m");
2115
2116 r = sd_bus_add_fallback_vtable(m->bus, NULL, "/org/freedesktop/resolve1/dnssd", "org.freedesktop.resolve1.DnssdService", dnssd_vtable, dnssd_object_find, m);
2117 if (r < 0)
2118 return log_error_errno(r, "Failed to register dnssd objects: %m");
2119
2120 r = sd_bus_add_node_enumerator(m->bus, NULL, "/org/freedesktop/resolve1/dnssd", dnssd_node_enumerator, m);
2121 if (r < 0)
2122 return log_error_errno(r, "Failed to register dnssd enumerator: %m");
2123
2124 r = sd_bus_request_name_async(m->bus, NULL, "org.freedesktop.resolve1", 0, NULL, NULL);
2125 if (r < 0)
2126 return log_error_errno(r, "Failed to request name: %m");
2127
2128 r = sd_bus_attach_event(m->bus, m->event, 0);
2129 if (r < 0)
2130 return log_error_errno(r, "Failed to attach bus to event loop: %m");
2131
2132 r = sd_bus_match_signal_async(
2133 m->bus,
2134 NULL,
2135 "org.freedesktop.login1",
2136 "/org/freedesktop/login1",
2137 "org.freedesktop.login1.Manager",
2138 "PrepareForSleep",
2139 match_prepare_for_sleep,
2140 NULL,
2141 m);
2142 if (r < 0)
2143 log_warning_errno(r, "Failed to request match for PrepareForSleep, ignoring: %m");
2144
2145 return 0;
2146 }
2147
2148 int _manager_send_changed(Manager *manager, const char *property, ...) {
2149 assert(manager);
2150
2151 char **l = strv_from_stdarg_alloca(property);
2152
2153 int r = sd_bus_emit_properties_changed_strv(
2154 manager->bus,
2155 "/org/freedesktop/resolve1",
2156 "org.freedesktop.resolve1.Manager",
2157 l);
2158 if (r < 0)
2159 log_notice_errno(r, "Failed to emit notification about changed property %s: %m", property);
2160 return r;
2161 }