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