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