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