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