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