chiark / gitweb /
resolved: discard more invalid llmnr messages
[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                 /* Don't accept UDP packets directed to anything but
265                  * the LLMNR multicast addresses. */
266
267                 if (p->ipproto == IPPROTO_UDP) {
268                         if (p->family == AF_INET && !in_addr_equal(AF_INET, &p->destination, (union in_addr_union*) &LLMNR_MULTICAST_IPV4_ADDRESS))
269                                 return;
270
271                         if (p->family == AF_INET6 && !in_addr_equal(AF_INET6, &p->destination, (union in_addr_union*) &LLMNR_MULTICAST_IPV6_ADDRESS))
272                                 return;
273                 }
274
275                 /* Tentative replies shall be discarded, see RFC 4795,
276                  * 2.1.1 */
277
278                 if (DNS_PACKET_T(p))
279                         return;
280         }
281
282         if (t->scope->protocol == DNS_PROTOCOL_DNS) {
283
284                 /* For DNS we are fine with accepting packets on any
285                  * interface, but the source IP address must be one of
286                  * a valid DNS server */
287
288                 if (!dns_scope_good_dns_server(t->scope, p->family, &p->sender))
289                         return;
290
291                 if (p->sender_port != 53)
292                         return;
293         }
294
295         if (t->received != p) {
296                 dns_packet_unref(t->received);
297                 t->received = dns_packet_ref(p);
298         }
299
300         if (p->ipproto == IPPROTO_TCP) {
301                 if (DNS_PACKET_TC(p)) {
302                         /* Truncated via TCP? Somebody must be fucking with us */
303                         dns_query_transaction_complete(t, DNS_QUERY_INVALID_REPLY);
304                         return;
305                 }
306
307                 if (DNS_PACKET_ID(p) != t->id) {
308                         /* Not the reply to our query? Somebody must be fucking with us */
309                         dns_query_transaction_complete(t, DNS_QUERY_INVALID_REPLY);
310                         return;
311                 }
312         }
313
314         if (DNS_PACKET_TC(p)) {
315                 /* Response was truncated, let's try again with good old TCP */
316                 r = dns_query_transaction_open_tcp(t);
317                 if (r == -ESRCH) {
318                         /* No servers found? Damn! */
319                         dns_query_transaction_complete(t, DNS_QUERY_NO_SERVERS);
320                         return;
321                 }
322                 if (r < 0) {
323                         /* On LLMNR, if we cannot connect to the host,
324                          * we immediately give up */
325                         if (t->scope->protocol == DNS_PROTOCOL_LLMNR) {
326                                 dns_query_transaction_complete(t, DNS_QUERY_RESOURCES);
327                                 return;
328                         }
329
330                         /* On DNS, couldn't send? Try immediately again, with a new server */
331                         dns_scope_next_dns_server(t->scope);
332
333                         r = dns_query_transaction_go(t);
334                         if (r < 0) {
335                                 dns_query_transaction_complete(t, DNS_QUERY_RESOURCES);
336                                 return;
337                         }
338
339                         return;
340                 }
341         }
342
343         /* Parse and update the cache */
344         r = dns_packet_extract(p);
345         if (r < 0) {
346                 dns_query_transaction_complete(t, DNS_QUERY_INVALID_REPLY);
347                 return;
348         }
349
350         dns_cache_put(&t->scope->cache, p->question, DNS_PACKET_RCODE(p), p->answer, 0);
351
352         if (DNS_PACKET_RCODE(p) == DNS_RCODE_SUCCESS)
353                 dns_query_transaction_complete(t, DNS_QUERY_SUCCESS);
354         else
355                 dns_query_transaction_complete(t, DNS_QUERY_FAILURE);
356 }
357
358 static int on_transaction_timeout(sd_event_source *s, usec_t usec, void *userdata) {
359         DnsQueryTransaction *t = userdata;
360         int r;
361
362         assert(s);
363         assert(t);
364
365         /* Timeout reached? Try again, with a new server */
366         dns_scope_next_dns_server(t->scope);
367
368         r = dns_query_transaction_go(t);
369         if (r < 0)
370                 dns_query_transaction_complete(t, DNS_QUERY_RESOURCES);
371
372         return 0;
373 }
374
375 static int dns_query_make_packet(DnsQueryTransaction *t) {
376         _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
377         unsigned n, added = 0;
378         int r;
379
380         assert(t);
381
382         if (t->sent)
383                 return 0;
384
385         r = dns_packet_new_query(&p, t->scope->protocol, 0);
386         if (r < 0)
387                 return r;
388
389         for (n = 0; n < t->question->n_keys; n++) {
390                 r = dns_scope_good_key(t->scope, t->question->keys[n]);
391                 if (r < 0)
392                         return r;
393                 if (r == 0)
394                         continue;
395
396                 r = dns_packet_append_key(p, t->question->keys[n], NULL);
397                 if (r < 0)
398                         return r;
399
400                 added++;
401         }
402
403         if (added <= 0)
404                 return -EDOM;
405
406         DNS_PACKET_HEADER(p)->qdcount = htobe16(added);
407         DNS_PACKET_HEADER(p)->id = t->id;
408
409         t->sent = p;
410         p = NULL;
411
412         return 0;
413 }
414
415 static int dns_query_transaction_go(DnsQueryTransaction *t) {
416         int r;
417
418         assert(t);
419
420         dns_query_transaction_stop(t);
421
422         if (t->n_attempts >= ATTEMPTS_MAX) {
423                 dns_query_transaction_complete(t, DNS_QUERY_ATTEMPTS_MAX);
424                 return 0;
425         }
426
427         t->n_attempts++;
428         t->received = dns_packet_unref(t->received);
429         t->cached = dns_answer_unref(t->cached);
430         t->cached_rcode = 0;
431
432         /* First, let's try the cache */
433         dns_cache_prune(&t->scope->cache);
434         r = dns_cache_lookup(&t->scope->cache, t->question, &t->cached_rcode, &t->cached);
435         if (r < 0)
436                 return r;
437         if (r > 0) {
438                 if (t->cached_rcode == DNS_RCODE_SUCCESS)
439                         dns_query_transaction_complete(t, DNS_QUERY_SUCCESS);
440                 else
441                         dns_query_transaction_complete(t, DNS_QUERY_FAILURE);
442                 return 0;
443         }
444
445         /* Otherwise, we need to ask the network */
446         r = dns_query_make_packet(t);
447         if (r == -EDOM) {
448                 /* Not the right request to make on this network?
449                  * (i.e. an A request made on IPv6 or an AAAA request
450                  * made on IPv4, on LLMNR or mDNS.) */
451                 dns_query_transaction_complete(t, DNS_QUERY_NO_SERVERS);
452                 return 0;
453         }
454         if (r < 0)
455                 return r;
456
457         if (t->scope->protocol == DNS_PROTOCOL_LLMNR &&
458             (dns_question_endswith(t->question, "in-addr.arpa") > 0 ||
459              dns_question_endswith(t->question, "ip6.arpa") > 0)) {
460
461                 /* RFC 4795, Section 2.4. says reverse lookups shall
462                  * always be made via TCP on LLMNR */
463                 r = dns_query_transaction_open_tcp(t);
464         } else {
465                 /* Try via UDP, and if that fails due to large size try via TCP */
466                 r = dns_scope_send(t->scope, t->sent);
467                 if (r == -EMSGSIZE)
468                         r = dns_query_transaction_open_tcp(t);
469         }
470         if (r == -ESRCH) {
471                 /* No servers to send this to? */
472                 dns_query_transaction_complete(t, DNS_QUERY_NO_SERVERS);
473                 return 0;
474         }
475         if (r < 0) {
476                 /* Couldn't send? Try immediately again, with a new server */
477                 dns_scope_next_dns_server(t->scope);
478
479                 return dns_query_transaction_go(t);
480         }
481
482         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);
483         if (r < 0)
484                 return r;
485
486         t->state = DNS_QUERY_PENDING;
487         return 1;
488 }
489
490 DnsQuery *dns_query_free(DnsQuery *q) {
491         DnsQueryTransaction *t;
492
493         if (!q)
494                 return NULL;
495
496         sd_bus_message_unref(q->request);
497
498         dns_question_unref(q->question);
499         dns_answer_unref(q->answer);
500
501         sd_event_source_unref(q->timeout_event_source);
502
503         while ((t = set_steal_first(q->transactions))) {
504                 set_remove(t->queries, q);
505                 dns_query_transaction_gc(t);
506         }
507
508         set_free(q->transactions);
509
510         if (q->manager) {
511                 LIST_REMOVE(queries, q->manager->dns_queries, q);
512                 q->manager->n_dns_queries--;
513         }
514
515         free(q);
516
517         return NULL;
518 }
519
520 int dns_query_new(Manager *m, DnsQuery **ret, DnsQuestion *question) {
521         _cleanup_(dns_query_freep) DnsQuery *q = NULL;
522         unsigned i;
523         int r;
524
525         assert(m);
526         assert(question);
527
528         r = dns_question_is_valid(question);
529         if (r < 0)
530                 return r;
531
532         if (m->n_dns_queries >= QUERIES_MAX)
533                 return -EBUSY;
534
535         q = new0(DnsQuery, 1);
536         if (!q)
537                 return -ENOMEM;
538
539         q->question = dns_question_ref(question);
540
541         for (i = 0; i < question->n_keys; i++) {
542                 log_debug("Looking up RR for %s %s %s",
543                           strna(dns_class_to_string(question->keys[i]->class)),
544                           strna(dns_type_to_string(question->keys[i]->type)),
545                           DNS_RESOURCE_KEY_NAME(question->keys[i]));
546         }
547
548         LIST_PREPEND(queries, m->dns_queries, q);
549         m->n_dns_queries++;
550         q->manager = m;
551
552         if (ret)
553                 *ret = q;
554         q = NULL;
555
556         return 0;
557 }
558
559 static void dns_query_stop(DnsQuery *q) {
560         DnsQueryTransaction *t;
561
562         assert(q);
563
564         q->timeout_event_source = sd_event_source_unref(q->timeout_event_source);
565
566         while ((t = set_steal_first(q->transactions))) {
567                 set_remove(t->queries, q);
568                 dns_query_transaction_gc(t);
569         }
570 }
571
572 static void dns_query_complete(DnsQuery *q, DnsQueryState state) {
573         assert(q);
574         assert(!IN_SET(state, DNS_QUERY_NULL, DNS_QUERY_PENDING));
575         assert(IN_SET(q->state, DNS_QUERY_NULL, DNS_QUERY_PENDING));
576
577         /* Note that this call might invalidate the query. Callers
578          * should hence not attempt to access the query or transaction
579          * after calling this function. */
580
581         q->state = state;
582
583         dns_query_stop(q);
584         if (q->complete)
585                 q->complete(q);
586 }
587
588 static int on_query_timeout(sd_event_source *s, usec_t usec, void *userdata) {
589         DnsQuery *q = userdata;
590
591         assert(s);
592         assert(q);
593
594         dns_query_complete(q, DNS_QUERY_TIMEOUT);
595         return 0;
596 }
597
598 static int dns_query_add_transaction(DnsQuery *q, DnsScope *s, DnsResourceKey *key) {
599         _cleanup_(dns_question_unrefp) DnsQuestion *question = NULL;
600         DnsQueryTransaction *t;
601         int r;
602
603         assert(q);
604
605         r = set_ensure_allocated(&q->transactions, NULL, NULL);
606         if (r < 0)
607                 return r;
608
609         if (key) {
610                 question = dns_question_new(1);
611                 if (!question)
612                         return -ENOMEM;
613
614                 r = dns_question_add(question, key);
615                 if (r < 0)
616                         return r;
617         } else
618                 question = dns_question_ref(q->question);
619
620         LIST_FOREACH(transactions_by_scope, t, s->transactions)
621                 if (dns_question_is_superset(t->question, question))
622                         break;
623
624         if (!t) {
625                 r = dns_query_transaction_new(&t, s, question);
626                 if (r < 0)
627                         return r;
628         }
629
630         r = set_ensure_allocated(&t->queries, NULL, NULL);
631         if (r < 0)
632                 goto fail;
633
634         r = set_put(t->queries, q);
635         if (r < 0)
636                 goto fail;
637
638         r = set_put(q->transactions, t);
639         if (r < 0) {
640                 set_remove(t->queries, q);
641                 goto fail;
642         }
643
644         return 0;
645
646 fail:
647         dns_query_transaction_gc(t);
648         return r;
649 }
650
651 static int dns_query_add_transaction_split(DnsQuery *q, DnsScope *s) {
652         int r;
653
654         assert(q);
655         assert(s);
656
657         if (s->protocol == DNS_PROTOCOL_MDNS) {
658                 r = dns_query_add_transaction(q, s, NULL);
659                 if (r < 0)
660                         return r;
661         } else {
662                 unsigned i;
663
664                 /* On DNS and LLMNR we can only send a single
665                  * question per datagram, hence issue multiple
666                  * transactions. */
667
668                 for (i = 0; i < q->question->n_keys; i++) {
669                         r = dns_query_add_transaction(q, s, q->question->keys[i]);
670                         if (r < 0)
671                                 return r;
672                 }
673         }
674
675         return 0;
676 }
677
678 int dns_query_go(DnsQuery *q) {
679         DnsScopeMatch found = DNS_SCOPE_NO;
680         DnsScope *s, *first = NULL;
681         DnsQueryTransaction *t;
682         const char *name;
683         Iterator i;
684         int r;
685
686         assert(q);
687
688         if (q->state != DNS_QUERY_NULL)
689                 return 0;
690
691         assert(q->question);
692         assert(q->question->n_keys > 0);
693
694         name = DNS_RESOURCE_KEY_NAME(q->question->keys[0]);
695
696         LIST_FOREACH(scopes, s, q->manager->dns_scopes) {
697                 DnsScopeMatch match;
698
699                 match = dns_scope_good_domain(s, name);
700                 if (match < 0)
701                         return match;
702
703                 if (match == DNS_SCOPE_NO)
704                         continue;
705
706                 found = match;
707
708                 if (match == DNS_SCOPE_YES) {
709                         first = s;
710                         break;
711                 } else {
712                         assert(match == DNS_SCOPE_MAYBE);
713
714                         if (!first)
715                                 first = s;
716                 }
717         }
718
719         if (found == DNS_SCOPE_NO)
720                 return -ESRCH;
721
722         r = dns_query_add_transaction_split(q, first);
723         if (r < 0)
724                 return r;
725
726         LIST_FOREACH(scopes, s, first->scopes_next) {
727                 DnsScopeMatch match;
728
729                 match = dns_scope_good_domain(s, name);
730                 if (match < 0)
731                         return match;
732
733                 if (match != found)
734                         continue;
735
736                 r = dns_query_add_transaction_split(q, s);
737                 if (r < 0)
738                         return r;
739         }
740
741         q->answer = dns_answer_unref(q->answer);
742         q->answer_ifindex = 0;
743         q->answer_rcode = 0;
744
745         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);
746         if (r < 0)
747                 goto fail;
748
749         q->state = DNS_QUERY_PENDING;
750         q->block_ready++;
751
752         SET_FOREACH(t, q->transactions, i) {
753                 if (t->state == DNS_QUERY_NULL) {
754                         r = dns_query_transaction_go(t);
755                         if (r < 0)
756                                 goto fail;
757                 }
758         }
759
760         q->block_ready--;
761         dns_query_ready(q);
762
763         return 1;
764
765 fail:
766         dns_query_stop(q);
767         return r;
768 }
769
770 void dns_query_ready(DnsQuery *q) {
771         DnsQueryTransaction *t;
772         DnsQueryState state = DNS_QUERY_NO_SERVERS;
773         _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL;
774         int rcode = 0;
775         DnsScope *scope = NULL;
776         Iterator i;
777
778         assert(q);
779         assert(IN_SET(q->state, DNS_QUERY_NULL, DNS_QUERY_PENDING));
780
781         /* Note that this call might invalidate the query. Callers
782          * should hence not attempt to access the query or transaction
783          * after calling this function, unless the block_ready
784          * counter was explicitly bumped before doing so. */
785
786         if (q->block_ready > 0)
787                 return;
788
789         SET_FOREACH(t, q->transactions, i) {
790
791                 /* If we found a successful answer, ignore all answers from other scopes */
792                 if (state == DNS_QUERY_SUCCESS && t->scope != scope)
793                         continue;
794
795                 /* One of the transactions is still going on, let's wait for it */
796                 if (t->state == DNS_QUERY_PENDING || t->state == DNS_QUERY_NULL)
797                         return;
798
799                 /* One of the transactions is successful, let's use
800                  * it, and copy its data out */
801                 if (t->state == DNS_QUERY_SUCCESS) {
802                         DnsAnswer *a;
803
804                         if (t->received) {
805                                 rcode = DNS_PACKET_RCODE(t->received);
806                                 a = t->received->answer;
807                         } else {
808                                 rcode = t->cached_rcode;
809                                 a = t->cached;
810                         }
811
812                         if (state == DNS_QUERY_SUCCESS) {
813                                 DnsAnswer *merged;
814
815                                 merged = dns_answer_merge(answer, a);
816                                 if (!merged) {
817                                         dns_query_complete(q, DNS_QUERY_RESOURCES);
818                                         return;
819                                 }
820
821                                 dns_answer_unref(answer);
822                                 answer = merged;
823                         } else {
824                                 dns_answer_unref(answer);
825                                 answer = dns_answer_ref(a);
826                         }
827
828                         scope = t->scope;
829                         state = DNS_QUERY_SUCCESS;
830                         continue;
831                 }
832
833                 /* One of the transactions has failed, let's see
834                  * whether we find anything better, but if not, return
835                  * its response data */
836                 if (state != DNS_QUERY_SUCCESS && t->state == DNS_QUERY_FAILURE) {
837                         DnsAnswer *a;
838
839                         if (t->received) {
840                                 rcode = DNS_PACKET_RCODE(t->received);
841                                 a = t->received->answer;
842                         } else {
843                                 rcode = t->cached_rcode;
844                                 a = t->cached;
845                         }
846
847                         dns_answer_unref(answer);
848                         answer = dns_answer_ref(a);
849
850                         scope = t->scope;
851                         state = DNS_QUERY_FAILURE;
852                         continue;
853                 }
854
855                 if (state == DNS_QUERY_NO_SERVERS && t->state != DNS_QUERY_NO_SERVERS)
856                         state = t->state;
857         }
858
859         if (IN_SET(state, DNS_QUERY_SUCCESS, DNS_QUERY_FAILURE)) {
860                 q->answer = dns_answer_ref(answer);
861                 q->answer_rcode = rcode;
862                 q->answer_ifindex = (scope && scope->link) ? scope->link->ifindex : 0;
863         }
864
865         dns_query_complete(q, state);
866 }
867
868 int dns_query_cname_redirect(DnsQuery *q, const char *name) {
869         _cleanup_(dns_question_unrefp) DnsQuestion *nq = NULL;
870         int r;
871
872         assert(q);
873
874         if (q->n_cname_redirects > CNAME_MAX)
875                 return -ELOOP;
876
877         r = dns_question_cname_redirect(q->question, name, &nq);
878         if (r < 0)
879                 return r;
880
881         dns_question_unref(q->question);
882         q->question = nq;
883         nq = NULL;
884
885         q->n_cname_redirects++;
886
887         dns_query_stop(q);
888         q->state = DNS_QUERY_NULL;
889
890         return 0;
891 }