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