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