chiark / gitweb /
42f4f23cb98ee83a612eabf35584a68db9c14243
[elogind.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 "resolved-dns-query.h"
23 #include "resolved-dns-domain.h"
24
25 #define TRANSACTION_TIMEOUT_USEC (5 * USEC_PER_SEC)
26 #define QUERY_TIMEOUT_USEC (30 * USEC_PER_SEC)
27 #define ATTEMPTS_MAX 8
28 #define CNAME_MAX 8
29 #define QUERIES_MAX 2048
30
31 static int dns_query_transaction_go(DnsQueryTransaction *t);
32
33 DnsQueryTransaction* dns_query_transaction_free(DnsQueryTransaction *t) {
34         DnsQuery *q;
35
36         if (!t)
37                 return NULL;
38
39         sd_event_source_unref(t->timeout_event_source);
40
41         dns_question_unref(t->question);
42         dns_packet_unref(t->sent);
43         dns_packet_unref(t->received);
44         dns_answer_unref(t->cached);
45
46         dns_stream_free(t->stream);
47
48         if (t->scope) {
49                 LIST_REMOVE(transactions_by_scope, t->scope->transactions, t);
50
51                 if (t->id != 0)
52                         hashmap_remove(t->scope->manager->dns_query_transactions, UINT_TO_PTR(t->id));
53         }
54
55         while ((q = set_steal_first(t->queries)))
56                 set_remove(q->transactions, t);
57
58         set_free(t->queries);
59
60         free(t);
61         return NULL;
62 }
63
64 DEFINE_TRIVIAL_CLEANUP_FUNC(DnsQueryTransaction*, dns_query_transaction_free);
65
66 static void dns_query_transaction_gc(DnsQueryTransaction *t) {
67         assert(t);
68
69         if (t->block_gc > 0)
70                 return;
71
72         if (set_isempty(t->queries))
73                 dns_query_transaction_free(t);
74 }
75
76 static int dns_query_transaction_new(DnsQueryTransaction **ret, DnsScope *s, DnsQuestion *q) {
77         _cleanup_(dns_query_transaction_freep) DnsQueryTransaction *t = NULL;
78         int r;
79
80         assert(ret);
81         assert(s);
82         assert(q);
83
84         r = hashmap_ensure_allocated(&s->manager->dns_query_transactions, NULL, NULL);
85         if (r < 0)
86                 return r;
87
88         t = new0(DnsQueryTransaction, 1);
89         if (!t)
90                 return -ENOMEM;
91
92         t->question = dns_question_ref(q);
93
94         do
95                 random_bytes(&t->id, sizeof(t->id));
96         while (t->id == 0 ||
97                hashmap_get(s->manager->dns_query_transactions, UINT_TO_PTR(t->id)));
98
99         r = hashmap_put(s->manager->dns_query_transactions, UINT_TO_PTR(t->id), t);
100         if (r < 0) {
101                 t->id = 0;
102                 return r;
103         }
104
105         LIST_PREPEND(transactions_by_scope, s->transactions, t);
106         t->scope = s;
107
108         if (ret)
109                 *ret = t;
110
111         t = NULL;
112
113         return 0;
114 }
115
116 static void dns_query_transaction_stop(DnsQueryTransaction *t) {
117         assert(t);
118
119         t->timeout_event_source = sd_event_source_unref(t->timeout_event_source);
120         t->stream = dns_stream_free(t->stream);
121 }
122
123 void dns_query_transaction_complete(DnsQueryTransaction *t, DnsQueryState state) {
124         DnsQuery *q;
125         Iterator i;
126
127         assert(t);
128         assert(!IN_SET(state, DNS_QUERY_NULL, DNS_QUERY_PENDING));
129         assert(IN_SET(t->state, DNS_QUERY_NULL, DNS_QUERY_PENDING));
130
131         /* Note that this call might invalidate the query. Callers
132          * should hence not attempt to access the query or transaction
133          * after calling this function. */
134
135         t->state = state;
136
137         dns_query_transaction_stop(t);
138
139         /* Notify all queries that are interested, but make sure the
140          * transaction isn't freed while we are still looking at it */
141         t->block_gc++;
142         SET_FOREACH(q, t->queries, i)
143                 dns_query_ready(q);
144         t->block_gc--;
145
146         dns_query_transaction_gc(t);
147 }
148
149 static int on_stream_complete(DnsStream *s, int error) {
150         _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
151         DnsQueryTransaction *t;
152
153         assert(s);
154         assert(s->transaction);
155
156         /* Copy the data we care about out of the stream before we
157          * destroy it. */
158         t = s->transaction;
159         p = dns_packet_ref(s->read_packet);
160
161         t->stream = dns_stream_free(t->stream);
162
163         if (error != 0) {
164                 dns_query_transaction_complete(t, DNS_QUERY_RESOURCES);
165                 return 0;
166         }
167
168         t->block_gc++;
169         dns_query_transaction_process_reply(t, p);
170         t->block_gc--;
171
172         /* If the response wasn't useful, then complete the transition now */
173         if (t->state == DNS_QUERY_PENDING)
174                 dns_query_transaction_complete(t, DNS_QUERY_INVALID_REPLY);
175
176         return 0;
177 }
178
179 static int dns_query_transaction_open_tcp(DnsQueryTransaction *t) {
180         _cleanup_close_ int fd = -1;
181         int r;
182
183         assert(t);
184
185         if (t->stream)
186                 return 0;
187
188         if (t->scope->protocol == DNS_PROTOCOL_DNS)
189                 fd = dns_scope_tcp_socket(t->scope, AF_UNSPEC, NULL, 53);
190         else if (t->scope->protocol == DNS_PROTOCOL_LLMNR) {
191
192                 /* When we already received a query to this (but it was truncated), send to its sender address */
193                 if (t->received)
194                         fd = dns_scope_tcp_socket(t->scope, t->received->family, &t->received->sender, t->received->sender_port);
195                 else {
196                         union in_addr_union address;
197                         int family;
198
199                         /* Otherwise, try to talk to the owner of a
200                          * the IP address, in case this is a reverse
201                          * PTR lookup */
202                         r = dns_question_extract_reverse_address(t->question, &family, &address);
203                         if (r < 0)
204                                 return r;
205                         if (r == 0)
206                                 return -EINVAL;
207
208                         fd = dns_scope_tcp_socket(t->scope, family, &address, 5355);
209                 }
210         } else
211                 return -EAFNOSUPPORT;
212
213         if (fd < 0)
214                 return fd;
215
216         r = dns_stream_new(t->scope->manager, &t->stream, t->scope->protocol, fd);
217         if (r < 0)
218                 return r;
219
220         fd = -1;
221
222         r = dns_stream_write_packet(t->stream, t->sent);
223         if (r < 0) {
224                 t->stream = dns_stream_free(t->stream);
225                 return r;
226         }
227
228         t->received = dns_packet_unref(t->received);
229         t->stream->complete = on_stream_complete;
230         t->stream->transaction = t;
231
232         /* The interface index is difficult to determine if we are
233          * connecting to the local host, hence fill this in right away
234          * instead of determining it from the socket */
235         if (t->scope->link)
236                 t->stream->ifindex = t->scope->link->ifindex;
237
238         return 0;
239 }
240
241 void dns_query_transaction_process_reply(DnsQueryTransaction *t, DnsPacket *p) {
242         int r;
243
244         assert(t);
245         assert(p);
246         assert(t->state == DNS_QUERY_PENDING);
247
248         /* Note that this call might invalidate the query. Callers
249          * should hence not attempt to access the query or transaction
250          * after calling this function. */
251
252         if (t->scope->protocol == DNS_PROTOCOL_LLMNR) {
253                 assert(t->scope->link);
254
255                 /* For LLMNR we will not accept any packets from other
256                  * interfaces */
257
258                 if (p->ifindex != t->scope->link->ifindex)
259                         return;
260
261                 if (p->family != t->scope->family)
262                         return;
263
264                 if (p->ipproto == IPPROTO_UDP) {
265                         if (p->family == AF_INET && !in_addr_equal(AF_INET, &p->destination, (union in_addr_union*) &LLMNR_MULTICAST_IPV4_ADDRESS))
266                                 return;
267
268                         if (p->family == AF_INET6 && !in_addr_equal(AF_INET6, &p->destination, (union in_addr_union*) &LLMNR_MULTICAST_IPV6_ADDRESS))
269                                 return;
270                 }
271         }
272
273         if (t->scope->protocol == DNS_PROTOCOL_DNS) {
274
275                 /* For DNS we are fine with accepting packets on any
276                  * interface, but the source IP address must be one of
277                  * a valid DNS server */
278
279                 if (!dns_scope_good_dns_server(t->scope, p->family, &p->sender))
280                         return;
281
282                 if (p->sender_port != 53)
283                         return;
284         }
285
286         if (t->received != p) {
287                 dns_packet_unref(t->received);
288                 t->received = dns_packet_ref(p);
289         }
290
291         if (p->ipproto == IPPROTO_TCP) {
292                 if (DNS_PACKET_TC(p)) {
293                         /* Truncated via TCP? Somebody must be fucking with us */
294                         dns_query_transaction_complete(t, DNS_QUERY_INVALID_REPLY);
295                         return;
296                 }
297
298                 if (DNS_PACKET_ID(p) != t->id) {
299                         /* Not the reply to our query? Somebody must be fucking with us */
300                         dns_query_transaction_complete(t, DNS_QUERY_INVALID_REPLY);
301                         return;
302                 }
303         }
304
305         if (DNS_PACKET_TC(p)) {
306                 /* Response was truncated, let's try again with good old TCP */
307                 r = dns_query_transaction_open_tcp(t);
308                 if (r == -ESRCH) {
309                         /* No servers found? Damn! */
310                         dns_query_transaction_complete(t, DNS_QUERY_NO_SERVERS);
311                         return;
312                 }
313                 if (r < 0) {
314                         /* On LLMNR, if we cannot connect to the host,
315                          * we immediately give up */
316                         if (t->scope->protocol == DNS_PROTOCOL_LLMNR) {
317                                 dns_query_transaction_complete(t, DNS_QUERY_RESOURCES);
318                                 return;
319                         }
320
321                         /* On DNS, couldn't send? Try immediately again, with a new server */
322                         dns_scope_next_dns_server(t->scope);
323
324                         r = dns_query_transaction_go(t);
325                         if (r < 0) {
326                                 dns_query_transaction_complete(t, DNS_QUERY_RESOURCES);
327                                 return;
328                         }
329
330                         return;
331                 }
332         }
333
334         /* Parse and update the cache */
335         r = dns_packet_extract(p);
336         if (r < 0) {
337                 dns_query_transaction_complete(t, DNS_QUERY_INVALID_REPLY);
338                 return;
339         }
340
341         dns_cache_put(&t->scope->cache, p->question, DNS_PACKET_RCODE(p), p->answer, 0);
342
343         if (DNS_PACKET_RCODE(p) == DNS_RCODE_SUCCESS)
344                 dns_query_transaction_complete(t, DNS_QUERY_SUCCESS);
345         else
346                 dns_query_transaction_complete(t, DNS_QUERY_FAILURE);
347 }
348
349 static int on_transaction_timeout(sd_event_source *s, usec_t usec, void *userdata) {
350         DnsQueryTransaction *t = userdata;
351         int r;
352
353         assert(s);
354         assert(t);
355
356         /* Timeout reached? Try again, with a new server */
357         dns_scope_next_dns_server(t->scope);
358
359         r = dns_query_transaction_go(t);
360         if (r < 0)
361                 dns_query_transaction_complete(t, DNS_QUERY_RESOURCES);
362
363         return 0;
364 }
365
366 static int dns_query_make_packet(DnsQueryTransaction *t) {
367         _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
368         unsigned n, added = 0;
369         int r;
370
371         assert(t);
372
373         if (t->sent)
374                 return 0;
375
376         r = dns_packet_new_query(&p, t->scope->protocol, 0);
377         if (r < 0)
378                 return r;
379
380         for (n = 0; n < t->question->n_keys; n++) {
381                 r = dns_scope_good_key(t->scope, t->question->keys[n]);
382                 if (r < 0)
383                         return r;
384                 if (r == 0)
385                         continue;
386
387                 r = dns_packet_append_key(p, t->question->keys[n], NULL);
388                 if (r < 0)
389                         return r;
390
391                 added++;
392         }
393
394         if (added <= 0)
395                 return -EDOM;
396
397         DNS_PACKET_HEADER(p)->qdcount = htobe16(added);
398         DNS_PACKET_HEADER(p)->id = t->id;
399
400         t->sent = p;
401         p = NULL;
402
403         return 0;
404 }
405
406 static int dns_query_transaction_go(DnsQueryTransaction *t) {
407         int r;
408
409         assert(t);
410
411         dns_query_transaction_stop(t);
412
413         if (t->n_attempts >= ATTEMPTS_MAX) {
414                 dns_query_transaction_complete(t, DNS_QUERY_ATTEMPTS_MAX);
415                 return 0;
416         }
417
418         t->n_attempts++;
419         t->received = dns_packet_unref(t->received);
420         t->cached = dns_answer_unref(t->cached);
421         t->cached_rcode = 0;
422
423         /* First, let's try the cache */
424         dns_cache_prune(&t->scope->cache);
425         r = dns_cache_lookup(&t->scope->cache, t->question, &t->cached_rcode, &t->cached);
426         if (r < 0)
427                 return r;
428         if (r > 0) {
429                 if (t->cached_rcode == DNS_RCODE_SUCCESS)
430                         dns_query_transaction_complete(t, DNS_QUERY_SUCCESS);
431                 else
432                         dns_query_transaction_complete(t, DNS_QUERY_FAILURE);
433                 return 0;
434         }
435
436         /* Otherwise, we need to ask the network */
437         r = dns_query_make_packet(t);
438         if (r == -EDOM) {
439                 /* Not the right request to make on this network?
440                  * (i.e. an A request made on IPv6 or an AAAA request
441                  * made on IPv4, on LLMNR or mDNS.) */
442                 dns_query_transaction_complete(t, DNS_QUERY_NO_SERVERS);
443                 return 0;
444         }
445         if (r < 0)
446                 return r;
447
448         if (t->scope->protocol == DNS_PROTOCOL_LLMNR &&
449             (dns_question_endswith(t->question, "in-addr.arpa") > 0 ||
450              dns_question_endswith(t->question, "ip6.arpa") > 0)) {
451
452                 /* RFC 4795, Section 2.4. says reverse lookups shall
453                  * always be made via TCP on LLMNR */
454                 r = dns_query_transaction_open_tcp(t);
455         } else {
456                 /* Try via UDP, and if that fails due to large size try via TCP */
457                 r = dns_scope_send(t->scope, t->sent);
458                 if (r == -EMSGSIZE)
459                         r = dns_query_transaction_open_tcp(t);
460         }
461         if (r == -ESRCH) {
462                 /* No servers to send this to? */
463                 dns_query_transaction_complete(t, DNS_QUERY_NO_SERVERS);
464                 return 0;
465         }
466         if (r < 0) {
467                 /* Couldn't send? Try immediately again, with a new server */
468                 dns_scope_next_dns_server(t->scope);
469
470                 return dns_query_transaction_go(t);
471         }
472
473         r = sd_event_add_time(t->scope->manager->event, &t->timeout_event_source, CLOCK_MONOTONIC, now(CLOCK_MONOTONIC) + TRANSACTION_TIMEOUT_USEC, 0, on_transaction_timeout, t);
474         if (r < 0)
475                 return r;
476
477         t->state = DNS_QUERY_PENDING;
478         return 1;
479 }
480
481 DnsQuery *dns_query_free(DnsQuery *q) {
482         DnsQueryTransaction *t;
483
484         if (!q)
485                 return NULL;
486
487         sd_bus_message_unref(q->request);
488
489         dns_question_unref(q->question);
490         dns_answer_unref(q->answer);
491
492         sd_event_source_unref(q->timeout_event_source);
493
494         while ((t = set_steal_first(q->transactions))) {
495                 set_remove(t->queries, q);
496                 dns_query_transaction_gc(t);
497         }
498
499         set_free(q->transactions);
500
501         if (q->manager) {
502                 LIST_REMOVE(queries, q->manager->dns_queries, q);
503                 q->manager->n_dns_queries--;
504         }
505
506         free(q);
507
508         return NULL;
509 }
510
511 int dns_query_new(Manager *m, DnsQuery **ret, DnsQuestion *question) {
512         _cleanup_(dns_query_freep) DnsQuery *q = NULL;
513         unsigned i;
514         int r;
515
516         assert(m);
517         assert(question);
518
519         r = dns_question_is_valid(question);
520         if (r < 0)
521                 return r;
522
523         if (m->n_dns_queries >= QUERIES_MAX)
524                 return -EBUSY;
525
526         q = new0(DnsQuery, 1);
527         if (!q)
528                 return -ENOMEM;
529
530         q->question = dns_question_ref(question);
531
532         for (i = 0; i < question->n_keys; i++) {
533                 log_debug("Looking up RR for %s %s %s",
534                           strna(dns_class_to_string(question->keys[i]->class)),
535                           strna(dns_type_to_string(question->keys[i]->type)),
536                           DNS_RESOURCE_KEY_NAME(question->keys[i]));
537         }
538
539         LIST_PREPEND(queries, m->dns_queries, q);
540         m->n_dns_queries++;
541         q->manager = m;
542
543         if (ret)
544                 *ret = q;
545         q = NULL;
546
547         return 0;
548 }
549
550 static void dns_query_stop(DnsQuery *q) {
551         DnsQueryTransaction *t;
552
553         assert(q);
554
555         q->timeout_event_source = sd_event_source_unref(q->timeout_event_source);
556
557         while ((t = set_steal_first(q->transactions))) {
558                 set_remove(t->queries, q);
559                 dns_query_transaction_gc(t);
560         }
561 }
562
563 static void dns_query_complete(DnsQuery *q, DnsQueryState state) {
564         assert(q);
565         assert(!IN_SET(state, DNS_QUERY_NULL, DNS_QUERY_PENDING));
566         assert(IN_SET(q->state, DNS_QUERY_NULL, DNS_QUERY_PENDING));
567
568         /* Note that this call might invalidate the query. Callers
569          * should hence not attempt to access the query or transaction
570          * after calling this function. */
571
572         q->state = state;
573
574         dns_query_stop(q);
575         if (q->complete)
576                 q->complete(q);
577 }
578
579 static int on_query_timeout(sd_event_source *s, usec_t usec, void *userdata) {
580         DnsQuery *q = userdata;
581
582         assert(s);
583         assert(q);
584
585         dns_query_complete(q, DNS_QUERY_TIMEOUT);
586         return 0;
587 }
588
589 static int dns_query_add_transaction(DnsQuery *q, DnsScope *s, DnsResourceKey *key) {
590         _cleanup_(dns_question_unrefp) DnsQuestion *question = NULL;
591         DnsQueryTransaction *t;
592         int r;
593
594         assert(q);
595
596         r = set_ensure_allocated(&q->transactions, NULL, NULL);
597         if (r < 0)
598                 return r;
599
600         if (key) {
601                 question = dns_question_new(1);
602                 if (!question)
603                         return -ENOMEM;
604
605                 r = dns_question_add(question, key);
606                 if (r < 0)
607                         return r;
608         } else
609                 question = dns_question_ref(q->question);
610
611         LIST_FOREACH(transactions_by_scope, t, s->transactions)
612                 if (dns_question_is_superset(t->question, question))
613                         break;
614
615         if (!t) {
616                 r = dns_query_transaction_new(&t, s, question);
617                 if (r < 0)
618                         return r;
619         }
620
621         r = set_ensure_allocated(&t->queries, NULL, NULL);
622         if (r < 0)
623                 goto fail;
624
625         r = set_put(t->queries, q);
626         if (r < 0)
627                 goto fail;
628
629         r = set_put(q->transactions, t);
630         if (r < 0) {
631                 set_remove(t->queries, q);
632                 goto fail;
633         }
634
635         return 0;
636
637 fail:
638         dns_query_transaction_gc(t);
639         return r;
640 }
641
642 static int dns_query_add_transaction_split(DnsQuery *q, DnsScope *s) {
643         int r;
644
645         assert(q);
646         assert(s);
647
648         if (s->protocol == DNS_PROTOCOL_MDNS) {
649                 r = dns_query_add_transaction(q, s, NULL);
650                 if (r < 0)
651                         return r;
652         } else {
653                 unsigned i;
654
655                 /* On DNS and LLMNR we can only send a single
656                  * question per datagram, hence issue multiple
657                  * transactions. */
658
659                 for (i = 0; i < q->question->n_keys; i++) {
660                         r = dns_query_add_transaction(q, s, q->question->keys[i]);
661                         if (r < 0)
662                                 return r;
663                 }
664         }
665
666         return 0;
667 }
668
669 int dns_query_go(DnsQuery *q) {
670         DnsScopeMatch found = DNS_SCOPE_NO;
671         DnsScope *s, *first = NULL;
672         DnsQueryTransaction *t;
673         const char *name;
674         Iterator i;
675         int r;
676
677         assert(q);
678
679         if (q->state != DNS_QUERY_NULL)
680                 return 0;
681
682         assert(q->question);
683         assert(q->question->n_keys > 0);
684
685         name = DNS_RESOURCE_KEY_NAME(q->question->keys[0]);
686
687         LIST_FOREACH(scopes, s, q->manager->dns_scopes) {
688                 DnsScopeMatch match;
689
690                 match = dns_scope_good_domain(s, name);
691                 if (match < 0)
692                         return match;
693
694                 if (match == DNS_SCOPE_NO)
695                         continue;
696
697                 found = match;
698
699                 if (match == DNS_SCOPE_YES) {
700                         first = s;
701                         break;
702                 } else {
703                         assert(match == DNS_SCOPE_MAYBE);
704
705                         if (!first)
706                                 first = s;
707                 }
708         }
709
710         if (found == DNS_SCOPE_NO)
711                 return -ESRCH;
712
713         r = dns_query_add_transaction_split(q, first);
714         if (r < 0)
715                 return r;
716
717         LIST_FOREACH(scopes, s, first->scopes_next) {
718                 DnsScopeMatch match;
719
720                 match = dns_scope_good_domain(s, name);
721                 if (match < 0)
722                         return match;
723
724                 if (match != found)
725                         continue;
726
727                 r = dns_query_add_transaction_split(q, s);
728                 if (r < 0)
729                         return r;
730         }
731
732         q->answer = dns_answer_unref(q->answer);
733         q->answer_ifindex = 0;
734         q->answer_rcode = 0;
735
736         r = sd_event_add_time(q->manager->event, &q->timeout_event_source, CLOCK_MONOTONIC, now(CLOCK_MONOTONIC) + QUERY_TIMEOUT_USEC, 0, on_query_timeout, q);
737         if (r < 0)
738                 goto fail;
739
740         q->state = DNS_QUERY_PENDING;
741         q->block_ready++;
742
743         SET_FOREACH(t, q->transactions, i) {
744                 if (t->state == DNS_QUERY_NULL) {
745                         r = dns_query_transaction_go(t);
746                         if (r < 0)
747                                 goto fail;
748                 }
749         }
750
751         q->block_ready--;
752         dns_query_ready(q);
753
754         return 1;
755
756 fail:
757         dns_query_stop(q);
758         return r;
759 }
760
761 void dns_query_ready(DnsQuery *q) {
762         DnsQueryTransaction *t;
763         DnsQueryState state = DNS_QUERY_NO_SERVERS;
764         _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL;
765         int rcode = 0;
766         DnsScope *scope = NULL;
767         Iterator i;
768
769         assert(q);
770         assert(IN_SET(q->state, DNS_QUERY_NULL, DNS_QUERY_PENDING));
771
772         /* Note that this call might invalidate the query. Callers
773          * should hence not attempt to access the query or transaction
774          * after calling this function, unless the block_ready
775          * counter was explicitly bumped before doing so. */
776
777         if (q->block_ready > 0)
778                 return;
779
780         SET_FOREACH(t, q->transactions, i) {
781
782                 /* If we found a successful answer, ignore all answers from other scopes */
783                 if (state == DNS_QUERY_SUCCESS && t->scope != scope)
784                         continue;
785
786                 /* One of the transactions is still going on, let's wait for it */
787                 if (t->state == DNS_QUERY_PENDING || t->state == DNS_QUERY_NULL)
788                         return;
789
790                 /* One of the transactions is successful, let's use
791                  * it, and copy its data out */
792                 if (t->state == DNS_QUERY_SUCCESS) {
793                         DnsAnswer *a;
794
795                         if (t->received) {
796                                 rcode = DNS_PACKET_RCODE(t->received);
797                                 a = t->received->answer;
798                         } else {
799                                 rcode = t->cached_rcode;
800                                 a = t->cached;
801                         }
802
803                         if (state == DNS_QUERY_SUCCESS) {
804                                 DnsAnswer *merged;
805
806                                 merged = dns_answer_merge(answer, a);
807                                 if (!merged) {
808                                         dns_query_complete(q, DNS_QUERY_RESOURCES);
809                                         return;
810                                 }
811
812                                 dns_answer_unref(answer);
813                                 answer = merged;
814                         } else {
815                                 dns_answer_unref(answer);
816                                 answer = dns_answer_ref(a);
817                         }
818
819                         scope = t->scope;
820                         state = DNS_QUERY_SUCCESS;
821                         continue;
822                 }
823
824                 /* One of the transactions has failed, let's see
825                  * whether we find anything better, but if not, return
826                  * its response data */
827                 if (state != DNS_QUERY_SUCCESS && t->state == DNS_QUERY_FAILURE) {
828                         DnsAnswer *a;
829
830                         if (t->received) {
831                                 rcode = DNS_PACKET_RCODE(t->received);
832                                 a = t->received->answer;
833                         } else {
834                                 rcode = t->cached_rcode;
835                                 a = t->cached;
836                         }
837
838                         dns_answer_unref(answer);
839                         answer = dns_answer_ref(a);
840
841                         scope = t->scope;
842                         state = DNS_QUERY_FAILURE;
843                         continue;
844                 }
845
846                 if (state == DNS_QUERY_NO_SERVERS && t->state != DNS_QUERY_NO_SERVERS)
847                         state = t->state;
848         }
849
850         if (IN_SET(state, DNS_QUERY_SUCCESS, DNS_QUERY_FAILURE)) {
851                 q->answer = dns_answer_ref(answer);
852                 q->answer_rcode = rcode;
853                 q->answer_ifindex = (scope && scope->link) ? scope->link->ifindex : 0;
854         }
855
856         dns_query_complete(q, state);
857 }
858
859 int dns_query_cname_redirect(DnsQuery *q, const char *name) {
860         _cleanup_(dns_question_unrefp) DnsQuestion *nq = NULL;
861         int r;
862
863         assert(q);
864
865         if (q->n_cname_redirects > CNAME_MAX)
866                 return -ELOOP;
867
868         r = dns_question_cname_redirect(q->question, name, &nq);
869         if (r < 0)
870                 return r;
871
872         dns_question_unref(q->question);
873         q->question = nq;
874         nq = NULL;
875
876         q->n_cname_redirects++;
877
878         dns_query_stop(q);
879         q->state = DNS_QUERY_NULL;
880
881         return 0;
882 }