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