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