]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/resolve/resolved-bus.c
resolved: add dns_packet_set_flags()
[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_FAILURE: {
64 _cleanup_(sd_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_(sd_bus_message_unrefp) 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_first_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, DNS_SEARCH_DOMAIN_NAME(q->answer_search_domain));
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_first_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, q->answer_authenticated));
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, SD_RESOLVED_NO_SEARCH, 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_(sd_bus_message_unrefp) 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_first_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, NULL);
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, q->answer_authenticated));
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|SD_RESOLVED_NO_SEARCH);
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 int r;
429
430 assert(m);
431 assert(rr);
432
433 r = sd_bus_message_open_container(m, 'r', "iqqay");
434 if (r < 0)
435 return r;
436
437 r = sd_bus_message_append(m, "iqq",
438 ifindex,
439 rr->key->class,
440 rr->key->type);
441 if (r < 0)
442 return r;
443
444 r = dns_resource_record_to_wire_format(rr, false);
445 if (r < 0)
446 return r;
447
448 r = sd_bus_message_append_array(m, 'y', rr->wire_format, rr->wire_format_size);
449 if (r < 0)
450 return r;
451
452 return sd_bus_message_close_container(m);
453 }
454
455 static void bus_method_resolve_record_complete(DnsQuery *q) {
456 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
457 unsigned added = 0;
458 int r;
459
460 assert(q);
461
462 if (q->state != DNS_TRANSACTION_SUCCESS) {
463 r = reply_query_state(q);
464 goto finish;
465 }
466
467 r = dns_query_process_cname(q);
468 if (r == -ELOOP) {
469 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));
470 goto finish;
471 }
472 if (r < 0)
473 goto finish;
474 if (r > 0) /* Following a CNAME */
475 return;
476
477 r = sd_bus_message_new_method_return(q->request, &reply);
478 if (r < 0)
479 goto finish;
480
481 r = sd_bus_message_open_container(reply, 'a', "(iqqay)");
482 if (r < 0)
483 goto finish;
484
485 if (q->answer) {
486 DnsResourceRecord *rr;
487 int ifindex;
488
489 DNS_ANSWER_FOREACH_IFINDEX(rr, ifindex, q->answer) {
490 r = dns_question_matches_rr(q->question, rr, NULL);
491 if (r < 0)
492 goto finish;
493 if (r == 0)
494 continue;
495
496 r = bus_message_append_rr(reply, rr, ifindex);
497 if (r < 0)
498 goto finish;
499
500 added ++;
501 }
502 }
503
504 if (added <= 0) {
505 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));
506 goto finish;
507 }
508
509 r = sd_bus_message_close_container(reply);
510 if (r < 0)
511 goto finish;
512
513 r = sd_bus_message_append(reply, "t", SD_RESOLVED_FLAGS_MAKE(q->answer_protocol, q->answer_family, q->answer_authenticated));
514 if (r < 0)
515 goto finish;
516
517 r = sd_bus_send(q->manager->bus, reply, NULL);
518
519 finish:
520 if (r < 0) {
521 log_error_errno(r, "Failed to send record reply: %m");
522 sd_bus_reply_method_errno(q->request, r, NULL);
523 }
524
525 dns_query_free(q);
526 }
527
528 static int bus_method_resolve_record(sd_bus_message *message, void *userdata, sd_bus_error *error) {
529 _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
530 _cleanup_(dns_question_unrefp) DnsQuestion *question = NULL;
531 Manager *m = userdata;
532 uint16_t class, type;
533 const char *name;
534 int r, ifindex;
535 uint64_t flags;
536 DnsQuery *q;
537
538 assert(message);
539 assert(m);
540
541 assert_cc(sizeof(int) == sizeof(int32_t));
542
543 r = sd_bus_message_read(message, "isqqt", &ifindex, &name, &class, &type, &flags);
544 if (r < 0)
545 return r;
546
547 r = dns_name_is_valid(name);
548 if (r < 0)
549 return r;
550 if (r == 0)
551 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid name '%s'", name);
552
553 r = check_ifindex_flags(ifindex, &flags, 0, error);
554 if (r < 0)
555 return r;
556
557 question = dns_question_new(1);
558 if (!question)
559 return -ENOMEM;
560
561 key = dns_resource_key_new(class, type, name);
562 if (!key)
563 return -ENOMEM;
564
565 r = dns_question_add(question, key);
566 if (r < 0)
567 return r;
568
569 r = dns_query_new(m, &q, question, ifindex, flags|SD_RESOLVED_NO_SEARCH);
570 if (r < 0)
571 return r;
572
573 q->request = sd_bus_message_ref(message);
574 q->complete = bus_method_resolve_record_complete;
575
576 r = dns_query_bus_track(q, message);
577 if (r < 0)
578 goto fail;
579
580 r = dns_query_go(q);
581 if (r < 0)
582 goto fail;
583
584 return 1;
585
586 fail:
587 dns_query_free(q);
588 return r;
589 }
590
591 static int append_srv(DnsQuery *q, sd_bus_message *reply, DnsResourceRecord *rr) {
592 _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *canonical = NULL;
593 DnsQuery *aux;
594 int r;
595
596 assert(q);
597 assert(reply);
598 assert(rr);
599 assert(rr->key);
600
601 if (rr->key->type != DNS_TYPE_SRV)
602 return 0;
603
604 if ((q->flags & SD_RESOLVED_NO_ADDRESS) == 0) {
605 /* First, let's see if we could find an appropriate A or AAAA
606 * record for the SRV record */
607 LIST_FOREACH(auxiliary_queries, aux, q->auxiliary_queries) {
608 DnsResourceRecord *zz;
609
610 if (aux->state != DNS_TRANSACTION_SUCCESS)
611 continue;
612 if (aux->auxiliary_result != 0)
613 continue;
614
615 r = dns_name_equal(dns_question_first_name(aux->question), rr->srv.name);
616 if (r < 0)
617 return r;
618 if (r == 0)
619 continue;
620
621 DNS_ANSWER_FOREACH(zz, aux->answer) {
622
623 r = dns_question_matches_rr(aux->question, zz, NULL);
624 if (r < 0)
625 return r;
626 if (r == 0)
627 continue;
628
629 canonical = dns_resource_record_ref(zz);
630 break;
631 }
632
633 if (canonical)
634 break;
635 }
636
637 /* Is there are successful A/AAAA lookup for this SRV RR? If not, don't add it */
638 if (!canonical)
639 return 0;
640 }
641
642 r = sd_bus_message_open_container(reply, 'r', "qqqsa(iiay)s");
643 if (r < 0)
644 return r;
645
646 r = sd_bus_message_append(
647 reply,
648 "qqqs",
649 rr->srv.priority, rr->srv.weight, rr->srv.port, rr->srv.name);
650 if (r < 0)
651 return r;
652
653 r = sd_bus_message_open_container(reply, 'a', "(iiay)");
654 if (r < 0)
655 return r;
656
657 if ((q->flags & SD_RESOLVED_NO_ADDRESS) == 0) {
658 LIST_FOREACH(auxiliary_queries, aux, q->auxiliary_queries) {
659 DnsResourceRecord *zz;
660 int ifindex;
661
662 if (aux->state != DNS_TRANSACTION_SUCCESS)
663 continue;
664 if (aux->auxiliary_result != 0)
665 continue;
666
667 r = dns_name_equal(dns_question_first_name(aux->question), rr->srv.name);
668 if (r < 0)
669 return r;
670 if (r == 0)
671 continue;
672
673 DNS_ANSWER_FOREACH_IFINDEX(zz, ifindex, aux->answer) {
674
675 r = dns_question_matches_rr(aux->question, zz, NULL);
676 if (r < 0)
677 return r;
678 if (r == 0)
679 continue;
680
681 r = append_address(reply, zz, ifindex);
682 if (r < 0)
683 return r;
684 }
685 }
686 }
687
688 r = sd_bus_message_close_container(reply);
689 if (r < 0)
690 return r;
691
692 /* Note that above we appended the hostname as encoded in the
693 * SRV, and here the canonical hostname this maps to. */
694 r = sd_bus_message_append(reply, "s", canonical ? DNS_RESOURCE_KEY_NAME(canonical->key) : rr->srv.name);
695 if (r < 0)
696 return r;
697
698 r = sd_bus_message_close_container(reply);
699 if (r < 0)
700 return r;
701
702 return 1;
703 }
704
705 static int append_txt(sd_bus_message *reply, DnsResourceRecord *rr) {
706 DnsTxtItem *i;
707 int r;
708
709 assert(reply);
710 assert(rr);
711 assert(rr->key);
712
713 if (rr->key->type != DNS_TYPE_TXT)
714 return 0;
715
716 LIST_FOREACH(items, i, rr->txt.items) {
717
718 if (i->length <= 0)
719 continue;
720
721 r = sd_bus_message_append_array(reply, 'y', i->data, i->length);
722 if (r < 0)
723 return r;
724 }
725
726 return 1;
727 }
728
729 static void resolve_service_all_complete(DnsQuery *q) {
730 _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *canonical = NULL;
731 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
732 _cleanup_free_ char *name = NULL, *type = NULL, *domain = NULL;
733 DnsQuery *aux;
734 unsigned added = false;
735 int r;
736
737 assert(q);
738
739 if (q->block_all_complete > 0)
740 return;
741
742 if ((q->flags & SD_RESOLVED_NO_ADDRESS) == 0) {
743 DnsQuery *bad = NULL;
744 bool have_success = false;
745
746 LIST_FOREACH(auxiliary_queries, aux, q->auxiliary_queries) {
747
748 switch (aux->state) {
749
750 case DNS_TRANSACTION_PENDING:
751 /* If an auxiliary query is still pending, let's wait */
752 return;
753
754 case DNS_TRANSACTION_SUCCESS:
755 if (aux->auxiliary_result == 0)
756 have_success = true;
757 else
758 bad = aux;
759 break;
760
761 default:
762 bad = aux;
763 break;
764 }
765 }
766
767 if (!have_success) {
768 /* We can only return one error, hence pick the last error we encountered */
769
770 assert(bad);
771
772 if (bad->state == DNS_TRANSACTION_SUCCESS) {
773 assert(bad->auxiliary_result != 0);
774
775 if (bad->auxiliary_result == -ELOOP) {
776 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));
777 goto finish;
778 }
779
780 r = bad->auxiliary_result;
781 goto finish;
782 }
783
784 r = reply_query_state(bad);
785 goto finish;
786 }
787 }
788
789 r = sd_bus_message_new_method_return(q->request, &reply);
790 if (r < 0)
791 goto finish;
792
793 r = sd_bus_message_open_container(reply, 'a', "(qqqsa(iiay)s)");
794 if (r < 0)
795 goto finish;
796
797 if (q->answer) {
798 DnsResourceRecord *rr;
799
800 DNS_ANSWER_FOREACH(rr, q->answer) {
801 r = dns_question_matches_rr(q->question, rr, NULL);
802 if (r < 0)
803 goto finish;
804 if (r == 0)
805 continue;
806
807 r = append_srv(q, reply, rr);
808 if (r < 0)
809 goto finish;
810 if (r == 0) /* not an SRV record */
811 continue;
812
813 if (!canonical)
814 canonical = dns_resource_record_ref(rr);
815
816 added++;
817 }
818 }
819
820 if (added <= 0) {
821 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));
822 goto finish;
823 }
824
825 r = sd_bus_message_close_container(reply);
826 if (r < 0)
827 goto finish;
828
829 r = sd_bus_message_open_container(reply, 'a', "ay");
830 if (r < 0)
831 goto finish;
832
833 if (q->answer) {
834 DnsResourceRecord *rr;
835
836 DNS_ANSWER_FOREACH(rr, q->answer) {
837 r = dns_question_matches_rr(q->question, rr, NULL);
838 if (r < 0)
839 goto finish;
840 if (r == 0)
841 continue;
842
843 r = append_txt(reply, rr);
844 if (r < 0)
845 goto finish;
846 }
847 }
848
849 r = sd_bus_message_close_container(reply);
850 if (r < 0)
851 goto finish;
852
853 assert(canonical);
854 r = dns_service_split(DNS_RESOURCE_KEY_NAME(canonical->key), &name, &type, &domain);
855 if (r < 0)
856 goto finish;
857
858 r = sd_bus_message_append(
859 reply,
860 "ssst",
861 name, type, domain,
862 SD_RESOLVED_FLAGS_MAKE(q->answer_protocol, q->answer_family, q->answer_authenticated));
863 if (r < 0)
864 goto finish;
865
866 r = sd_bus_send(q->manager->bus, reply, NULL);
867
868 finish:
869 if (r < 0) {
870 log_error_errno(r, "Failed to send service reply: %m");
871 sd_bus_reply_method_errno(q->request, r, NULL);
872 }
873
874 dns_query_free(q);
875 }
876
877 static void resolve_service_hostname_complete(DnsQuery *q) {
878 int r;
879
880 assert(q);
881 assert(q->auxiliary_for);
882
883 if (q->state != DNS_TRANSACTION_SUCCESS) {
884 resolve_service_all_complete(q->auxiliary_for);
885 return;
886 }
887
888 r = dns_query_process_cname(q);
889 if (r > 0) /* This was a cname, and the query was restarted. */
890 return;
891
892 /* This auxiliary lookup is finished or failed, let's see if all are finished now. */
893 q->auxiliary_result = r;
894 resolve_service_all_complete(q->auxiliary_for);
895 }
896
897 static int resolve_service_hostname(DnsQuery *q, DnsResourceRecord *rr, int ifindex) {
898 _cleanup_(dns_question_unrefp) DnsQuestion *question = NULL;
899 DnsQuery *aux;
900 int r;
901
902 assert(q);
903 assert(rr);
904 assert(rr->key);
905 assert(rr->key->type == DNS_TYPE_SRV);
906
907 /* OK, we found an SRV record for the service. Let's resolve
908 * the hostname included in it */
909
910 r = dns_question_new_address(&question, q->request_family, rr->srv.name);
911 if (r < 0)
912 return r;
913
914 r = dns_query_new(q->manager, &aux, question, ifindex, q->flags|SD_RESOLVED_NO_SEARCH);
915 if (r < 0)
916 return r;
917
918 aux->request_family = q->request_family;
919 aux->complete = resolve_service_hostname_complete;
920
921 r = dns_query_make_auxiliary(aux, q);
922 if (r == -EAGAIN) {
923 /* Too many auxiliary lookups? If so, don't complain,
924 * let's just not add this one, we already have more
925 * than enough */
926
927 dns_query_free(aux);
928 return 0;
929 }
930 if (r < 0)
931 goto fail;
932
933 /* Note that auxiliary queries do not track the original bus
934 * client, only the primary request does that. */
935
936 r = dns_query_go(aux);
937 if (r < 0)
938 goto fail;
939
940 return 1;
941
942 fail:
943 dns_query_free(aux);
944 return r;
945 }
946
947 static void bus_method_resolve_service_complete(DnsQuery *q) {
948 unsigned found = 0;
949 int r;
950
951 assert(q);
952
953 if (q->state != DNS_TRANSACTION_SUCCESS) {
954 r = reply_query_state(q);
955 goto finish;
956 }
957
958 r = dns_query_process_cname(q);
959 if (r == -ELOOP) {
960 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));
961 goto finish;
962 }
963 if (r < 0)
964 goto finish;
965 if (r > 0) /* This was a cname, and the query was restarted. */
966 return;
967
968 if (q->answer) {
969 DnsResourceRecord *rr;
970 int ifindex;
971
972 DNS_ANSWER_FOREACH_IFINDEX(rr, ifindex, q->answer) {
973 r = dns_question_matches_rr(q->question, rr, NULL);
974 if (r < 0)
975 goto finish;
976 if (r == 0)
977 continue;
978
979 if (rr->key->type != DNS_TYPE_SRV)
980 continue;
981
982 if ((q->flags & SD_RESOLVED_NO_ADDRESS) == 0) {
983 q->block_all_complete ++;
984 r = resolve_service_hostname(q, rr, ifindex);
985 q->block_all_complete --;
986
987 if (r < 0)
988 goto finish;
989 }
990
991 found++;
992 }
993 }
994
995 if (found <= 0) {
996 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));
997 goto finish;
998 }
999
1000 /* Maybe we are already finished? check now... */
1001 resolve_service_all_complete(q);
1002 return;
1003
1004 finish:
1005 if (r < 0) {
1006 log_error_errno(r, "Failed to send service reply: %m");
1007 sd_bus_reply_method_errno(q->request, r, NULL);
1008 }
1009
1010 dns_query_free(q);
1011 }
1012
1013 static int bus_method_resolve_service(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1014 _cleanup_(dns_question_unrefp) DnsQuestion *question = NULL;
1015 const char *name, *type, *domain, *joined;
1016 _cleanup_free_ char *n = NULL;
1017 Manager *m = userdata;
1018 int family, ifindex;
1019 uint64_t flags;
1020 DnsQuery *q;
1021 int r;
1022
1023 assert(message);
1024 assert(m);
1025
1026 assert_cc(sizeof(int) == sizeof(int32_t));
1027
1028 r = sd_bus_message_read(message, "isssit", &ifindex, &name, &type, &domain, &family, &flags);
1029 if (r < 0)
1030 return r;
1031
1032 if (!IN_SET(family, AF_INET, AF_INET6, AF_UNSPEC))
1033 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown address family %i", family);
1034
1035 if (isempty(name))
1036 name = NULL;
1037 else {
1038 if (!dns_service_name_is_valid(name))
1039 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid service name '%s'", name);
1040 }
1041
1042 if (isempty(type))
1043 type = NULL;
1044 else if (!dns_srv_type_is_valid(type))
1045 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid SRV service type '%s'", type);
1046
1047 r = dns_name_is_valid(domain);
1048 if (r < 0)
1049 return r;
1050 if (r == 0)
1051 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid domain '%s'", domain);
1052
1053 if (name && !type)
1054 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Service name cannot be specified without service type.");
1055
1056 r = check_ifindex_flags(ifindex, &flags, SD_RESOLVED_NO_TXT|SD_RESOLVED_NO_ADDRESS, error);
1057 if (r < 0)
1058 return r;
1059
1060 if (type) {
1061 /* If the type is specified, we generate the full domain name to look up ourselves */
1062 r = dns_service_join(name, type, domain, &n);
1063 if (r < 0)
1064 return r;
1065
1066 joined = n;
1067 } else
1068 /* If no type is specified, we assume the domain
1069 * contains the full domain name to lookup already */
1070 joined = domain;
1071
1072 r = dns_question_new_service(&question, joined, !(flags & SD_RESOLVED_NO_TXT));
1073 if (r < 0)
1074 return r;
1075
1076 r = dns_query_new(m, &q, question, ifindex, flags|SD_RESOLVED_NO_SEARCH);
1077 if (r < 0)
1078 return r;
1079
1080 q->request = sd_bus_message_ref(message);
1081 q->request_family = family;
1082 q->complete = bus_method_resolve_service_complete;
1083
1084 r = dns_query_bus_track(q, message);
1085 if (r < 0)
1086 goto fail;
1087
1088 r = dns_query_go(q);
1089 if (r < 0)
1090 goto fail;
1091
1092 return 1;
1093
1094 fail:
1095 dns_query_free(q);
1096 return r;
1097 }
1098
1099 static int append_dns_server(sd_bus_message *reply, DnsServer *s) {
1100 int r;
1101
1102 assert(reply);
1103 assert(s);
1104
1105 r = sd_bus_message_open_container(reply, 'r', "iiay");
1106 if (r < 0)
1107 return r;
1108
1109 r = sd_bus_message_append(reply, "ii", s->link ? s->link->ifindex : 0, s->family);
1110 if (r < 0)
1111 return r;
1112
1113 r = sd_bus_message_append_array(reply, 'y', &s->address, FAMILY_ADDRESS_SIZE(s->family));
1114 if (r < 0)
1115 return r;
1116
1117 return sd_bus_message_close_container(reply);
1118 }
1119
1120 static int bus_property_get_dns_servers(
1121 sd_bus *bus,
1122 const char *path,
1123 const char *interface,
1124 const char *property,
1125 sd_bus_message *reply,
1126 void *userdata,
1127 sd_bus_error *error) {
1128
1129 Manager *m = userdata;
1130 unsigned c = 0;
1131 DnsServer *s;
1132 Iterator i;
1133 Link *l;
1134 int r;
1135
1136 assert(reply);
1137 assert(m);
1138
1139 r = sd_bus_message_open_container(reply, 'a', "(iiay)");
1140 if (r < 0)
1141 return r;
1142
1143 LIST_FOREACH(servers, s, m->dns_servers) {
1144 r = append_dns_server(reply, s);
1145 if (r < 0)
1146 return r;
1147
1148 c++;
1149 }
1150
1151 HASHMAP_FOREACH(l, m->links, i) {
1152 LIST_FOREACH(servers, s, l->dns_servers) {
1153 r = append_dns_server(reply, s);
1154 if (r < 0)
1155 return r;
1156 c++;
1157 }
1158 }
1159
1160 if (c == 0) {
1161 LIST_FOREACH(servers, s, m->fallback_dns_servers) {
1162 r = append_dns_server(reply, s);
1163 if (r < 0)
1164 return r;
1165 }
1166 }
1167
1168 return sd_bus_message_close_container(reply);
1169 }
1170
1171 static int bus_property_get_search_domains(
1172 sd_bus *bus,
1173 const char *path,
1174 const char *interface,
1175 const char *property,
1176 sd_bus_message *reply,
1177 void *userdata,
1178 sd_bus_error *error) {
1179
1180 Manager *m = userdata;
1181 DnsSearchDomain *d;
1182 Iterator i;
1183 Link *l;
1184 int r;
1185
1186 assert(reply);
1187 assert(m);
1188
1189 r = sd_bus_message_open_container(reply, 'a', "(is)");
1190 if (r < 0)
1191 return r;
1192
1193 LIST_FOREACH(domains, d, m->search_domains) {
1194 r = sd_bus_message_append(reply, "(is)", 0, d->name);
1195 if (r < 0)
1196 return r;
1197 }
1198
1199 HASHMAP_FOREACH(l, m->links, i) {
1200 LIST_FOREACH(domains, d, l->search_domains) {
1201 r = sd_bus_message_append(reply, "is", l->ifindex, d->name);
1202 if (r < 0)
1203 return r;
1204 }
1205 }
1206
1207 return sd_bus_message_close_container(reply);
1208 }
1209
1210 static const sd_bus_vtable resolve_vtable[] = {
1211 SD_BUS_VTABLE_START(0),
1212 SD_BUS_PROPERTY("LLMNRHostname", "s", NULL, offsetof(Manager, llmnr_hostname), 0),
1213 SD_BUS_PROPERTY("DNSServers", "a(iiay)", bus_property_get_dns_servers, 0, 0),
1214 SD_BUS_PROPERTY("SearchDomains", "a(is)", bus_property_get_search_domains, 0, 0),
1215
1216 SD_BUS_METHOD("ResolveHostname", "isit", "a(iiay)st", bus_method_resolve_hostname, SD_BUS_VTABLE_UNPRIVILEGED),
1217 SD_BUS_METHOD("ResolveAddress", "iiayt", "a(is)t", bus_method_resolve_address, SD_BUS_VTABLE_UNPRIVILEGED),
1218 SD_BUS_METHOD("ResolveRecord", "isqqt", "a(iqqay)t", bus_method_resolve_record, SD_BUS_VTABLE_UNPRIVILEGED),
1219 SD_BUS_METHOD("ResolveService", "isssit", "a(qqqsa(iiay)s)aayssst", bus_method_resolve_service, SD_BUS_VTABLE_UNPRIVILEGED),
1220 SD_BUS_VTABLE_END,
1221 };
1222
1223 static int on_bus_retry(sd_event_source *s, usec_t usec, void *userdata) {
1224 Manager *m = userdata;
1225
1226 assert(s);
1227 assert(m);
1228
1229 m->bus_retry_event_source = sd_event_source_unref(m->bus_retry_event_source);
1230
1231 manager_connect_bus(m);
1232 return 0;
1233 }
1234
1235 static int match_prepare_for_sleep(sd_bus_message *message, void *userdata, sd_bus_error *ret_error) {
1236 Manager *m = userdata;
1237 int b, r;
1238
1239 assert(message);
1240 assert(m);
1241
1242 r = sd_bus_message_read(message, "b", &b);
1243 if (r < 0) {
1244 log_debug_errno(r, "Failed to parse PrepareForSleep signal: %m");
1245 return 0;
1246 }
1247
1248 if (b)
1249 return 0;
1250
1251 log_debug("Coming back from suspend, verifying all RRs...");
1252
1253 manager_verify_all(m);
1254 return 0;
1255 }
1256
1257 int manager_connect_bus(Manager *m) {
1258 int r;
1259
1260 assert(m);
1261
1262 if (m->bus)
1263 return 0;
1264
1265 r = sd_bus_default_system(&m->bus);
1266 if (r < 0) {
1267 /* We failed to connect? Yuck, we must be in early
1268 * boot. Let's try in 5s again. As soon as we have
1269 * kdbus we can stop doing this... */
1270
1271 log_debug_errno(r, "Failed to connect to bus, trying again in 5s: %m");
1272
1273 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);
1274 if (r < 0)
1275 return log_error_errno(r, "Failed to install bus reconnect time event: %m");
1276
1277 return 0;
1278 }
1279
1280 r = sd_bus_add_object_vtable(m->bus, NULL, "/org/freedesktop/resolve1", "org.freedesktop.resolve1.Manager", resolve_vtable, m);
1281 if (r < 0)
1282 return log_error_errno(r, "Failed to register object: %m");
1283
1284 r = sd_bus_request_name(m->bus, "org.freedesktop.resolve1", 0);
1285 if (r < 0)
1286 return log_error_errno(r, "Failed to register name: %m");
1287
1288 r = sd_bus_attach_event(m->bus, m->event, 0);
1289 if (r < 0)
1290 return log_error_errno(r, "Failed to attach bus to event loop: %m");
1291
1292 r = sd_bus_add_match(m->bus, &m->prepare_for_sleep_slot,
1293 "type='signal',"
1294 "sender='org.freedesktop.login1',"
1295 "interface='org.freedesktop.login1.Manager',"
1296 "member='PrepareForSleep',"
1297 "path='/org/freedesktop/login1'",
1298 match_prepare_for_sleep,
1299 m);
1300 if (r < 0)
1301 log_error_errno(r, "Failed to add match for PrepareForSleep: %m");
1302
1303 return 0;
1304 }