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