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