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