]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/resolve/resolved-dns-query.c
question: drop dns_question_is_superset() which we don't use anymore
[thirdparty/systemd.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 "alloc-util.h"
23 #include "dns-domain.h"
24 #include "hostname-util.h"
25 #include "local-addresses.h"
26 #include "resolved-dns-query.h"
27
28 /* How long to wait for the query in total */
29 #define QUERY_TIMEOUT_USEC (30 * USEC_PER_SEC)
30
31 #define CNAME_MAX 8
32 #define QUERIES_MAX 2048
33 #define AUXILIARY_QUERIES_MAX 64
34
35 static void dns_query_stop(DnsQuery *q) {
36 DnsTransaction *t;
37
38 assert(q);
39
40 q->timeout_event_source = sd_event_source_unref(q->timeout_event_source);
41
42 while ((t = set_steal_first(q->transactions))) {
43 set_remove(t->queries, q);
44 dns_transaction_gc(t);
45 }
46 }
47
48 DnsQuery *dns_query_free(DnsQuery *q) {
49 if (!q)
50 return NULL;
51
52 while (q->auxiliary_queries)
53 dns_query_free(q->auxiliary_queries);
54
55 if (q->auxiliary_for) {
56 assert(q->auxiliary_for->n_auxiliary_queries > 0);
57 q->auxiliary_for->n_auxiliary_queries--;
58 LIST_REMOVE(auxiliary_queries, q->auxiliary_for->auxiliary_queries, q);
59 }
60
61 dns_query_stop(q);
62 set_free(q->transactions);
63
64 dns_question_unref(q->question);
65 dns_answer_unref(q->answer);
66
67 sd_bus_message_unref(q->request);
68 sd_bus_track_unref(q->bus_track);
69
70 if (q->manager) {
71 LIST_REMOVE(queries, q->manager->dns_queries, q);
72 q->manager->n_dns_queries--;
73 }
74
75 free(q);
76
77 return NULL;
78 }
79
80 int dns_query_new(Manager *m, DnsQuery **ret, DnsQuestion *question, int ifindex, uint64_t flags) {
81 _cleanup_(dns_query_freep) DnsQuery *q = NULL;
82 unsigned i;
83 int r;
84
85 assert(m);
86 assert(question);
87
88 r = dns_question_is_valid(question);
89 if (r < 0)
90 return r;
91
92 if (m->n_dns_queries >= QUERIES_MAX)
93 return -EBUSY;
94
95 q = new0(DnsQuery, 1);
96 if (!q)
97 return -ENOMEM;
98
99 q->question = dns_question_ref(question);
100 q->ifindex = ifindex;
101 q->flags = flags;
102
103 for (i = 0; i < question->n_keys; i++) {
104 _cleanup_free_ char *p;
105
106 r = dns_resource_key_to_string(question->keys[i], &p);
107 if (r < 0)
108 return r;
109
110 log_debug("Looking up RR for %s", p);
111 }
112
113 LIST_PREPEND(queries, m->dns_queries, q);
114 m->n_dns_queries++;
115 q->manager = m;
116
117 if (ret)
118 *ret = q;
119 q = NULL;
120
121 return 0;
122 }
123
124 int dns_query_make_auxiliary(DnsQuery *q, DnsQuery *auxiliary_for) {
125 assert(q);
126 assert(auxiliary_for);
127
128 /* Ensure that that the query is not auxiliary yet, and
129 * nothing else is auxiliary to it either */
130 assert(!q->auxiliary_for);
131 assert(!q->auxiliary_queries);
132
133 /* Ensure that the unit we shall be made auxiliary for isn't
134 * auxiliary itself */
135 assert(!auxiliary_for->auxiliary_for);
136
137 if (auxiliary_for->n_auxiliary_queries >= AUXILIARY_QUERIES_MAX)
138 return -EAGAIN;
139
140 LIST_PREPEND(auxiliary_queries, auxiliary_for->auxiliary_queries, q);
141 q->auxiliary_for = auxiliary_for;
142
143 auxiliary_for->n_auxiliary_queries++;
144 return 0;
145 }
146
147 static void dns_query_complete(DnsQuery *q, DnsTransactionState state) {
148 assert(q);
149 assert(!IN_SET(state, DNS_TRANSACTION_NULL, DNS_TRANSACTION_PENDING));
150 assert(IN_SET(q->state, DNS_TRANSACTION_NULL, DNS_TRANSACTION_PENDING));
151
152 /* Note that this call might invalidate the query. Callers
153 * should hence not attempt to access the query or transaction
154 * after calling this function. */
155
156 q->state = state;
157
158 dns_query_stop(q);
159 if (q->complete)
160 q->complete(q);
161 }
162
163 static int on_query_timeout(sd_event_source *s, usec_t usec, void *userdata) {
164 DnsQuery *q = userdata;
165
166 assert(s);
167 assert(q);
168
169 dns_query_complete(q, DNS_TRANSACTION_TIMEOUT);
170 return 0;
171 }
172
173 static int dns_query_add_transaction(DnsQuery *q, DnsScope *s, DnsResourceKey *key) {
174 DnsTransaction *t;
175 int r;
176
177 assert(q);
178 assert(s);
179 assert(key);
180
181 r = set_ensure_allocated(&q->transactions, NULL);
182 if (r < 0)
183 return r;
184
185 t = dns_scope_find_transaction(s, key, true);
186 if (!t) {
187 r = dns_transaction_new(&t, s, key);
188 if (r < 0)
189 return r;
190 }
191
192 r = set_ensure_allocated(&t->queries, NULL);
193 if (r < 0)
194 goto gc;
195
196 r = set_put(t->queries, q);
197 if (r < 0)
198 goto gc;
199
200 r = set_put(q->transactions, t);
201 if (r < 0) {
202 set_remove(t->queries, q);
203 goto gc;
204 }
205
206 return 0;
207
208 gc:
209 dns_transaction_gc(t);
210 return r;
211 }
212
213 static int dns_query_add_transaction_split(DnsQuery *q, DnsScope *s) {
214 unsigned i;
215 int r;
216
217 assert(q);
218 assert(s);
219
220 /* Create one transaction per question key */
221
222 for (i = 0; i < q->question->n_keys; i++) {
223 r = dns_query_add_transaction(q, s, q->question->keys[i]);
224 if (r < 0)
225 return r;
226 }
227
228 return 0;
229 }
230
231 static int SYNTHESIZE_IFINDEX(int ifindex) {
232
233 /* When the caller asked for resolving on a specific
234 * interface, we synthesize the answer for that
235 * interface. However, if nothing specific was claimed and we
236 * only return localhost RRs, we synthesize the answer for
237 * localhost. */
238
239 if (ifindex > 0)
240 return ifindex;
241
242 return LOOPBACK_IFINDEX;
243 }
244
245 static int SYNTHESIZE_FAMILY(uint64_t flags) {
246
247 /* Picks an address family depending on set flags. This is
248 * purely for synthesized answers, where the family we return
249 * for the reply should match what was requested in the
250 * question, even though we are synthesizing the answer
251 * here. */
252
253 if (!(flags & SD_RESOLVED_DNS)) {
254 if (flags & SD_RESOLVED_LLMNR_IPV4)
255 return AF_INET;
256 if (flags & SD_RESOLVED_LLMNR_IPV6)
257 return AF_INET6;
258 }
259
260 return AF_UNSPEC;
261 }
262
263 static DnsProtocol SYNTHESIZE_PROTOCOL(uint64_t flags) {
264
265 /* Similar as SYNTHESIZE_FAMILY() but does this for the
266 * protocol. If resolving via DNS was requested, we claim it
267 * was DNS. Similar, if nothing specific was
268 * requested. However, if only resolving via LLMNR was
269 * requested we return that. */
270
271 if (flags & SD_RESOLVED_DNS)
272 return DNS_PROTOCOL_DNS;
273 if (flags & SD_RESOLVED_LLMNR)
274 return DNS_PROTOCOL_LLMNR;
275
276 return DNS_PROTOCOL_DNS;
277 }
278
279 static int dns_type_to_af(uint16_t t) {
280 switch (t) {
281
282 case DNS_TYPE_A:
283 return AF_INET;
284
285 case DNS_TYPE_AAAA:
286 return AF_INET6;
287
288 case DNS_TYPE_ANY:
289 return AF_UNSPEC;
290
291 default:
292 return -EINVAL;
293 }
294 }
295
296 static int synthesize_localhost_rr(DnsQuery *q, DnsResourceKey *key, DnsAnswer **answer) {
297 int r;
298
299 assert(q);
300 assert(key);
301 assert(answer);
302
303 r = dns_answer_reserve(answer, 2);
304 if (r < 0)
305 return r;
306
307 if (IN_SET(key->type, DNS_TYPE_A, DNS_TYPE_ANY)) {
308 _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
309
310 rr = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_A, DNS_RESOURCE_KEY_NAME(key));
311 if (!rr)
312 return -ENOMEM;
313
314 rr->a.in_addr.s_addr = htobe32(INADDR_LOOPBACK);
315
316 r = dns_answer_add(*answer, rr, SYNTHESIZE_IFINDEX(q->ifindex));
317 if (r < 0)
318 return r;
319 }
320
321 if (IN_SET(key->type, DNS_TYPE_AAAA, DNS_TYPE_ANY)) {
322 _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
323
324 rr = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_AAAA, DNS_RESOURCE_KEY_NAME(key));
325 if (!rr)
326 return -ENOMEM;
327
328 rr->aaaa.in6_addr = in6addr_loopback;
329
330 r = dns_answer_add(*answer, rr, SYNTHESIZE_IFINDEX(q->ifindex));
331 if (r < 0)
332 return r;
333 }
334
335 return 0;
336 }
337
338 static int answer_add_ptr(DnsAnswer **answer, const char *from, const char *to, int ifindex) {
339 _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
340
341 rr = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_PTR, from);
342 if (!rr)
343 return -ENOMEM;
344
345 rr->ptr.name = strdup(to);
346 if (!rr->ptr.name)
347 return -ENOMEM;
348
349 return dns_answer_add(*answer, rr, ifindex);
350 }
351
352 static int synthesize_localhost_ptr(DnsQuery *q, DnsResourceKey *key, DnsAnswer **answer) {
353 int r;
354
355 assert(q);
356 assert(key);
357 assert(answer);
358
359 r = dns_answer_reserve(answer, 1);
360 if (r < 0)
361 return r;
362
363 if (IN_SET(key->type, DNS_TYPE_PTR, DNS_TYPE_ANY)) {
364 r = answer_add_ptr(answer, DNS_RESOURCE_KEY_NAME(key), "localhost", SYNTHESIZE_IFINDEX(q->ifindex));
365 if (r < 0)
366 return r;
367 }
368
369 return 0;
370 }
371
372 static int answer_add_addresses_rr(
373 DnsAnswer **answer,
374 const char *name,
375 struct local_address *addresses,
376 unsigned n_addresses) {
377
378 unsigned j;
379 int r;
380
381 assert(answer);
382 assert(name);
383
384 r = dns_answer_reserve(answer, n_addresses);
385 if (r < 0)
386 return r;
387
388 for (j = 0; j < n_addresses; j++) {
389 _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
390
391 r = dns_resource_record_new_address(&rr, addresses[j].family, &addresses[j].address, name);
392 if (r < 0)
393 return r;
394
395 r = dns_answer_add(*answer, rr, addresses[j].ifindex);
396 if (r < 0)
397 return r;
398 }
399
400 return 0;
401 }
402
403 static int answer_add_addresses_ptr(
404 DnsAnswer **answer,
405 const char *name,
406 struct local_address *addresses,
407 unsigned n_addresses,
408 int af, const union in_addr_union *match) {
409
410 unsigned j;
411 int r;
412
413 assert(answer);
414 assert(name);
415
416 for (j = 0; j < n_addresses; j++) {
417 _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
418
419 if (af != AF_UNSPEC) {
420
421 if (addresses[j].family != af)
422 continue;
423
424 if (match && !in_addr_equal(af, match, &addresses[j].address))
425 continue;
426 }
427
428 r = dns_answer_reserve(answer, 1);
429 if (r < 0)
430 return r;
431
432 r = dns_resource_record_new_reverse(&rr, addresses[j].family, &addresses[j].address, name);
433 if (r < 0)
434 return r;
435
436 r = dns_answer_add(*answer, rr, addresses[j].ifindex);
437 if (r < 0)
438 return r;
439 }
440
441 return 0;
442 }
443
444 static int synthesize_system_hostname_rr(DnsQuery *q, DnsResourceKey *key, DnsAnswer **answer) {
445 _cleanup_free_ struct local_address *addresses = NULL;
446 int n = 0, af;
447
448 assert(q);
449 assert(key);
450 assert(answer);
451
452 af = dns_type_to_af(key->type);
453 if (af >= 0) {
454 n = local_addresses(q->manager->rtnl, q->ifindex, af, &addresses);
455 if (n < 0)
456 return n;
457
458 if (n == 0) {
459 struct local_address buffer[2];
460
461 /* If we have no local addresses then use ::1
462 * and 127.0.0.2 as local ones. */
463
464 if (af == AF_INET || af == AF_UNSPEC)
465 buffer[n++] = (struct local_address) {
466 .family = AF_INET,
467 .ifindex = SYNTHESIZE_IFINDEX(q->ifindex),
468 .address.in.s_addr = htobe32(0x7F000002),
469 };
470
471 if (af == AF_INET6 || af == AF_UNSPEC)
472 buffer[n++] = (struct local_address) {
473 .family = AF_INET6,
474 .ifindex = SYNTHESIZE_IFINDEX(q->ifindex),
475 .address.in6 = in6addr_loopback,
476 };
477
478 return answer_add_addresses_rr(answer, DNS_RESOURCE_KEY_NAME(key), buffer, n);
479 }
480 }
481
482 return answer_add_addresses_rr(answer, DNS_RESOURCE_KEY_NAME(key), addresses, n);
483 }
484
485 static int synthesize_system_hostname_ptr(DnsQuery *q, int af, const union in_addr_union *address, DnsAnswer **answer) {
486 _cleanup_free_ struct local_address *addresses = NULL;
487 int n, r;
488
489 assert(q);
490 assert(address);
491 assert(answer);
492
493 if (af == AF_INET && address->in.s_addr == htobe32(0x7F000002)) {
494
495 /* Always map the IPv4 address 127.0.0.2 to the local
496 * hostname, in addition to "localhost": */
497
498 r = dns_answer_reserve(answer, 3);
499 if (r < 0)
500 return r;
501
502 r = answer_add_ptr(answer, "2.0.0.127.in-addr.arpa", q->manager->llmnr_hostname, SYNTHESIZE_IFINDEX(q->ifindex));
503 if (r < 0)
504 return r;
505
506 r = answer_add_ptr(answer, "2.0.0.127.in-addr.arpa", q->manager->mdns_hostname, SYNTHESIZE_IFINDEX(q->ifindex));
507 if (r < 0)
508 return r;
509
510 r = answer_add_ptr(answer, "2.0.0.127.in-addr.arpa", "localhost", SYNTHESIZE_IFINDEX(q->ifindex));
511 if (r < 0)
512 return r;
513
514 return 0;
515 }
516
517 n = local_addresses(q->manager->rtnl, q->ifindex, af, &addresses);
518 if (n < 0)
519 return n;
520
521 r = answer_add_addresses_ptr(answer, q->manager->llmnr_hostname, addresses, n, af, address);
522 if (r < 0)
523 return r;
524
525 return answer_add_addresses_ptr(answer, q->manager->mdns_hostname, addresses, n, af, address);
526 }
527
528 static int synthesize_gateway_rr(DnsQuery *q, DnsResourceKey *key, DnsAnswer **answer) {
529 _cleanup_free_ struct local_address *addresses = NULL;
530 int n = 0, af;
531
532 assert(q);
533 assert(key);
534 assert(answer);
535
536 af = dns_type_to_af(key->type);
537 if (af >= 0) {
538 n = local_gateways(q->manager->rtnl, q->ifindex, af, &addresses);
539 if (n < 0)
540 return n;
541 }
542
543 return answer_add_addresses_rr(answer, DNS_RESOURCE_KEY_NAME(key), addresses, n);
544 }
545
546 static int synthesize_gateway_ptr(DnsQuery *q, int af, const union in_addr_union *address, DnsAnswer **answer) {
547 _cleanup_free_ struct local_address *addresses = NULL;
548 int n;
549
550 assert(q);
551 assert(address);
552 assert(answer);
553
554 n = local_gateways(q->manager->rtnl, q->ifindex, af, &addresses);
555 if (n < 0)
556 return n;
557
558 return answer_add_addresses_ptr(answer, "gateway", addresses, n, af, address);
559 }
560
561 static int dns_query_synthesize_reply(DnsQuery *q, DnsTransactionState *state) {
562 _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL;
563 unsigned i;
564 int r;
565
566 assert(q);
567 assert(state);
568
569 /* Tries to synthesize localhost RR replies where appropriate */
570
571 if (!IN_SET(*state,
572 DNS_TRANSACTION_FAILURE,
573 DNS_TRANSACTION_NO_SERVERS,
574 DNS_TRANSACTION_TIMEOUT,
575 DNS_TRANSACTION_ATTEMPTS_MAX_REACHED))
576 return 0;
577
578 for (i = 0; i < q->question->n_keys; i++) {
579 union in_addr_union address;
580 const char *name;
581 int af;
582
583 if (q->question->keys[i]->class != DNS_CLASS_IN &&
584 q->question->keys[i]->class != DNS_CLASS_ANY)
585 continue;
586
587 name = DNS_RESOURCE_KEY_NAME(q->question->keys[i]);
588
589 if (is_localhost(name)) {
590
591 r = synthesize_localhost_rr(q, q->question->keys[i], &answer);
592 if (r < 0)
593 return log_error_errno(r, "Failed to synthesize localhost RRs: %m");
594
595 } else if (manager_is_own_hostname(q->manager, name)) {
596
597 r = synthesize_system_hostname_rr(q, q->question->keys[i], &answer);
598 if (r < 0)
599 return log_error_errno(r, "Failed to synthesize system hostname RRs: %m");
600
601 } else if (is_gateway_hostname(name)) {
602
603 r = synthesize_gateway_rr(q, q->question->keys[i], &answer);
604 if (r < 0)
605 return log_error_errno(r, "Failed to synthesize gateway RRs: %m");
606
607 } else if ((dns_name_endswith(name, "127.in-addr.arpa") > 0 && dns_name_equal(name, "2.0.0.127.in-addr.arpa") == 0) ||
608 dns_name_equal(name, "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa") > 0) {
609
610 r = synthesize_localhost_ptr(q, q->question->keys[i], &answer);
611 if (r < 0)
612 return log_error_errno(r, "Failed to synthesize localhost PTR RRs: %m");
613
614 } else if (dns_name_address(name, &af, &address) > 0) {
615
616 r = synthesize_system_hostname_ptr(q, af, &address, &answer);
617 if (r < 0)
618 return log_error_errno(r, "Failed to synthesize system hostname PTR RR: %m");
619
620 r = synthesize_gateway_ptr(q, af, &address, &answer);
621 if (r < 0)
622 return log_error_errno(r, "Failed to synthesize gateway hostname PTR RR: %m");
623 }
624 }
625
626 if (!answer)
627 return 0;
628
629 dns_answer_unref(q->answer);
630 q->answer = answer;
631 answer = NULL;
632
633 q->answer_family = SYNTHESIZE_FAMILY(q->flags);
634 q->answer_protocol = SYNTHESIZE_PROTOCOL(q->flags);
635 q->answer_rcode = DNS_RCODE_SUCCESS;
636
637 *state = DNS_TRANSACTION_SUCCESS;
638
639 return 1;
640 }
641
642 int dns_query_go(DnsQuery *q) {
643 DnsScopeMatch found = DNS_SCOPE_NO;
644 DnsScope *s, *first = NULL;
645 DnsTransaction *t;
646 const char *name;
647 Iterator i;
648 int r;
649
650 assert(q);
651
652 if (q->state != DNS_TRANSACTION_NULL)
653 return 0;
654
655 assert(q->question);
656 assert(q->question->n_keys > 0);
657
658 name = dns_question_name(q->question);
659
660 LIST_FOREACH(scopes, s, q->manager->dns_scopes) {
661 DnsScopeMatch match;
662
663 match = dns_scope_good_domain(s, q->ifindex, q->flags, name);
664 if (match < 0)
665 return match;
666
667 if (match == DNS_SCOPE_NO)
668 continue;
669
670 found = match;
671
672 if (match == DNS_SCOPE_YES) {
673 first = s;
674 break;
675 } else {
676 assert(match == DNS_SCOPE_MAYBE);
677
678 if (!first)
679 first = s;
680 }
681 }
682
683 if (found == DNS_SCOPE_NO) {
684 DnsTransactionState state = DNS_TRANSACTION_NO_SERVERS;
685
686 dns_query_synthesize_reply(q, &state);
687 dns_query_complete(q, state);
688 return 1;
689 }
690
691 r = dns_query_add_transaction_split(q, first);
692 if (r < 0)
693 goto fail;
694
695 LIST_FOREACH(scopes, s, first->scopes_next) {
696 DnsScopeMatch match;
697
698 match = dns_scope_good_domain(s, q->ifindex, q->flags, name);
699 if (match < 0)
700 goto fail;
701
702 if (match != found)
703 continue;
704
705 r = dns_query_add_transaction_split(q, s);
706 if (r < 0)
707 goto fail;
708 }
709
710 q->answer = dns_answer_unref(q->answer);
711 q->answer_rcode = 0;
712 q->answer_family = AF_UNSPEC;
713 q->answer_protocol = _DNS_PROTOCOL_INVALID;
714
715 r = sd_event_add_time(
716 q->manager->event,
717 &q->timeout_event_source,
718 clock_boottime_or_monotonic(),
719 now(clock_boottime_or_monotonic()) + QUERY_TIMEOUT_USEC, 0,
720 on_query_timeout, q);
721 if (r < 0)
722 goto fail;
723
724 q->state = DNS_TRANSACTION_PENDING;
725 q->block_ready++;
726
727 /* Start the transactions that are not started yet */
728 SET_FOREACH(t, q->transactions, i) {
729 if (t->state != DNS_TRANSACTION_NULL)
730 continue;
731
732 r = dns_transaction_go(t);
733 if (r < 0)
734 goto fail;
735 }
736
737 q->block_ready--;
738 dns_query_ready(q);
739
740 return 1;
741
742 fail:
743 dns_query_stop(q);
744 return r;
745 }
746
747 void dns_query_ready(DnsQuery *q) {
748 DnsTransaction *t;
749 DnsTransactionState state = DNS_TRANSACTION_NO_SERVERS;
750 _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL;
751 int rcode = 0;
752 DnsScope *scope = NULL;
753 bool pending = false;
754 Iterator i;
755
756 assert(q);
757 assert(IN_SET(q->state, DNS_TRANSACTION_NULL, DNS_TRANSACTION_PENDING));
758
759 /* Note that this call might invalidate the query. Callers
760 * should hence not attempt to access the query or transaction
761 * after calling this function, unless the block_ready
762 * counter was explicitly bumped before doing so. */
763
764 if (q->block_ready > 0)
765 return;
766
767 SET_FOREACH(t, q->transactions, i) {
768
769 /* If we found a successful answer, ignore all answers from other scopes */
770 if (state == DNS_TRANSACTION_SUCCESS && t->scope != scope)
771 continue;
772
773 /* One of the transactions is still going on, let's maybe wait for it */
774 if (IN_SET(t->state, DNS_TRANSACTION_PENDING, DNS_TRANSACTION_NULL)) {
775 pending = true;
776 continue;
777 }
778
779 /* One of the transactions is successful, let's use
780 * it, and copy its data out */
781 if (t->state == DNS_TRANSACTION_SUCCESS) {
782 DnsAnswer *a;
783
784 if (t->received) {
785 rcode = DNS_PACKET_RCODE(t->received);
786 a = t->received->answer;
787 } else {
788 rcode = t->cached_rcode;
789 a = t->cached;
790 }
791
792 if (state == DNS_TRANSACTION_SUCCESS) {
793 DnsAnswer *merged;
794
795 merged = dns_answer_merge(answer, a);
796 if (!merged) {
797 dns_query_complete(q, DNS_TRANSACTION_RESOURCES);
798 return;
799 }
800
801 dns_answer_unref(answer);
802 answer = merged;
803 } else {
804 dns_answer_unref(answer);
805 answer = dns_answer_ref(a);
806 }
807
808 scope = t->scope;
809 state = DNS_TRANSACTION_SUCCESS;
810 continue;
811 }
812
813 /* One of the transactions has failed, let's see
814 * whether we find anything better, but if not, return
815 * its response data */
816 if (state != DNS_TRANSACTION_SUCCESS && t->state == DNS_TRANSACTION_FAILURE) {
817 DnsAnswer *a;
818
819 if (t->received) {
820 rcode = DNS_PACKET_RCODE(t->received);
821 a = t->received->answer;
822 } else {
823 rcode = t->cached_rcode;
824 a = t->cached;
825 }
826
827 dns_answer_unref(answer);
828 answer = dns_answer_ref(a);
829
830 scope = t->scope;
831 state = DNS_TRANSACTION_FAILURE;
832 continue;
833 }
834
835 if (state == DNS_TRANSACTION_NO_SERVERS && t->state != DNS_TRANSACTION_NO_SERVERS)
836 state = t->state;
837 }
838
839 if (pending) {
840
841 /* If so far we weren't successful, and there's
842 * something still pending, then wait for it */
843 if (state != DNS_TRANSACTION_SUCCESS)
844 return;
845
846 /* If we already were successful, then only wait for
847 * other transactions on the same scope to finish. */
848 SET_FOREACH(t, q->transactions, i) {
849 if (t->scope == scope && IN_SET(t->state, DNS_TRANSACTION_PENDING, DNS_TRANSACTION_NULL))
850 return;
851 }
852 }
853
854 if (IN_SET(state, DNS_TRANSACTION_SUCCESS, DNS_TRANSACTION_FAILURE)) {
855 q->answer = dns_answer_ref(answer);
856 q->answer_rcode = rcode;
857 q->answer_protocol = scope ? scope->protocol : _DNS_PROTOCOL_INVALID;
858 q->answer_family = scope ? scope->family : AF_UNSPEC;
859 }
860
861 /* Try to synthesize a reply if we couldn't resolve something. */
862 dns_query_synthesize_reply(q, &state);
863
864 dns_query_complete(q, state);
865 }
866
867 static int dns_query_cname_redirect(DnsQuery *q, const DnsResourceRecord *cname) {
868 _cleanup_(dns_question_unrefp) DnsQuestion *nq = NULL;
869 int r;
870
871 assert(q);
872
873 q->n_cname_redirects ++;
874 if (q->n_cname_redirects > CNAME_MAX)
875 return -ELOOP;
876
877 r = dns_question_cname_redirect(q->question, cname, &nq);
878 if (r < 0)
879 return r;
880
881 dns_question_unref(q->question);
882 q->question = nq;
883 nq = NULL;
884
885 dns_query_stop(q);
886 q->state = DNS_TRANSACTION_NULL;
887
888 return 0;
889 }
890
891 int dns_query_process_cname(DnsQuery *q) {
892 _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *cname = NULL;
893 DnsResourceRecord *rr;
894 int r;
895
896 assert(q);
897
898 if (q->state != DNS_TRANSACTION_SUCCESS)
899 return 0;
900
901 DNS_ANSWER_FOREACH(rr, q->answer) {
902
903 r = dns_question_matches_rr(q->question, rr);
904 if (r < 0)
905 return r;
906 if (r > 0)
907 return 0; /* The answer matches directly, no need to follow cnames */
908
909 r = dns_question_matches_cname(q->question, rr);
910 if (r < 0)
911 return r;
912 if (r > 0 && !cname)
913 cname = dns_resource_record_ref(rr);
914 }
915
916 if (!cname)
917 return 0; /* No cname to follow */
918
919 if (q->flags & SD_RESOLVED_NO_CNAME)
920 return -ELOOP;
921
922 /* OK, let's actually follow the CNAME */
923 r = dns_query_cname_redirect(q, cname);
924 if (r < 0)
925 return r;
926
927 /* Let's see if the answer can already answer the new
928 * redirected question */
929 DNS_ANSWER_FOREACH(rr, q->answer) {
930 r = dns_question_matches_rr(q->question, rr);
931 if (r < 0)
932 return r;
933 if (r > 0)
934 return 0; /* It can answer it, yay! */
935 }
936
937 /* OK, it cannot, let's begin with the new query */
938 r = dns_query_go(q);
939 if (r < 0)
940 return r;
941
942 return 1; /* We return > 0, if we restarted the query for a new cname */
943 }
944
945 static int on_bus_track(sd_bus_track *t, void *userdata) {
946 DnsQuery *q = userdata;
947
948 assert(t);
949 assert(q);
950
951 log_debug("Client of active query vanished, aborting query.");
952 dns_query_complete(q, DNS_TRANSACTION_ABORTED);
953 return 0;
954 }
955
956 int dns_query_bus_track(DnsQuery *q, sd_bus_message *m) {
957 int r;
958
959 assert(q);
960 assert(m);
961
962 if (!q->bus_track) {
963 r = sd_bus_track_new(sd_bus_message_get_bus(m), &q->bus_track, on_bus_track, q);
964 if (r < 0)
965 return r;
966 }
967
968 r = sd_bus_track_add_sender(q->bus_track, m);
969 if (r < 0)
970 return r;
971
972 return 0;
973 }