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