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