]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/resolve/resolved-bus.c
resolved: set a description on all our event sources
[thirdparty/systemd.git] / src / resolve / resolved-bus.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4 This file is part of systemd.
5
6 Copyright 2014 Lennart Poettering
7
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
12
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22 #include "alloc-util.h"
23 #include "bus-common-errors.h"
24 #include "bus-util.h"
25 #include "dns-domain.h"
26 #include "resolved-bus.h"
27 #include "resolved-def.h"
28
29 static int reply_query_state(DnsQuery *q) {
30 _cleanup_free_ char *ip = NULL;
31 const char *name;
32 int r;
33
34 if (q->request_address_valid) {
35 r = in_addr_to_string(q->request_family, &q->request_address, &ip);
36 if (r < 0)
37 return r;
38
39 name = ip;
40 } else
41 name = dns_question_first_name(q->question);
42
43 switch (q->state) {
44
45 case DNS_TRANSACTION_NO_SERVERS:
46 return sd_bus_reply_method_errorf(q->request, BUS_ERROR_NO_NAME_SERVERS, "No appropriate name servers or networks for name found");
47
48 case DNS_TRANSACTION_TIMEOUT:
49 return sd_bus_reply_method_errorf(q->request, SD_BUS_ERROR_TIMEOUT, "Query timed out");
50
51 case DNS_TRANSACTION_ATTEMPTS_MAX_REACHED:
52 return sd_bus_reply_method_errorf(q->request, SD_BUS_ERROR_TIMEOUT, "All attempts to contact name servers or networks failed");
53
54 case DNS_TRANSACTION_INVALID_REPLY:
55 return sd_bus_reply_method_errorf(q->request, BUS_ERROR_INVALID_REPLY, "Received invalid reply");
56
57 case DNS_TRANSACTION_RESOURCES:
58 return sd_bus_reply_method_errorf(q->request, BUS_ERROR_NO_RESOURCES, "Not enough resources");
59
60 case DNS_TRANSACTION_CONNECTION_FAILURE:
61 return sd_bus_reply_method_errorf(q->request, BUS_ERROR_CONNECTION_FAILURE, "DNS server connection failure");
62
63 case DNS_TRANSACTION_ABORTED:
64 return sd_bus_reply_method_errorf(q->request, BUS_ERROR_ABORTED, "Query aborted");
65
66 case DNS_TRANSACTION_DNSSEC_FAILED:
67 return sd_bus_reply_method_errorf(q->request, BUS_ERROR_DNSSEC_FAILED, "DNSSEC validation failed: %s",
68 dnssec_result_to_string(q->answer_dnssec_result));
69
70 case DNS_TRANSACTION_NO_TRUST_ANCHOR:
71 return sd_bus_reply_method_errorf(q->request, BUS_ERROR_NO_TRUST_ANCHOR, "No suitable trust anchor known");
72
73 case DNS_TRANSACTION_RCODE_FAILURE: {
74 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
75
76 if (q->answer_rcode == DNS_RCODE_NXDOMAIN)
77 sd_bus_error_setf(&error, _BUS_ERROR_DNS "NXDOMAIN", "'%s' not found", name);
78 else {
79 const char *rc, *n;
80 char p[3]; /* the rcode is 4 bits long */
81
82 rc = dns_rcode_to_string(q->answer_rcode);
83 if (!rc) {
84 sprintf(p, "%i", q->answer_rcode);
85 rc = p;
86 }
87
88 n = strjoina(_BUS_ERROR_DNS, rc);
89 sd_bus_error_setf(&error, n, "Could not resolve '%s', server or network returned error %s", name, rc);
90 }
91
92 return sd_bus_reply_method_error(q->request, &error);
93 }
94
95 case DNS_TRANSACTION_NULL:
96 case DNS_TRANSACTION_PENDING:
97 case DNS_TRANSACTION_SUCCESS:
98 default:
99 assert_not_reached("Impossible state");
100 }
101 }
102
103 static int append_address(sd_bus_message *reply, DnsResourceRecord *rr, int ifindex) {
104 int r;
105
106 assert(reply);
107 assert(rr);
108
109 r = sd_bus_message_open_container(reply, 'r', "iiay");
110 if (r < 0)
111 return r;
112
113 r = sd_bus_message_append(reply, "i", ifindex);
114 if (r < 0)
115 return r;
116
117 if (rr->key->type == DNS_TYPE_A) {
118 r = sd_bus_message_append(reply, "i", AF_INET);
119 if (r < 0)
120 return r;
121
122 r = sd_bus_message_append_array(reply, 'y', &rr->a.in_addr, sizeof(struct in_addr));
123
124 } else if (rr->key->type == DNS_TYPE_AAAA) {
125 r = sd_bus_message_append(reply, "i", AF_INET6);
126 if (r < 0)
127 return r;
128
129 r = sd_bus_message_append_array(reply, 'y', &rr->aaaa.in6_addr, sizeof(struct in6_addr));
130 } else
131 return -EAFNOSUPPORT;
132
133 if (r < 0)
134 return r;
135
136 r = sd_bus_message_close_container(reply);
137 if (r < 0)
138 return r;
139
140 return 0;
141 }
142
143 static void bus_method_resolve_hostname_complete(DnsQuery *q) {
144 _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *canonical = NULL;
145 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
146 unsigned added = 0;
147 int 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_question_first_name(q->question));
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 if (q->answer) {
175 DnsResourceRecord *rr;
176 int ifindex;
177
178 DNS_ANSWER_FOREACH_IFINDEX(rr, ifindex, q->answer) {
179 r = dns_question_matches_rr(q->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
196 if (added <= 0) {
197 r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_NO_SUCH_RR, "'%s' does not have any RR of the requested type", dns_question_first_name(q->question));
198 goto finish;
199 }
200
201 r = sd_bus_message_close_container(reply);
202 if (r < 0)
203 goto finish;
204
205 /* Return the precise spelling and uppercasing and CNAME target reported by the server */
206 assert(canonical);
207 r = sd_bus_message_append(
208 reply, "st",
209 DNS_RESOURCE_KEY_NAME(canonical->key),
210 SD_RESOLVED_FLAGS_MAKE(q->answer_protocol, q->answer_family, q->answer_authenticated));
211 if (r < 0)
212 goto finish;
213
214 r = sd_bus_send(q->manager->bus, reply, NULL);
215
216 finish:
217 if (r < 0) {
218 log_error_errno(r, "Failed to send hostname reply: %m");
219 sd_bus_reply_method_errno(q->request, r, NULL);
220 }
221
222 dns_query_free(q);
223 }
224
225 static int check_ifindex_flags(int ifindex, uint64_t *flags, uint64_t ok, sd_bus_error *error) {
226 assert(flags);
227
228 if (ifindex < 0)
229 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid interface index");
230
231 if (*flags & ~(SD_RESOLVED_PROTOCOLS_ALL|SD_RESOLVED_NO_CNAME|ok))
232 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid flags parameter");
233
234 if ((*flags & SD_RESOLVED_PROTOCOLS_ALL) == 0) /* If no protocol is enabled, enable all */
235 *flags |= SD_RESOLVED_PROTOCOLS_ALL;
236
237 return 0;
238 }
239
240 static int bus_method_resolve_hostname(sd_bus_message *message, void *userdata, sd_bus_error *error) {
241 _cleanup_(dns_question_unrefp) DnsQuestion *question = NULL;
242 Manager *m = userdata;
243 const char *hostname;
244 int family, ifindex;
245 uint64_t flags;
246 DnsQuery *q;
247 int r;
248
249 assert(message);
250 assert(m);
251
252 assert_cc(sizeof(int) == sizeof(int32_t));
253
254 r = sd_bus_message_read(message, "isit", &ifindex, &hostname, &family, &flags);
255 if (r < 0)
256 return r;
257
258 if (!IN_SET(family, AF_INET, AF_INET6, AF_UNSPEC))
259 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown address family %i", family);
260
261 r = dns_name_is_valid(hostname);
262 if (r < 0)
263 return r;
264 if (r == 0)
265 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid hostname '%s'", hostname);
266
267 r = check_ifindex_flags(ifindex, &flags, SD_RESOLVED_NO_SEARCH, error);
268 if (r < 0)
269 return r;
270
271 r = dns_question_new_address(&question, family, hostname);
272 if (r < 0)
273 return r;
274
275 r = dns_query_new(m, &q, question, ifindex, flags);
276 if (r < 0)
277 return r;
278
279 q->request = sd_bus_message_ref(message);
280 q->request_family = family;
281 q->complete = bus_method_resolve_hostname_complete;
282
283 r = dns_query_bus_track(q, message);
284 if (r < 0)
285 goto fail;
286
287 r = dns_query_go(q);
288 if (r < 0)
289 goto fail;
290
291 return 1;
292
293 fail:
294 dns_query_free(q);
295 return r;
296 }
297
298 static void bus_method_resolve_address_complete(DnsQuery *q) {
299 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
300 DnsResourceRecord *rr;
301 unsigned added = 0;
302 int ifindex, r;
303
304 assert(q);
305
306 if (q->state != DNS_TRANSACTION_SUCCESS) {
307 r = reply_query_state(q);
308 goto finish;
309 }
310
311 r = dns_query_process_cname(q);
312 if (r == -ELOOP) {
313 r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_CNAME_LOOP, "CNAME loop detected, or CNAME resolving disabled on '%s'", dns_question_first_name(q->question));
314 goto finish;
315 }
316 if (r < 0)
317 goto finish;
318 if (r == DNS_QUERY_RESTARTED) /* This was a cname, and the query was restarted. */
319 return;
320
321 r = sd_bus_message_new_method_return(q->request, &reply);
322 if (r < 0)
323 goto finish;
324
325 r = sd_bus_message_open_container(reply, 'a', "(is)");
326 if (r < 0)
327 goto finish;
328
329 if (q->answer) {
330 DNS_ANSWER_FOREACH_IFINDEX(rr, ifindex, q->answer) {
331 r = dns_question_matches_rr(q->question, rr, NULL);
332 if (r < 0)
333 goto finish;
334 if (r == 0)
335 continue;
336
337 r = sd_bus_message_append(reply, "(is)", ifindex, rr->ptr.name);
338 if (r < 0)
339 goto finish;
340
341 added ++;
342 }
343 }
344
345 if (added <= 0) {
346 _cleanup_free_ char *ip = NULL;
347
348 in_addr_to_string(q->request_family, &q->request_address, &ip);
349 r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_NO_SUCH_RR, "Address '%s' does not have any RR of requested type", strna(ip));
350 goto finish;
351 }
352
353 r = sd_bus_message_close_container(reply);
354 if (r < 0)
355 goto finish;
356
357 r = sd_bus_message_append(reply, "t", SD_RESOLVED_FLAGS_MAKE(q->answer_protocol, q->answer_family, q->answer_authenticated));
358 if (r < 0)
359 goto finish;
360
361 r = sd_bus_send(q->manager->bus, reply, NULL);
362
363 finish:
364 if (r < 0) {
365 log_error_errno(r, "Failed to send address reply: %m");
366 sd_bus_reply_method_errno(q->request, r, NULL);
367 }
368
369 dns_query_free(q);
370 }
371
372 static int bus_method_resolve_address(sd_bus_message *message, void *userdata, sd_bus_error *error) {
373 _cleanup_(dns_question_unrefp) DnsQuestion *question = NULL;
374 Manager *m = userdata;
375 int family, ifindex;
376 uint64_t flags;
377 const void *d;
378 DnsQuery *q;
379 size_t sz;
380 int r;
381
382 assert(message);
383 assert(m);
384
385 assert_cc(sizeof(int) == sizeof(int32_t));
386
387 r = sd_bus_message_read(message, "ii", &ifindex, &family);
388 if (r < 0)
389 return r;
390
391 if (!IN_SET(family, AF_INET, AF_INET6))
392 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown address family %i", family);
393
394 r = sd_bus_message_read_array(message, 'y', &d, &sz);
395 if (r < 0)
396 return r;
397
398 if (sz != FAMILY_ADDRESS_SIZE(family))
399 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid address size");
400
401 r = sd_bus_message_read(message, "t", &flags);
402 if (r < 0)
403 return r;
404
405 r = check_ifindex_flags(ifindex, &flags, 0, error);
406 if (r < 0)
407 return r;
408
409 r = dns_question_new_reverse(&question, family, d);
410 if (r < 0)
411 return r;
412
413 r = dns_query_new(m, &q, question, ifindex, flags|SD_RESOLVED_NO_SEARCH);
414 if (r < 0)
415 return r;
416
417 q->request = sd_bus_message_ref(message);
418 q->request_family = family;
419 memcpy(&q->request_address, d, sz);
420 q->complete = bus_method_resolve_address_complete;
421
422 r = dns_query_bus_track(q, message);
423 if (r < 0)
424 goto fail;
425
426 r = dns_query_go(q);
427 if (r < 0)
428 goto fail;
429
430 return 1;
431
432 fail:
433 dns_query_free(q);
434 return r;
435 }
436
437 static int bus_message_append_rr(sd_bus_message *m, DnsResourceRecord *rr, int ifindex) {
438 int r;
439
440 assert(m);
441 assert(rr);
442
443 r = sd_bus_message_open_container(m, 'r', "iqqay");
444 if (r < 0)
445 return r;
446
447 r = sd_bus_message_append(m, "iqq",
448 ifindex,
449 rr->key->class,
450 rr->key->type);
451 if (r < 0)
452 return r;
453
454 r = dns_resource_record_to_wire_format(rr, false);
455 if (r < 0)
456 return r;
457
458 r = sd_bus_message_append_array(m, 'y', rr->wire_format, rr->wire_format_size);
459 if (r < 0)
460 return r;
461
462 return sd_bus_message_close_container(m);
463 }
464
465 static void bus_method_resolve_record_complete(DnsQuery *q) {
466 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
467 unsigned added = 0;
468 int r;
469
470 assert(q);
471
472 if (q->state != DNS_TRANSACTION_SUCCESS) {
473 r = reply_query_state(q);
474 goto finish;
475 }
476
477 r = dns_query_process_cname(q);
478 if (r == -ELOOP) {
479 r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_CNAME_LOOP, "CNAME loop detected, or CNAME resolving disabled on '%s'", dns_question_first_name(q->question));
480 goto finish;
481 }
482 if (r < 0)
483 goto finish;
484 if (r == DNS_QUERY_RESTARTED) /* This was a cname, and the query was restarted. */
485 return;
486
487 r = sd_bus_message_new_method_return(q->request, &reply);
488 if (r < 0)
489 goto finish;
490
491 r = sd_bus_message_open_container(reply, 'a', "(iqqay)");
492 if (r < 0)
493 goto finish;
494
495 if (q->answer) {
496 DnsResourceRecord *rr;
497 int ifindex;
498
499 DNS_ANSWER_FOREACH_IFINDEX(rr, ifindex, q->answer) {
500 r = dns_question_matches_rr(q->question, rr, NULL);
501 if (r < 0)
502 goto finish;
503 if (r == 0)
504 continue;
505
506 r = bus_message_append_rr(reply, rr, ifindex);
507 if (r < 0)
508 goto finish;
509
510 added ++;
511 }
512 }
513
514 if (added <= 0) {
515 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_question_first_name(q->question));
516 goto finish;
517 }
518
519 r = sd_bus_message_close_container(reply);
520 if (r < 0)
521 goto finish;
522
523 r = sd_bus_message_append(reply, "t", SD_RESOLVED_FLAGS_MAKE(q->answer_protocol, q->answer_family, q->answer_authenticated));
524 if (r < 0)
525 goto finish;
526
527 r = sd_bus_send(q->manager->bus, reply, NULL);
528
529 finish:
530 if (r < 0) {
531 log_error_errno(r, "Failed to send record reply: %m");
532 sd_bus_reply_method_errno(q->request, r, NULL);
533 }
534
535 dns_query_free(q);
536 }
537
538 static int bus_method_resolve_record(sd_bus_message *message, void *userdata, sd_bus_error *error) {
539 _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
540 _cleanup_(dns_question_unrefp) DnsQuestion *question = NULL;
541 Manager *m = userdata;
542 uint16_t class, type;
543 const char *name;
544 int r, ifindex;
545 uint64_t flags;
546 DnsQuery *q;
547
548 assert(message);
549 assert(m);
550
551 assert_cc(sizeof(int) == sizeof(int32_t));
552
553 r = sd_bus_message_read(message, "isqqt", &ifindex, &name, &class, &type, &flags);
554 if (r < 0)
555 return r;
556
557 r = dns_name_is_valid(name);
558 if (r < 0)
559 return r;
560 if (r == 0)
561 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid name '%s'", name);
562
563 if (!dns_type_is_valid_query(type))
564 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid RR type for query %" PRIu16, type);
565
566 r = check_ifindex_flags(ifindex, &flags, 0, error);
567 if (r < 0)
568 return r;
569
570 question = dns_question_new(1);
571 if (!question)
572 return -ENOMEM;
573
574 key = dns_resource_key_new(class, type, name);
575 if (!key)
576 return -ENOMEM;
577
578 r = dns_question_add(question, key);
579 if (r < 0)
580 return r;
581
582 r = dns_query_new(m, &q, question, ifindex, flags|SD_RESOLVED_NO_SEARCH);
583 if (r < 0)
584 return r;
585
586 q->request = sd_bus_message_ref(message);
587 q->complete = bus_method_resolve_record_complete;
588
589 r = dns_query_bus_track(q, message);
590 if (r < 0)
591 goto fail;
592
593 r = dns_query_go(q);
594 if (r < 0)
595 goto fail;
596
597 return 1;
598
599 fail:
600 dns_query_free(q);
601 return r;
602 }
603
604 static int append_srv(DnsQuery *q, sd_bus_message *reply, DnsResourceRecord *rr) {
605 _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *canonical = NULL;
606 DnsQuery *aux;
607 int r;
608
609 assert(q);
610 assert(reply);
611 assert(rr);
612 assert(rr->key);
613
614 if (rr->key->type != DNS_TYPE_SRV)
615 return 0;
616
617 if ((q->flags & SD_RESOLVED_NO_ADDRESS) == 0) {
618 /* First, let's see if we could find an appropriate A or AAAA
619 * record for the SRV record */
620 LIST_FOREACH(auxiliary_queries, aux, q->auxiliary_queries) {
621 DnsResourceRecord *zz;
622
623 if (aux->state != DNS_TRANSACTION_SUCCESS)
624 continue;
625 if (aux->auxiliary_result != 0)
626 continue;
627
628 r = dns_name_equal(dns_question_first_name(aux->question), rr->srv.name);
629 if (r < 0)
630 return r;
631 if (r == 0)
632 continue;
633
634 DNS_ANSWER_FOREACH(zz, aux->answer) {
635
636 r = dns_question_matches_rr(aux->question, zz, NULL);
637 if (r < 0)
638 return r;
639 if (r == 0)
640 continue;
641
642 canonical = dns_resource_record_ref(zz);
643 break;
644 }
645
646 if (canonical)
647 break;
648 }
649
650 /* Is there are successful A/AAAA lookup for this SRV RR? If not, don't add it */
651 if (!canonical)
652 return 0;
653 }
654
655 r = sd_bus_message_open_container(reply, 'r', "qqqsa(iiay)s");
656 if (r < 0)
657 return r;
658
659 r = sd_bus_message_append(
660 reply,
661 "qqqs",
662 rr->srv.priority, rr->srv.weight, rr->srv.port, rr->srv.name);
663 if (r < 0)
664 return r;
665
666 r = sd_bus_message_open_container(reply, 'a', "(iiay)");
667 if (r < 0)
668 return r;
669
670 if ((q->flags & SD_RESOLVED_NO_ADDRESS) == 0) {
671 LIST_FOREACH(auxiliary_queries, aux, q->auxiliary_queries) {
672 DnsResourceRecord *zz;
673 int ifindex;
674
675 if (aux->state != DNS_TRANSACTION_SUCCESS)
676 continue;
677 if (aux->auxiliary_result != 0)
678 continue;
679
680 r = dns_name_equal(dns_question_first_name(aux->question), rr->srv.name);
681 if (r < 0)
682 return r;
683 if (r == 0)
684 continue;
685
686 DNS_ANSWER_FOREACH_IFINDEX(zz, ifindex, aux->answer) {
687
688 r = dns_question_matches_rr(aux->question, zz, NULL);
689 if (r < 0)
690 return r;
691 if (r == 0)
692 continue;
693
694 r = append_address(reply, zz, ifindex);
695 if (r < 0)
696 return r;
697 }
698 }
699 }
700
701 r = sd_bus_message_close_container(reply);
702 if (r < 0)
703 return r;
704
705 /* Note that above we appended the hostname as encoded in the
706 * SRV, and here the canonical hostname this maps to. */
707 r = sd_bus_message_append(reply, "s", canonical ? DNS_RESOURCE_KEY_NAME(canonical->key) : rr->srv.name);
708 if (r < 0)
709 return r;
710
711 r = sd_bus_message_close_container(reply);
712 if (r < 0)
713 return r;
714
715 return 1;
716 }
717
718 static int append_txt(sd_bus_message *reply, DnsResourceRecord *rr) {
719 DnsTxtItem *i;
720 int r;
721
722 assert(reply);
723 assert(rr);
724 assert(rr->key);
725
726 if (rr->key->type != DNS_TYPE_TXT)
727 return 0;
728
729 LIST_FOREACH(items, i, rr->txt.items) {
730
731 if (i->length <= 0)
732 continue;
733
734 r = sd_bus_message_append_array(reply, 'y', i->data, i->length);
735 if (r < 0)
736 return r;
737 }
738
739 return 1;
740 }
741
742 static void resolve_service_all_complete(DnsQuery *q) {
743 _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *canonical = NULL;
744 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
745 _cleanup_free_ char *name = NULL, *type = NULL, *domain = NULL;
746 DnsQuery *aux;
747 unsigned added = false;
748 int r;
749
750 assert(q);
751
752 if (q->block_all_complete > 0)
753 return;
754
755 if ((q->flags & SD_RESOLVED_NO_ADDRESS) == 0) {
756 DnsQuery *bad = NULL;
757 bool have_success = false;
758
759 LIST_FOREACH(auxiliary_queries, aux, q->auxiliary_queries) {
760
761 switch (aux->state) {
762
763 case DNS_TRANSACTION_PENDING:
764 /* If an auxiliary query is still pending, let's wait */
765 return;
766
767 case DNS_TRANSACTION_SUCCESS:
768 if (aux->auxiliary_result == 0)
769 have_success = true;
770 else
771 bad = aux;
772 break;
773
774 default:
775 bad = aux;
776 break;
777 }
778 }
779
780 if (!have_success) {
781 /* We can only return one error, hence pick the last error we encountered */
782
783 assert(bad);
784
785 if (bad->state == DNS_TRANSACTION_SUCCESS) {
786 assert(bad->auxiliary_result != 0);
787
788 if (bad->auxiliary_result == -ELOOP) {
789 r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_CNAME_LOOP, "CNAME loop detected, or CNAME resolving disabled on '%s'", dns_question_first_name(bad->question));
790 goto finish;
791 }
792
793 r = bad->auxiliary_result;
794 goto finish;
795 }
796
797 r = reply_query_state(bad);
798 goto finish;
799 }
800 }
801
802 r = sd_bus_message_new_method_return(q->request, &reply);
803 if (r < 0)
804 goto finish;
805
806 r = sd_bus_message_open_container(reply, 'a', "(qqqsa(iiay)s)");
807 if (r < 0)
808 goto finish;
809
810 if (q->answer) {
811 DnsResourceRecord *rr;
812
813 DNS_ANSWER_FOREACH(rr, q->answer) {
814 r = dns_question_matches_rr(q->question, rr, NULL);
815 if (r < 0)
816 goto finish;
817 if (r == 0)
818 continue;
819
820 r = append_srv(q, reply, rr);
821 if (r < 0)
822 goto finish;
823 if (r == 0) /* not an SRV record */
824 continue;
825
826 if (!canonical)
827 canonical = dns_resource_record_ref(rr);
828
829 added++;
830 }
831 }
832
833 if (added <= 0) {
834 r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_NO_SUCH_RR, "'%s' does not have any RR of the requested type", dns_question_first_name(q->question));
835 goto finish;
836 }
837
838 r = sd_bus_message_close_container(reply);
839 if (r < 0)
840 goto finish;
841
842 r = sd_bus_message_open_container(reply, 'a', "ay");
843 if (r < 0)
844 goto finish;
845
846 if (q->answer) {
847 DnsResourceRecord *rr;
848
849 DNS_ANSWER_FOREACH(rr, q->answer) {
850 r = dns_question_matches_rr(q->question, rr, NULL);
851 if (r < 0)
852 goto finish;
853 if (r == 0)
854 continue;
855
856 r = append_txt(reply, rr);
857 if (r < 0)
858 goto finish;
859 }
860 }
861
862 r = sd_bus_message_close_container(reply);
863 if (r < 0)
864 goto finish;
865
866 assert(canonical);
867 r = dns_service_split(DNS_RESOURCE_KEY_NAME(canonical->key), &name, &type, &domain);
868 if (r < 0)
869 goto finish;
870
871 r = sd_bus_message_append(
872 reply,
873 "ssst",
874 name, type, domain,
875 SD_RESOLVED_FLAGS_MAKE(q->answer_protocol, q->answer_family, q->answer_authenticated));
876 if (r < 0)
877 goto finish;
878
879 r = sd_bus_send(q->manager->bus, reply, NULL);
880
881 finish:
882 if (r < 0) {
883 log_error_errno(r, "Failed to send service reply: %m");
884 sd_bus_reply_method_errno(q->request, r, NULL);
885 }
886
887 dns_query_free(q);
888 }
889
890 static void resolve_service_hostname_complete(DnsQuery *q) {
891 int r;
892
893 assert(q);
894 assert(q->auxiliary_for);
895
896 if (q->state != DNS_TRANSACTION_SUCCESS) {
897 resolve_service_all_complete(q->auxiliary_for);
898 return;
899 }
900
901 r = dns_query_process_cname(q);
902 if (r == DNS_QUERY_RESTARTED) /* This was a cname, and the query was restarted. */
903 return;
904
905 /* This auxiliary lookup is finished or failed, let's see if all are finished now. */
906 q->auxiliary_result = r;
907 resolve_service_all_complete(q->auxiliary_for);
908 }
909
910 static int resolve_service_hostname(DnsQuery *q, DnsResourceRecord *rr, int ifindex) {
911 _cleanup_(dns_question_unrefp) DnsQuestion *question = NULL;
912 DnsQuery *aux;
913 int r;
914
915 assert(q);
916 assert(rr);
917 assert(rr->key);
918 assert(rr->key->type == DNS_TYPE_SRV);
919
920 /* OK, we found an SRV record for the service. Let's resolve
921 * the hostname included in it */
922
923 r = dns_question_new_address(&question, q->request_family, rr->srv.name);
924 if (r < 0)
925 return r;
926
927 r = dns_query_new(q->manager, &aux, question, ifindex, q->flags|SD_RESOLVED_NO_SEARCH);
928 if (r < 0)
929 return r;
930
931 aux->request_family = q->request_family;
932 aux->complete = resolve_service_hostname_complete;
933
934 r = dns_query_make_auxiliary(aux, q);
935 if (r == -EAGAIN) {
936 /* Too many auxiliary lookups? If so, don't complain,
937 * let's just not add this one, we already have more
938 * than enough */
939
940 dns_query_free(aux);
941 return 0;
942 }
943 if (r < 0)
944 goto fail;
945
946 /* Note that auxiliary queries do not track the original bus
947 * client, only the primary request does that. */
948
949 r = dns_query_go(aux);
950 if (r < 0)
951 goto fail;
952
953 return 1;
954
955 fail:
956 dns_query_free(aux);
957 return r;
958 }
959
960 static void bus_method_resolve_service_complete(DnsQuery *q) {
961 unsigned found = 0;
962 int r;
963
964 assert(q);
965
966 if (q->state != DNS_TRANSACTION_SUCCESS) {
967 r = reply_query_state(q);
968 goto finish;
969 }
970
971 r = dns_query_process_cname(q);
972 if (r == -ELOOP) {
973 r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_CNAME_LOOP, "CNAME loop detected, or CNAME resolving disabled on '%s'", dns_question_first_name(q->question));
974 goto finish;
975 }
976 if (r < 0)
977 goto finish;
978 if (r == DNS_QUERY_RESTARTED) /* This was a cname, and the query was restarted. */
979 return;
980
981 if (q->answer) {
982 bool has_root_domain = false;
983 DnsResourceRecord *rr;
984 int ifindex;
985
986 DNS_ANSWER_FOREACH_IFINDEX(rr, ifindex, q->answer) {
987 r = dns_question_matches_rr(q->question, rr, NULL);
988 if (r < 0)
989 goto finish;
990 if (r == 0)
991 continue;
992
993 if (rr->key->type != DNS_TYPE_SRV)
994 continue;
995
996 if (dns_name_is_root(rr->srv.name)) {
997 has_root_domain = true;
998 continue;
999 }
1000
1001 if ((q->flags & SD_RESOLVED_NO_ADDRESS) == 0) {
1002 q->block_all_complete ++;
1003 r = resolve_service_hostname(q, rr, ifindex);
1004 q->block_all_complete --;
1005
1006 if (r < 0)
1007 goto finish;
1008 }
1009
1010 found++;
1011 }
1012
1013 if (has_root_domain && found == 0) {
1014 /* If there's exactly one SRV RR and it uses
1015 * the root domain as host name, then the
1016 * service is explicitly not offered on the
1017 * domain. Report this as a recognizable
1018 * error. See RFC 2782, Section "Usage
1019 * Rules". */
1020 r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_NO_SUCH_SERVICE, "'%s' does not provide the requested service", dns_question_first_name(q->question));
1021 goto finish;
1022 }
1023
1024 }
1025
1026 if (found <= 0) {
1027 r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_NO_SUCH_RR, "'%s' does not have any RR of the requested type", dns_question_first_name(q->question));
1028 goto finish;
1029 }
1030
1031 /* Maybe we are already finished? check now... */
1032 resolve_service_all_complete(q);
1033 return;
1034
1035 finish:
1036 if (r < 0) {
1037 log_error_errno(r, "Failed to send service reply: %m");
1038 sd_bus_reply_method_errno(q->request, r, NULL);
1039 }
1040
1041 dns_query_free(q);
1042 }
1043
1044 static int bus_method_resolve_service(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1045 _cleanup_(dns_question_unrefp) DnsQuestion *question = NULL;
1046 const char *name, *type, *domain, *joined;
1047 _cleanup_free_ char *n = NULL;
1048 Manager *m = userdata;
1049 int family, ifindex;
1050 uint64_t flags;
1051 DnsQuery *q;
1052 int r;
1053
1054 assert(message);
1055 assert(m);
1056
1057 assert_cc(sizeof(int) == sizeof(int32_t));
1058
1059 r = sd_bus_message_read(message, "isssit", &ifindex, &name, &type, &domain, &family, &flags);
1060 if (r < 0)
1061 return r;
1062
1063 if (!IN_SET(family, AF_INET, AF_INET6, AF_UNSPEC))
1064 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown address family %i", family);
1065
1066 if (isempty(name))
1067 name = NULL;
1068 else {
1069 if (!dns_service_name_is_valid(name))
1070 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid service name '%s'", name);
1071 }
1072
1073 if (isempty(type))
1074 type = NULL;
1075 else if (!dns_srv_type_is_valid(type))
1076 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid SRV service type '%s'", type);
1077
1078 r = dns_name_is_valid(domain);
1079 if (r < 0)
1080 return r;
1081 if (r == 0)
1082 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid domain '%s'", domain);
1083
1084 if (name && !type)
1085 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Service name cannot be specified without service type.");
1086
1087 r = check_ifindex_flags(ifindex, &flags, SD_RESOLVED_NO_TXT|SD_RESOLVED_NO_ADDRESS, error);
1088 if (r < 0)
1089 return r;
1090
1091 if (type) {
1092 /* If the type is specified, we generate the full domain name to look up ourselves */
1093 r = dns_service_join(name, type, domain, &n);
1094 if (r < 0)
1095 return r;
1096
1097 joined = n;
1098 } else
1099 /* If no type is specified, we assume the domain
1100 * contains the full domain name to lookup already */
1101 joined = domain;
1102
1103 r = dns_question_new_service(&question, joined, !(flags & SD_RESOLVED_NO_TXT));
1104 if (r < 0)
1105 return r;
1106
1107 r = dns_query_new(m, &q, question, ifindex, flags|SD_RESOLVED_NO_SEARCH);
1108 if (r < 0)
1109 return r;
1110
1111 q->request = sd_bus_message_ref(message);
1112 q->request_family = family;
1113 q->complete = bus_method_resolve_service_complete;
1114
1115 r = dns_query_bus_track(q, message);
1116 if (r < 0)
1117 goto fail;
1118
1119 r = dns_query_go(q);
1120 if (r < 0)
1121 goto fail;
1122
1123 return 1;
1124
1125 fail:
1126 dns_query_free(q);
1127 return r;
1128 }
1129
1130 static int append_dns_server(sd_bus_message *reply, DnsServer *s) {
1131 int r;
1132
1133 assert(reply);
1134 assert(s);
1135
1136 r = sd_bus_message_open_container(reply, 'r', "iiay");
1137 if (r < 0)
1138 return r;
1139
1140 r = sd_bus_message_append(reply, "ii", s->link ? s->link->ifindex : 0, s->family);
1141 if (r < 0)
1142 return r;
1143
1144 r = sd_bus_message_append_array(reply, 'y', &s->address, FAMILY_ADDRESS_SIZE(s->family));
1145 if (r < 0)
1146 return r;
1147
1148 return sd_bus_message_close_container(reply);
1149 }
1150
1151 static int bus_property_get_dns_servers(
1152 sd_bus *bus,
1153 const char *path,
1154 const char *interface,
1155 const char *property,
1156 sd_bus_message *reply,
1157 void *userdata,
1158 sd_bus_error *error) {
1159
1160 Manager *m = userdata;
1161 unsigned c = 0;
1162 DnsServer *s;
1163 Iterator i;
1164 Link *l;
1165 int r;
1166
1167 assert(reply);
1168 assert(m);
1169
1170 r = sd_bus_message_open_container(reply, 'a', "(iiay)");
1171 if (r < 0)
1172 return r;
1173
1174 LIST_FOREACH(servers, s, m->dns_servers) {
1175 r = append_dns_server(reply, s);
1176 if (r < 0)
1177 return r;
1178
1179 c++;
1180 }
1181
1182 HASHMAP_FOREACH(l, m->links, i) {
1183 LIST_FOREACH(servers, s, l->dns_servers) {
1184 r = append_dns_server(reply, s);
1185 if (r < 0)
1186 return r;
1187 c++;
1188 }
1189 }
1190
1191 if (c == 0) {
1192 LIST_FOREACH(servers, s, m->fallback_dns_servers) {
1193 r = append_dns_server(reply, s);
1194 if (r < 0)
1195 return r;
1196 }
1197 }
1198
1199 return sd_bus_message_close_container(reply);
1200 }
1201
1202 static int bus_property_get_search_domains(
1203 sd_bus *bus,
1204 const char *path,
1205 const char *interface,
1206 const char *property,
1207 sd_bus_message *reply,
1208 void *userdata,
1209 sd_bus_error *error) {
1210
1211 Manager *m = userdata;
1212 DnsSearchDomain *d;
1213 Iterator i;
1214 Link *l;
1215 int r;
1216
1217 assert(reply);
1218 assert(m);
1219
1220 r = sd_bus_message_open_container(reply, 'a', "(is)");
1221 if (r < 0)
1222 return r;
1223
1224 LIST_FOREACH(domains, d, m->search_domains) {
1225 r = sd_bus_message_append(reply, "(is)", 0, d->name);
1226 if (r < 0)
1227 return r;
1228 }
1229
1230 HASHMAP_FOREACH(l, m->links, i) {
1231 LIST_FOREACH(domains, d, l->search_domains) {
1232 r = sd_bus_message_append(reply, "is", l->ifindex, d->name);
1233 if (r < 0)
1234 return r;
1235 }
1236 }
1237
1238 return sd_bus_message_close_container(reply);
1239 }
1240
1241 static int bus_property_get_transaction_statistics(
1242 sd_bus *bus,
1243 const char *path,
1244 const char *interface,
1245 const char *property,
1246 sd_bus_message *reply,
1247 void *userdata,
1248 sd_bus_error *error) {
1249
1250 Manager *m = userdata;
1251
1252 assert(reply);
1253 assert(m);
1254
1255 return sd_bus_message_append(reply, "(tt)",
1256 (uint64_t) hashmap_size(m->dns_transactions),
1257 (uint64_t) m->n_transactions_total);
1258 }
1259
1260 static int bus_property_get_cache_statistics(
1261 sd_bus *bus,
1262 const char *path,
1263 const char *interface,
1264 const char *property,
1265 sd_bus_message *reply,
1266 void *userdata,
1267 sd_bus_error *error) {
1268
1269 uint64_t size = 0, hit = 0, miss = 0;
1270 Manager *m = userdata;
1271 DnsScope *s;
1272
1273 assert(reply);
1274 assert(m);
1275
1276 LIST_FOREACH(scopes, s, m->dns_scopes) {
1277 size += dns_cache_size(&s->cache);
1278 hit += s->cache.n_hit;
1279 miss += s->cache.n_miss;
1280 }
1281
1282 return sd_bus_message_append(reply, "(ttt)", size, hit, miss);
1283 }
1284
1285 static int bus_property_get_dnssec_statistics(
1286 sd_bus *bus,
1287 const char *path,
1288 const char *interface,
1289 const char *property,
1290 sd_bus_message *reply,
1291 void *userdata,
1292 sd_bus_error *error) {
1293
1294 Manager *m = userdata;
1295
1296 assert(reply);
1297 assert(m);
1298
1299 return sd_bus_message_append(reply, "(tttt)",
1300 (uint64_t) m->n_dnssec_secure,
1301 (uint64_t) m->n_dnssec_insecure,
1302 (uint64_t) m->n_dnssec_bogus,
1303 (uint64_t) m->n_dnssec_indeterminate);
1304 }
1305
1306 static int bus_method_reset_statistics(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1307 Manager *m = userdata;
1308 DnsScope *s;
1309
1310 assert(message);
1311 assert(m);
1312
1313 LIST_FOREACH(scopes, s, m->dns_scopes)
1314 s->cache.n_hit = s->cache.n_miss = 0;
1315
1316 m->n_transactions_total = 0;
1317 m->n_dnssec_secure = m->n_dnssec_insecure = m->n_dnssec_bogus = m->n_dnssec_indeterminate = 0;
1318
1319 return sd_bus_reply_method_return(message, NULL);
1320 }
1321
1322 static const sd_bus_vtable resolve_vtable[] = {
1323 SD_BUS_VTABLE_START(0),
1324 SD_BUS_PROPERTY("LLMNRHostname", "s", NULL, offsetof(Manager, llmnr_hostname), 0),
1325 SD_BUS_PROPERTY("DNSServers", "a(iiay)", bus_property_get_dns_servers, 0, 0),
1326 SD_BUS_PROPERTY("SearchDomains", "a(is)", bus_property_get_search_domains, 0, 0),
1327 SD_BUS_PROPERTY("TransactionStatistics", "(tt)", bus_property_get_transaction_statistics, 0, 0),
1328 SD_BUS_PROPERTY("CacheStatistics", "(ttt)", bus_property_get_cache_statistics, 0, 0),
1329 SD_BUS_PROPERTY("DNSSECStatistics", "(tttt)", bus_property_get_dnssec_statistics, 0, 0),
1330
1331 SD_BUS_METHOD("ResolveHostname", "isit", "a(iiay)st", bus_method_resolve_hostname, SD_BUS_VTABLE_UNPRIVILEGED),
1332 SD_BUS_METHOD("ResolveAddress", "iiayt", "a(is)t", bus_method_resolve_address, SD_BUS_VTABLE_UNPRIVILEGED),
1333 SD_BUS_METHOD("ResolveRecord", "isqqt", "a(iqqay)t", bus_method_resolve_record, SD_BUS_VTABLE_UNPRIVILEGED),
1334 SD_BUS_METHOD("ResolveService", "isssit", "a(qqqsa(iiay)s)aayssst", bus_method_resolve_service, SD_BUS_VTABLE_UNPRIVILEGED),
1335 SD_BUS_METHOD("ResetStatistics", NULL, NULL, bus_method_reset_statistics, 0),
1336 SD_BUS_VTABLE_END,
1337 };
1338
1339 static int on_bus_retry(sd_event_source *s, usec_t usec, void *userdata) {
1340 Manager *m = userdata;
1341
1342 assert(s);
1343 assert(m);
1344
1345 m->bus_retry_event_source = sd_event_source_unref(m->bus_retry_event_source);
1346
1347 manager_connect_bus(m);
1348 return 0;
1349 }
1350
1351 static int match_prepare_for_sleep(sd_bus_message *message, void *userdata, sd_bus_error *ret_error) {
1352 Manager *m = userdata;
1353 int b, r;
1354
1355 assert(message);
1356 assert(m);
1357
1358 r = sd_bus_message_read(message, "b", &b);
1359 if (r < 0) {
1360 log_debug_errno(r, "Failed to parse PrepareForSleep signal: %m");
1361 return 0;
1362 }
1363
1364 if (b)
1365 return 0;
1366
1367 log_debug("Coming back from suspend, verifying all RRs...");
1368
1369 manager_verify_all(m);
1370 return 0;
1371 }
1372
1373 int manager_connect_bus(Manager *m) {
1374 int r;
1375
1376 assert(m);
1377
1378 if (m->bus)
1379 return 0;
1380
1381 r = sd_bus_default_system(&m->bus);
1382 if (r < 0) {
1383 /* We failed to connect? Yuck, we must be in early
1384 * boot. Let's try in 5s again. As soon as we have
1385 * kdbus we can stop doing this... */
1386
1387 log_debug_errno(r, "Failed to connect to bus, trying again in 5s: %m");
1388
1389 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);
1390 if (r < 0)
1391 return log_error_errno(r, "Failed to install bus reconnect time event: %m");
1392
1393 (void) sd_event_source_set_description(m->bus_retry_event_source, "bus-retry");
1394 return 0;
1395 }
1396
1397 r = sd_bus_add_object_vtable(m->bus, NULL, "/org/freedesktop/resolve1", "org.freedesktop.resolve1.Manager", resolve_vtable, m);
1398 if (r < 0)
1399 return log_error_errno(r, "Failed to register object: %m");
1400
1401 r = sd_bus_request_name(m->bus, "org.freedesktop.resolve1", 0);
1402 if (r < 0)
1403 return log_error_errno(r, "Failed to register name: %m");
1404
1405 r = sd_bus_attach_event(m->bus, m->event, 0);
1406 if (r < 0)
1407 return log_error_errno(r, "Failed to attach bus to event loop: %m");
1408
1409 r = sd_bus_add_match(m->bus, &m->prepare_for_sleep_slot,
1410 "type='signal',"
1411 "sender='org.freedesktop.login1',"
1412 "interface='org.freedesktop.login1.Manager',"
1413 "member='PrepareForSleep',"
1414 "path='/org/freedesktop/login1'",
1415 match_prepare_for_sleep,
1416 m);
1417 if (r < 0)
1418 log_error_errno(r, "Failed to add match for PrepareForSleep: %m");
1419
1420 return 0;
1421 }