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