]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/resolve/resolved-dns-query.c
resolved: rr - introduce dns_resource_key_new_redirect()
[thirdparty/systemd.git] / src / resolve / resolved-dns-query.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 "hostname-util.h"
23 #include "dns-domain.h"
24 #include "local-addresses.h"
25
26 #include "resolved-dns-query.h"
27
28 /* How long to wait for the query in total */
29 #define QUERY_TIMEOUT_USEC (30 * USEC_PER_SEC)
30
31 #define CNAME_MAX 8
32 #define QUERIES_MAX 2048
33
34 static void dns_query_stop(DnsQuery *q) {
35 DnsTransaction *t;
36
37 assert(q);
38
39 q->timeout_event_source = sd_event_source_unref(q->timeout_event_source);
40
41 while ((t = set_steal_first(q->transactions))) {
42 set_remove(t->queries, q);
43 dns_transaction_gc(t);
44 }
45 }
46
47 DnsQuery *dns_query_free(DnsQuery *q) {
48 if (!q)
49 return NULL;
50
51 dns_query_stop(q);
52 set_free(q->transactions);
53
54 dns_question_unref(q->question);
55 dns_answer_unref(q->answer);
56
57 sd_bus_message_unref(q->request);
58 sd_bus_track_unref(q->bus_track);
59
60 if (q->manager) {
61 LIST_REMOVE(queries, q->manager->dns_queries, q);
62 q->manager->n_dns_queries--;
63 }
64
65 free(q);
66
67 return NULL;
68 }
69
70 int dns_query_new(Manager *m, DnsQuery **ret, DnsQuestion *question, int ifindex, uint64_t flags) {
71 _cleanup_(dns_query_freep) DnsQuery *q = NULL;
72 unsigned i;
73 int r;
74
75 assert(m);
76 assert(question);
77
78 r = dns_question_is_valid(question);
79 if (r < 0)
80 return r;
81
82 if (m->n_dns_queries >= QUERIES_MAX)
83 return -EBUSY;
84
85 q = new0(DnsQuery, 1);
86 if (!q)
87 return -ENOMEM;
88
89 q->question = dns_question_ref(question);
90 q->ifindex = ifindex;
91 q->flags = flags;
92
93 for (i = 0; i < question->n_keys; i++) {
94 _cleanup_free_ char *p;
95
96 r = dns_resource_key_to_string(question->keys[i], &p);
97 if (r < 0)
98 return r;
99
100 log_debug("Looking up RR for %s", p);
101 }
102
103 LIST_PREPEND(queries, m->dns_queries, q);
104 m->n_dns_queries++;
105 q->manager = m;
106
107 if (ret)
108 *ret = q;
109 q = NULL;
110
111 return 0;
112 }
113
114 static void dns_query_complete(DnsQuery *q, DnsTransactionState state) {
115 assert(q);
116 assert(!IN_SET(state, DNS_TRANSACTION_NULL, DNS_TRANSACTION_PENDING));
117 assert(IN_SET(q->state, DNS_TRANSACTION_NULL, DNS_TRANSACTION_PENDING));
118
119 /* Note that this call might invalidate the query. Callers
120 * should hence not attempt to access the query or transaction
121 * after calling this function. */
122
123 q->state = state;
124
125 dns_query_stop(q);
126 if (q->complete)
127 q->complete(q);
128 }
129
130 static int on_query_timeout(sd_event_source *s, usec_t usec, void *userdata) {
131 DnsQuery *q = userdata;
132
133 assert(s);
134 assert(q);
135
136 dns_query_complete(q, DNS_TRANSACTION_TIMEOUT);
137 return 0;
138 }
139
140 static int dns_query_add_transaction(DnsQuery *q, DnsScope *s, DnsResourceKey *key) {
141 DnsTransaction *t;
142 int r;
143
144 assert(q);
145 assert(s);
146 assert(key);
147
148 r = set_ensure_allocated(&q->transactions, NULL);
149 if (r < 0)
150 return r;
151
152 t = dns_scope_find_transaction(s, key, true);
153 if (!t) {
154 r = dns_transaction_new(&t, s, key);
155 if (r < 0)
156 return r;
157 }
158
159 r = set_ensure_allocated(&t->queries, NULL);
160 if (r < 0)
161 goto gc;
162
163 r = set_put(t->queries, q);
164 if (r < 0)
165 goto gc;
166
167 r = set_put(q->transactions, t);
168 if (r < 0) {
169 set_remove(t->queries, q);
170 goto gc;
171 }
172
173 return 0;
174
175 gc:
176 dns_transaction_gc(t);
177 return r;
178 }
179
180 static int dns_query_add_transaction_split(DnsQuery *q, DnsScope *s) {
181 unsigned i;
182 int r;
183
184 assert(q);
185 assert(s);
186
187 /* Create one transaction per question key */
188
189 for (i = 0; i < q->question->n_keys; i++) {
190 r = dns_query_add_transaction(q, s, q->question->keys[i]);
191 if (r < 0)
192 return r;
193 }
194
195 return 0;
196 }
197
198 static int SYNTHESIZE_IFINDEX(int ifindex) {
199
200 /* When the caller asked for resolving on a specific
201 * interface, we synthesize the answer for that
202 * interface. However, if nothing specific was claimed and we
203 * only return localhost RRs, we synthesize the answer for
204 * localhost. */
205
206 if (ifindex > 0)
207 return ifindex;
208
209 return LOOPBACK_IFINDEX;
210 }
211
212 static int SYNTHESIZE_FAMILY(uint64_t flags) {
213
214 /* Picks an address family depending on set flags. This is
215 * purely for synthesized answers, where the family we return
216 * for the reply should match what was requested in the
217 * question, even though we are synthesizing the answer
218 * here. */
219
220 if (!(flags & SD_RESOLVED_DNS)) {
221 if (flags & SD_RESOLVED_LLMNR_IPV4)
222 return AF_INET;
223 if (flags & SD_RESOLVED_LLMNR_IPV6)
224 return AF_INET6;
225 }
226
227 return AF_UNSPEC;
228 }
229
230 static DnsProtocol SYNTHESIZE_PROTOCOL(uint64_t flags) {
231
232 /* Similar as SYNTHESIZE_FAMILY() but does this for the
233 * protocol. If resolving via DNS was requested, we claim it
234 * was DNS. Similar, if nothing specific was
235 * requested. However, if only resolving via LLMNR was
236 * requested we return that. */
237
238 if (flags & SD_RESOLVED_DNS)
239 return DNS_PROTOCOL_DNS;
240 if (flags & SD_RESOLVED_LLMNR)
241 return DNS_PROTOCOL_LLMNR;
242
243 return DNS_PROTOCOL_DNS;
244 }
245
246 static int dns_type_to_af(uint16_t t) {
247 switch (t) {
248
249 case DNS_TYPE_A:
250 return AF_INET;
251
252 case DNS_TYPE_AAAA:
253 return AF_INET6;
254
255 case DNS_TYPE_ANY:
256 return AF_UNSPEC;
257
258 default:
259 return -EINVAL;
260 }
261 }
262
263 static int synthesize_localhost_rr(DnsQuery *q, DnsResourceKey *key, DnsAnswer **answer) {
264 int r;
265
266 assert(q);
267 assert(key);
268 assert(answer);
269
270 r = dns_answer_reserve(answer, 2);
271 if (r < 0)
272 return r;
273
274 if (IN_SET(key->type, DNS_TYPE_A, DNS_TYPE_ANY)) {
275 _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
276
277 rr = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_A, DNS_RESOURCE_KEY_NAME(key));
278 if (!rr)
279 return -ENOMEM;
280
281 rr->a.in_addr.s_addr = htobe32(INADDR_LOOPBACK);
282
283 r = dns_answer_add(*answer, rr, SYNTHESIZE_IFINDEX(q->ifindex));
284 if (r < 0)
285 return r;
286 }
287
288 if (IN_SET(key->type, DNS_TYPE_AAAA, DNS_TYPE_ANY)) {
289 _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
290
291 rr = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_AAAA, DNS_RESOURCE_KEY_NAME(key));
292 if (!rr)
293 return -ENOMEM;
294
295 rr->aaaa.in6_addr = in6addr_loopback;
296
297 r = dns_answer_add(*answer, rr, SYNTHESIZE_IFINDEX(q->ifindex));
298 if (r < 0)
299 return r;
300 }
301
302 return 0;
303 }
304
305 static int answer_add_ptr(DnsAnswer **answer, const char *from, const char *to, int ifindex) {
306 _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
307
308 rr = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_PTR, from);
309 if (!rr)
310 return -ENOMEM;
311
312 rr->ptr.name = strdup(to);
313 if (!rr->ptr.name)
314 return -ENOMEM;
315
316 return dns_answer_add(*answer, rr, ifindex);
317 }
318
319 static int synthesize_localhost_ptr(DnsQuery *q, DnsResourceKey *key, DnsAnswer **answer) {
320 int r;
321
322 assert(q);
323 assert(key);
324 assert(answer);
325
326 r = dns_answer_reserve(answer, 1);
327 if (r < 0)
328 return r;
329
330 if (IN_SET(key->type, DNS_TYPE_PTR, DNS_TYPE_ANY)) {
331 r = answer_add_ptr(answer, DNS_RESOURCE_KEY_NAME(key), "localhost", SYNTHESIZE_IFINDEX(q->ifindex));
332 if (r < 0)
333 return r;
334 }
335
336 return 0;
337 }
338
339 static int answer_add_addresses_rr(
340 DnsAnswer **answer,
341 const char *name,
342 struct local_address *addresses,
343 unsigned n_addresses) {
344
345 unsigned j;
346 int r;
347
348 assert(answer);
349 assert(name);
350
351 r = dns_answer_reserve(answer, n_addresses);
352 if (r < 0)
353 return r;
354
355 for (j = 0; j < n_addresses; j++) {
356 _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
357
358 r = dns_resource_record_new_address(&rr, addresses[j].family, &addresses[j].address, name);
359 if (r < 0)
360 return r;
361
362 r = dns_answer_add(*answer, rr, addresses[j].ifindex);
363 if (r < 0)
364 return r;
365 }
366
367 return 0;
368 }
369
370 static int answer_add_addresses_ptr(
371 DnsAnswer **answer,
372 const char *name,
373 struct local_address *addresses,
374 unsigned n_addresses,
375 int af, const union in_addr_union *match) {
376
377 unsigned j;
378 int r;
379
380 assert(answer);
381 assert(name);
382
383 for (j = 0; j < n_addresses; j++) {
384 _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
385
386 if (af != AF_UNSPEC) {
387
388 if (addresses[j].family != af)
389 continue;
390
391 if (match && !in_addr_equal(af, match, &addresses[j].address))
392 continue;
393 }
394
395 r = dns_answer_reserve(answer, 1);
396 if (r < 0)
397 return r;
398
399 r = dns_resource_record_new_reverse(&rr, addresses[j].family, &addresses[j].address, name);
400 if (r < 0)
401 return r;
402
403 r = dns_answer_add(*answer, rr, addresses[j].ifindex);
404 if (r < 0)
405 return r;
406 }
407
408 return 0;
409 }
410
411 static int synthesize_system_hostname_rr(DnsQuery *q, DnsResourceKey *key, DnsAnswer **answer) {
412 _cleanup_free_ struct local_address *addresses = NULL;
413 int n = 0, af;
414
415 assert(q);
416 assert(key);
417 assert(answer);
418
419 af = dns_type_to_af(key->type);
420 if (af >= 0) {
421 n = local_addresses(q->manager->rtnl, q->ifindex, af, &addresses);
422 if (n < 0)
423 return n;
424
425 if (n == 0) {
426 struct local_address buffer[2];
427
428 /* If we have no local addresses then use ::1
429 * and 127.0.0.2 as local ones. */
430
431 if (af == AF_INET || af == AF_UNSPEC)
432 buffer[n++] = (struct local_address) {
433 .family = AF_INET,
434 .ifindex = SYNTHESIZE_IFINDEX(q->ifindex),
435 .address.in.s_addr = htobe32(0x7F000002),
436 };
437
438 if (af == AF_INET6 || af == AF_UNSPEC)
439 buffer[n++] = (struct local_address) {
440 .family = AF_INET6,
441 .ifindex = SYNTHESIZE_IFINDEX(q->ifindex),
442 .address.in6 = in6addr_loopback,
443 };
444
445 return answer_add_addresses_rr(answer, DNS_RESOURCE_KEY_NAME(key), buffer, n);
446 }
447 }
448
449 return answer_add_addresses_rr(answer, DNS_RESOURCE_KEY_NAME(key), addresses, n);
450 }
451
452 static int synthesize_system_hostname_ptr(DnsQuery *q, int af, const union in_addr_union *address, DnsAnswer **answer) {
453 _cleanup_free_ struct local_address *addresses = NULL;
454 int n, r;
455
456 assert(q);
457 assert(address);
458 assert(answer);
459
460 if (af == AF_INET && address->in.s_addr == htobe32(0x7F000002)) {
461
462 /* Always map the IPv4 address 127.0.0.2 to the local
463 * hostname, in addition to "localhost": */
464
465 r = dns_answer_reserve(answer, 3);
466 if (r < 0)
467 return r;
468
469 r = answer_add_ptr(answer, "2.0.0.127.in-addr.arpa", q->manager->llmnr_hostname, SYNTHESIZE_IFINDEX(q->ifindex));
470 if (r < 0)
471 return r;
472
473 r = answer_add_ptr(answer, "2.0.0.127.in-addr.arpa", q->manager->mdns_hostname, SYNTHESIZE_IFINDEX(q->ifindex));
474 if (r < 0)
475 return r;
476
477 r = answer_add_ptr(answer, "2.0.0.127.in-addr.arpa", "localhost", SYNTHESIZE_IFINDEX(q->ifindex));
478 if (r < 0)
479 return r;
480
481 return 0;
482 }
483
484 n = local_addresses(q->manager->rtnl, q->ifindex, af, &addresses);
485 if (n < 0)
486 return n;
487
488 r = answer_add_addresses_ptr(answer, q->manager->llmnr_hostname, addresses, n, af, address);
489 if (r < 0)
490 return r;
491
492 return answer_add_addresses_ptr(answer, q->manager->mdns_hostname, addresses, n, af, address);
493 }
494
495 static int synthesize_gateway_rr(DnsQuery *q, DnsResourceKey *key, DnsAnswer **answer) {
496 _cleanup_free_ struct local_address *addresses = NULL;
497 int n = 0, af;
498
499 assert(q);
500 assert(key);
501 assert(answer);
502
503 af = dns_type_to_af(key->type);
504 if (af >= 0) {
505 n = local_gateways(q->manager->rtnl, q->ifindex, af, &addresses);
506 if (n < 0)
507 return n;
508 }
509
510 return answer_add_addresses_rr(answer, DNS_RESOURCE_KEY_NAME(key), addresses, n);
511 }
512
513 static int synthesize_gateway_ptr(DnsQuery *q, int af, const union in_addr_union *address, DnsAnswer **answer) {
514 _cleanup_free_ struct local_address *addresses = NULL;
515 int n;
516
517 assert(q);
518 assert(address);
519 assert(answer);
520
521 n = local_gateways(q->manager->rtnl, q->ifindex, af, &addresses);
522 if (n < 0)
523 return n;
524
525 return answer_add_addresses_ptr(answer, "gateway", addresses, n, af, address);
526 }
527
528 static int dns_query_synthesize_reply(DnsQuery *q, DnsTransactionState *state) {
529 _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL;
530 unsigned i;
531 int r;
532
533 assert(q);
534 assert(state);
535
536 /* Tries to synthesize localhost RR replies where appropriate */
537
538 if (!IN_SET(*state,
539 DNS_TRANSACTION_FAILURE,
540 DNS_TRANSACTION_NO_SERVERS,
541 DNS_TRANSACTION_TIMEOUT,
542 DNS_TRANSACTION_ATTEMPTS_MAX_REACHED))
543 return 0;
544
545 for (i = 0; i < q->question->n_keys; i++) {
546 union in_addr_union address;
547 const char *name;
548 int af;
549
550 if (q->question->keys[i]->class != DNS_CLASS_IN &&
551 q->question->keys[i]->class != DNS_CLASS_ANY)
552 continue;
553
554 name = DNS_RESOURCE_KEY_NAME(q->question->keys[i]);
555
556 if (is_localhost(name)) {
557
558 r = synthesize_localhost_rr(q, q->question->keys[i], &answer);
559 if (r < 0)
560 return log_error_errno(r, "Failed to synthesize localhost RRs: %m");
561
562 } else if (manager_is_own_hostname(q->manager, name)) {
563
564 r = synthesize_system_hostname_rr(q, q->question->keys[i], &answer);
565 if (r < 0)
566 return log_error_errno(r, "Failed to synthesize system hostname RRs: %m");
567
568 } else if (is_gateway_hostname(name)) {
569
570 r = synthesize_gateway_rr(q, q->question->keys[i], &answer);
571 if (r < 0)
572 return log_error_errno(r, "Failed to synthesize gateway RRs: %m");
573
574 } else if ((dns_name_endswith(name, "127.in-addr.arpa") > 0 && dns_name_equal(name, "2.0.0.127.in-addr.arpa") == 0) ||
575 dns_name_equal(name, "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa") > 0) {
576
577 r = synthesize_localhost_ptr(q, q->question->keys[i], &answer);
578 if (r < 0)
579 return log_error_errno(r, "Failed to synthesize localhost PTR RRs: %m");
580
581 } else if (dns_name_address(name, &af, &address) > 0) {
582
583 r = synthesize_system_hostname_ptr(q, af, &address, &answer);
584 if (r < 0)
585 return log_error_errno(r, "Failed to synthesize system hostname PTR RR: %m");
586
587 r = synthesize_gateway_ptr(q, af, &address, &answer);
588 if (r < 0)
589 return log_error_errno(r, "Failed to synthesize gateway hostname PTR RR: %m");
590 }
591 }
592
593 if (!answer)
594 return 0;
595
596 dns_answer_unref(q->answer);
597 q->answer = answer;
598 answer = NULL;
599
600 q->answer_family = SYNTHESIZE_FAMILY(q->flags);
601 q->answer_protocol = SYNTHESIZE_PROTOCOL(q->flags);
602 q->answer_rcode = DNS_RCODE_SUCCESS;
603
604 *state = DNS_TRANSACTION_SUCCESS;
605
606 return 1;
607 }
608
609 int dns_query_go(DnsQuery *q) {
610 DnsScopeMatch found = DNS_SCOPE_NO;
611 DnsScope *s, *first = NULL;
612 DnsTransaction *t;
613 const char *name;
614 Iterator i;
615 int r;
616
617 assert(q);
618
619 if (q->state != DNS_TRANSACTION_NULL)
620 return 0;
621
622 assert(q->question);
623 assert(q->question->n_keys > 0);
624
625 name = DNS_RESOURCE_KEY_NAME(q->question->keys[0]);
626
627 LIST_FOREACH(scopes, s, q->manager->dns_scopes) {
628 DnsScopeMatch match;
629
630 match = dns_scope_good_domain(s, q->ifindex, q->flags, name);
631 if (match < 0)
632 return match;
633
634 if (match == DNS_SCOPE_NO)
635 continue;
636
637 found = match;
638
639 if (match == DNS_SCOPE_YES) {
640 first = s;
641 break;
642 } else {
643 assert(match == DNS_SCOPE_MAYBE);
644
645 if (!first)
646 first = s;
647 }
648 }
649
650 if (found == DNS_SCOPE_NO) {
651 DnsTransactionState state = DNS_TRANSACTION_NO_SERVERS;
652
653 dns_query_synthesize_reply(q, &state);
654 dns_query_complete(q, state);
655 return 1;
656 }
657
658 r = dns_query_add_transaction_split(q, first);
659 if (r < 0)
660 goto fail;
661
662 LIST_FOREACH(scopes, s, first->scopes_next) {
663 DnsScopeMatch match;
664
665 match = dns_scope_good_domain(s, q->ifindex, q->flags, name);
666 if (match < 0)
667 goto fail;
668
669 if (match != found)
670 continue;
671
672 r = dns_query_add_transaction_split(q, s);
673 if (r < 0)
674 goto fail;
675 }
676
677 q->answer = dns_answer_unref(q->answer);
678 q->answer_rcode = 0;
679 q->answer_family = AF_UNSPEC;
680 q->answer_protocol = _DNS_PROTOCOL_INVALID;
681
682 r = sd_event_add_time(
683 q->manager->event,
684 &q->timeout_event_source,
685 clock_boottime_or_monotonic(),
686 now(clock_boottime_or_monotonic()) + QUERY_TIMEOUT_USEC, 0,
687 on_query_timeout, q);
688 if (r < 0)
689 goto fail;
690
691 q->state = DNS_TRANSACTION_PENDING;
692 q->block_ready++;
693
694 /* Start the transactions that are not started yet */
695 SET_FOREACH(t, q->transactions, i) {
696 if (t->state != DNS_TRANSACTION_NULL)
697 continue;
698
699 r = dns_transaction_go(t);
700 if (r < 0)
701 goto fail;
702 }
703
704 q->block_ready--;
705 dns_query_ready(q);
706
707 return 1;
708
709 fail:
710 dns_query_stop(q);
711 return r;
712 }
713
714 void dns_query_ready(DnsQuery *q) {
715 DnsTransaction *t;
716 DnsTransactionState state = DNS_TRANSACTION_NO_SERVERS;
717 _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL;
718 int rcode = 0;
719 DnsScope *scope = NULL;
720 bool pending = false;
721 Iterator i;
722
723 assert(q);
724 assert(IN_SET(q->state, DNS_TRANSACTION_NULL, DNS_TRANSACTION_PENDING));
725
726 /* Note that this call might invalidate the query. Callers
727 * should hence not attempt to access the query or transaction
728 * after calling this function, unless the block_ready
729 * counter was explicitly bumped before doing so. */
730
731 if (q->block_ready > 0)
732 return;
733
734 SET_FOREACH(t, q->transactions, i) {
735
736 /* If we found a successful answer, ignore all answers from other scopes */
737 if (state == DNS_TRANSACTION_SUCCESS && t->scope != scope)
738 continue;
739
740 /* One of the transactions is still going on, let's maybe wait for it */
741 if (IN_SET(t->state, DNS_TRANSACTION_PENDING, DNS_TRANSACTION_NULL)) {
742 pending = true;
743 continue;
744 }
745
746 /* One of the transactions is successful, let's use
747 * it, and copy its data out */
748 if (t->state == DNS_TRANSACTION_SUCCESS) {
749 DnsAnswer *a;
750
751 if (t->received) {
752 rcode = DNS_PACKET_RCODE(t->received);
753 a = t->received->answer;
754 } else {
755 rcode = t->cached_rcode;
756 a = t->cached;
757 }
758
759 if (state == DNS_TRANSACTION_SUCCESS) {
760 DnsAnswer *merged;
761
762 merged = dns_answer_merge(answer, a);
763 if (!merged) {
764 dns_query_complete(q, DNS_TRANSACTION_RESOURCES);
765 return;
766 }
767
768 dns_answer_unref(answer);
769 answer = merged;
770 } else {
771 dns_answer_unref(answer);
772 answer = dns_answer_ref(a);
773 }
774
775 scope = t->scope;
776 state = DNS_TRANSACTION_SUCCESS;
777 continue;
778 }
779
780 /* One of the transactions has failed, let's see
781 * whether we find anything better, but if not, return
782 * its response data */
783 if (state != DNS_TRANSACTION_SUCCESS && t->state == DNS_TRANSACTION_FAILURE) {
784 DnsAnswer *a;
785
786 if (t->received) {
787 rcode = DNS_PACKET_RCODE(t->received);
788 a = t->received->answer;
789 } else {
790 rcode = t->cached_rcode;
791 a = t->cached;
792 }
793
794 dns_answer_unref(answer);
795 answer = dns_answer_ref(a);
796
797 scope = t->scope;
798 state = DNS_TRANSACTION_FAILURE;
799 continue;
800 }
801
802 if (state == DNS_TRANSACTION_NO_SERVERS && t->state != DNS_TRANSACTION_NO_SERVERS)
803 state = t->state;
804 }
805
806 if (pending) {
807
808 /* If so far we weren't successful, and there's
809 * something still pending, then wait for it */
810 if (state != DNS_TRANSACTION_SUCCESS)
811 return;
812
813 /* If we already were successful, then only wait for
814 * other transactions on the same scope to finish. */
815 SET_FOREACH(t, q->transactions, i) {
816 if (t->scope == scope && IN_SET(t->state, DNS_TRANSACTION_PENDING, DNS_TRANSACTION_NULL))
817 return;
818 }
819 }
820
821 if (IN_SET(state, DNS_TRANSACTION_SUCCESS, DNS_TRANSACTION_FAILURE)) {
822 q->answer = dns_answer_ref(answer);
823 q->answer_rcode = rcode;
824 q->answer_protocol = scope ? scope->protocol : _DNS_PROTOCOL_INVALID;
825 q->answer_family = scope ? scope->family : AF_UNSPEC;
826 }
827
828 /* Try to synthesize a reply if we couldn't resolve something. */
829 dns_query_synthesize_reply(q, &state);
830
831 dns_query_complete(q, state);
832 }
833
834 int dns_query_cname_redirect(DnsQuery *q, const DnsResourceRecord *cname) {
835 _cleanup_(dns_question_unrefp) DnsQuestion *nq = NULL;
836 int r;
837
838 assert(q);
839
840 if (q->n_cname_redirects > CNAME_MAX)
841 return -ELOOP;
842
843 r = dns_question_cname_redirect(q->question, cname, &nq);
844 if (r < 0)
845 return r;
846
847 dns_question_unref(q->question);
848 q->question = nq;
849 nq = NULL;
850
851 q->n_cname_redirects++;
852
853 dns_query_stop(q);
854 q->state = DNS_TRANSACTION_NULL;
855
856 return 0;
857 }
858
859 static int on_bus_track(sd_bus_track *t, void *userdata) {
860 DnsQuery *q = userdata;
861
862 assert(t);
863 assert(q);
864
865 log_debug("Client of active query vanished, aborting query.");
866 dns_query_complete(q, DNS_TRANSACTION_ABORTED);
867 return 0;
868 }
869
870 int dns_query_bus_track(DnsQuery *q, sd_bus_message *m) {
871 int r;
872
873 assert(q);
874 assert(m);
875
876 if (!q->bus_track) {
877 r = sd_bus_track_new(sd_bus_message_get_bus(m), &q->bus_track, on_bus_track, q);
878 if (r < 0)
879 return r;
880 }
881
882 r = sd_bus_track_add_sender(q->bus_track, m);
883 if (r < 0)
884 return r;
885
886 return 0;
887 }