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