]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/resolve/resolved-dns-query.c
resolved: fix logging about DNAME redirection
[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 int dns_query_candidate_new(DnsQueryCandidate **ret, DnsQuery *q, DnsScope *s) {
36 DnsQueryCandidate *c;
37
38 assert(ret);
39 assert(q);
40 assert(s);
41
42 c = new0(DnsQueryCandidate, 1);
43 if (!c)
44 return -ENOMEM;
45
46 c->query = q;
47 c->scope = s;
48
49 LIST_PREPEND(candidates_by_query, q->candidates, c);
50 LIST_PREPEND(candidates_by_scope, s->query_candidates, c);
51
52 *ret = c;
53 return 0;
54 }
55
56 static void dns_query_candidate_stop(DnsQueryCandidate *c) {
57 DnsTransaction *t;
58
59 assert(c);
60
61 while ((t = set_steal_first(c->transactions))) {
62 set_remove(t->notify_query_candidates, c);
63 dns_transaction_gc(t);
64 }
65 }
66
67 DnsQueryCandidate* dns_query_candidate_free(DnsQueryCandidate *c) {
68
69 if (!c)
70 return NULL;
71
72 dns_query_candidate_stop(c);
73
74 set_free(c->transactions);
75 dns_search_domain_unref(c->search_domain);
76
77 if (c->query)
78 LIST_REMOVE(candidates_by_query, c->query->candidates, c);
79
80 if (c->scope)
81 LIST_REMOVE(candidates_by_scope, c->scope->query_candidates, c);
82
83 free(c);
84
85 return NULL;
86 }
87
88 static int dns_query_candidate_next_search_domain(DnsQueryCandidate *c) {
89 DnsSearchDomain *next = NULL;
90
91 assert(c);
92
93 if (c->search_domain && c->search_domain->linked) {
94 next = c->search_domain->domains_next;
95
96 if (!next) /* We hit the end of the list */
97 return 0;
98
99 } else {
100 next = dns_scope_get_search_domains(c->scope);
101
102 if (!next) /* OK, there's nothing. */
103 return 0;
104 }
105
106 dns_search_domain_unref(c->search_domain);
107 c->search_domain = dns_search_domain_ref(next);
108
109 return 1;
110 }
111
112 static int dns_query_candidate_add_transaction(DnsQueryCandidate *c, DnsResourceKey *key) {
113 DnsTransaction *t;
114 int r;
115
116 assert(c);
117 assert(key);
118
119 t = dns_scope_find_transaction(c->scope, key, true);
120 if (!t) {
121 r = dns_transaction_new(&t, c->scope, key);
122 if (r < 0)
123 return r;
124 } else {
125 if (set_contains(c->transactions, t))
126 return 0;
127 }
128
129 r = set_ensure_allocated(&c->transactions, NULL);
130 if (r < 0)
131 goto gc;
132
133 r = set_ensure_allocated(&t->notify_query_candidates, NULL);
134 if (r < 0)
135 goto gc;
136
137 r = set_put(t->notify_query_candidates, c);
138 if (r < 0)
139 goto gc;
140
141 r = set_put(c->transactions, t);
142 if (r < 0) {
143 (void) set_remove(t->notify_query_candidates, c);
144 goto gc;
145 }
146
147 return 1;
148
149 gc:
150 dns_transaction_gc(t);
151 return r;
152 }
153
154 static int dns_query_candidate_go(DnsQueryCandidate *c) {
155 DnsTransaction *t;
156 Iterator i;
157 int r;
158
159 assert(c);
160
161 /* Start the transactions that are not started yet */
162 SET_FOREACH(t, c->transactions, i) {
163 if (t->state != DNS_TRANSACTION_NULL)
164 continue;
165
166 r = dns_transaction_go(t);
167 if (r < 0)
168 return r;
169 }
170
171 return 0;
172 }
173
174 static DnsTransactionState dns_query_candidate_state(DnsQueryCandidate *c) {
175 DnsTransactionState state = DNS_TRANSACTION_NO_SERVERS;
176 DnsTransaction *t;
177 Iterator i;
178
179 assert(c);
180
181 if (c->error_code != 0)
182 return DNS_TRANSACTION_RESOURCES;
183
184 SET_FOREACH(t, c->transactions, i) {
185
186 switch (t->state) {
187
188 case DNS_TRANSACTION_NULL:
189 /* If there's a NULL transaction pending, then
190 * this means not all transactions where
191 * started yet, and we were called from within
192 * the stackframe that is supposed to start
193 * remaining transactions. In this case,
194 * simply claim the candidate is pending. */
195
196 case DNS_TRANSACTION_PENDING:
197 case DNS_TRANSACTION_VALIDATING:
198 /* If there's one transaction currently in
199 * VALIDATING state, then this means there's
200 * also one in PENDING state, hence we can
201 * return PENDING immediately. */
202 return DNS_TRANSACTION_PENDING;
203
204 case DNS_TRANSACTION_SUCCESS:
205 state = t->state;
206 break;
207
208 default:
209 if (state != DNS_TRANSACTION_SUCCESS)
210 state = t->state;
211
212 break;
213 }
214 }
215
216 return state;
217 }
218
219 static int dns_query_candidate_setup_transactions(DnsQueryCandidate *c) {
220 DnsResourceKey *key;
221 int n = 0, r;
222
223 assert(c);
224
225 dns_query_candidate_stop(c);
226
227 /* Create one transaction per question key */
228 DNS_QUESTION_FOREACH(key, c->query->question) {
229 _cleanup_(dns_resource_key_unrefp) DnsResourceKey *new_key = NULL;
230
231 if (c->search_domain) {
232 r = dns_resource_key_new_append_suffix(&new_key, key, c->search_domain->name);
233 if (r < 0)
234 goto fail;
235 }
236
237 r = dns_query_candidate_add_transaction(c, new_key ?: key);
238 if (r < 0)
239 goto fail;
240
241 n++;
242 }
243
244 return n;
245
246 fail:
247 dns_query_candidate_stop(c);
248 return r;
249 }
250
251 void dns_query_candidate_notify(DnsQueryCandidate *c) {
252 DnsTransactionState state;
253 int r;
254
255 assert(c);
256
257 state = dns_query_candidate_state(c);
258
259 if (DNS_TRANSACTION_IS_LIVE(state))
260 return;
261
262 if (state != DNS_TRANSACTION_SUCCESS && c->search_domain) {
263
264 r = dns_query_candidate_next_search_domain(c);
265 if (r < 0)
266 goto fail;
267
268 if (r > 0) {
269 /* OK, there's another search domain to try, let's do so. */
270
271 r = dns_query_candidate_setup_transactions(c);
272 if (r < 0)
273 goto fail;
274
275 if (r > 0) {
276 /* New transactions where queued. Start them and wait */
277
278 r = dns_query_candidate_go(c);
279 if (r < 0)
280 goto fail;
281
282 return;
283 }
284 }
285
286 }
287
288 dns_query_ready(c->query);
289 return;
290
291 fail:
292 log_warning_errno(r, "Failed to follow search domains: %m");
293 c->error_code = r;
294 dns_query_ready(c->query);
295 }
296
297 static void dns_query_stop(DnsQuery *q) {
298 DnsQueryCandidate *c;
299
300 assert(q);
301
302 q->timeout_event_source = sd_event_source_unref(q->timeout_event_source);
303
304 LIST_FOREACH(candidates_by_query, c, q->candidates)
305 dns_query_candidate_stop(c);
306 }
307
308 DnsQuery *dns_query_free(DnsQuery *q) {
309 if (!q)
310 return NULL;
311
312 while (q->auxiliary_queries)
313 dns_query_free(q->auxiliary_queries);
314
315 if (q->auxiliary_for) {
316 assert(q->auxiliary_for->n_auxiliary_queries > 0);
317 q->auxiliary_for->n_auxiliary_queries--;
318 LIST_REMOVE(auxiliary_queries, q->auxiliary_for->auxiliary_queries, q);
319 }
320
321 while (q->candidates)
322 dns_query_candidate_free(q->candidates);
323
324 dns_question_unref(q->question);
325 dns_answer_unref(q->answer);
326 dns_search_domain_unref(q->answer_search_domain);
327
328 sd_bus_message_unref(q->request);
329 sd_bus_track_unref(q->bus_track);
330
331 if (q->manager) {
332 LIST_REMOVE(queries, q->manager->dns_queries, q);
333 q->manager->n_dns_queries--;
334 }
335
336 free(q);
337
338 return NULL;
339 }
340
341 int dns_query_new(Manager *m, DnsQuery **ret, DnsQuestion *question, int ifindex, uint64_t flags) {
342 _cleanup_(dns_query_freep) DnsQuery *q = NULL;
343 unsigned i;
344 int r;
345
346 assert(m);
347 assert(question);
348
349 r = dns_question_is_valid_for_query(question);
350 if (r < 0)
351 return r;
352
353 if (m->n_dns_queries >= QUERIES_MAX)
354 return -EBUSY;
355
356 q = new0(DnsQuery, 1);
357 if (!q)
358 return -ENOMEM;
359
360 q->question = dns_question_ref(question);
361 q->ifindex = ifindex;
362 q->flags = flags;
363 q->answer_family = AF_UNSPEC;
364 q->answer_protocol = _DNS_PROTOCOL_INVALID;
365
366 for (i = 0; i < question->n_keys; i++) {
367 _cleanup_free_ char *p;
368
369 r = dns_resource_key_to_string(question->keys[i], &p);
370 if (r < 0)
371 return r;
372
373 log_debug("Looking up RR for %s", p);
374 }
375
376 LIST_PREPEND(queries, m->dns_queries, q);
377 m->n_dns_queries++;
378 q->manager = m;
379
380 if (ret)
381 *ret = q;
382 q = NULL;
383
384 return 0;
385 }
386
387 int dns_query_make_auxiliary(DnsQuery *q, DnsQuery *auxiliary_for) {
388 assert(q);
389 assert(auxiliary_for);
390
391 /* Ensure that that the query is not auxiliary yet, and
392 * nothing else is auxiliary to it either */
393 assert(!q->auxiliary_for);
394 assert(!q->auxiliary_queries);
395
396 /* Ensure that the unit we shall be made auxiliary for isn't
397 * auxiliary itself */
398 assert(!auxiliary_for->auxiliary_for);
399
400 if (auxiliary_for->n_auxiliary_queries >= AUXILIARY_QUERIES_MAX)
401 return -EAGAIN;
402
403 LIST_PREPEND(auxiliary_queries, auxiliary_for->auxiliary_queries, q);
404 q->auxiliary_for = auxiliary_for;
405
406 auxiliary_for->n_auxiliary_queries++;
407 return 0;
408 }
409
410 static void dns_query_complete(DnsQuery *q, DnsTransactionState state) {
411 assert(q);
412 assert(!DNS_TRANSACTION_IS_LIVE(state));
413 assert(DNS_TRANSACTION_IS_LIVE(q->state));
414
415 /* Note that this call might invalidate the query. Callers
416 * should hence not attempt to access the query or transaction
417 * after calling this function. */
418
419 q->state = state;
420
421 dns_query_stop(q);
422 if (q->complete)
423 q->complete(q);
424 }
425
426 static int on_query_timeout(sd_event_source *s, usec_t usec, void *userdata) {
427 DnsQuery *q = userdata;
428
429 assert(s);
430 assert(q);
431
432 dns_query_complete(q, DNS_TRANSACTION_TIMEOUT);
433 return 0;
434 }
435
436 static int dns_query_add_candidate(DnsQuery *q, DnsScope *s) {
437 DnsQueryCandidate *c;
438 int r;
439
440 assert(q);
441 assert(s);
442
443 r = dns_query_candidate_new(&c, q, s);
444 if (r < 0)
445 return r;
446
447 /* If this a single-label domain on DNS, we might append a suitable search domain first. */
448 if ((q->flags & SD_RESOLVED_NO_SEARCH) == 0) {
449 r = dns_scope_name_needs_search_domain(s, dns_question_first_name(q->question));
450 if (r < 0)
451 goto fail;
452 if (r > 0) {
453 /* OK, we need a search domain now. Let's find one for this scope */
454
455 r = dns_query_candidate_next_search_domain(c);
456 if (r <= 0) /* if there's no search domain, then we won't add any transaction. */
457 goto fail;
458 }
459 }
460
461 r = dns_query_candidate_setup_transactions(c);
462 if (r < 0)
463 goto fail;
464
465 return 0;
466
467 fail:
468 dns_query_candidate_free(c);
469 return r;
470 }
471
472 static int SYNTHESIZE_IFINDEX(int ifindex) {
473
474 /* When the caller asked for resolving on a specific
475 * interface, we synthesize the answer for that
476 * interface. However, if nothing specific was claimed and we
477 * only return localhost RRs, we synthesize the answer for
478 * localhost. */
479
480 if (ifindex > 0)
481 return ifindex;
482
483 return LOOPBACK_IFINDEX;
484 }
485
486 static int SYNTHESIZE_FAMILY(uint64_t flags) {
487
488 /* Picks an address family depending on set flags. This is
489 * purely for synthesized answers, where the family we return
490 * for the reply should match what was requested in the
491 * question, even though we are synthesizing the answer
492 * here. */
493
494 if (!(flags & SD_RESOLVED_DNS)) {
495 if (flags & SD_RESOLVED_LLMNR_IPV4)
496 return AF_INET;
497 if (flags & SD_RESOLVED_LLMNR_IPV6)
498 return AF_INET6;
499 }
500
501 return AF_UNSPEC;
502 }
503
504 static DnsProtocol SYNTHESIZE_PROTOCOL(uint64_t flags) {
505
506 /* Similar as SYNTHESIZE_FAMILY() but does this for the
507 * protocol. If resolving via DNS was requested, we claim it
508 * was DNS. Similar, if nothing specific was
509 * requested. However, if only resolving via LLMNR was
510 * requested we return that. */
511
512 if (flags & SD_RESOLVED_DNS)
513 return DNS_PROTOCOL_DNS;
514 if (flags & SD_RESOLVED_LLMNR)
515 return DNS_PROTOCOL_LLMNR;
516
517 return DNS_PROTOCOL_DNS;
518 }
519
520 static int dns_type_to_af(uint16_t t) {
521 switch (t) {
522
523 case DNS_TYPE_A:
524 return AF_INET;
525
526 case DNS_TYPE_AAAA:
527 return AF_INET6;
528
529 case DNS_TYPE_ANY:
530 return AF_UNSPEC;
531
532 default:
533 return -EINVAL;
534 }
535 }
536
537 static int synthesize_localhost_rr(DnsQuery *q, DnsResourceKey *key, DnsAnswer **answer) {
538 int r;
539
540 assert(q);
541 assert(key);
542 assert(answer);
543
544 r = dns_answer_reserve(answer, 2);
545 if (r < 0)
546 return r;
547
548 if (IN_SET(key->type, DNS_TYPE_A, DNS_TYPE_ANY)) {
549 _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
550
551 rr = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_A, DNS_RESOURCE_KEY_NAME(key));
552 if (!rr)
553 return -ENOMEM;
554
555 rr->a.in_addr.s_addr = htobe32(INADDR_LOOPBACK);
556
557 r = dns_answer_add(*answer, rr, SYNTHESIZE_IFINDEX(q->ifindex), DNS_ANSWER_AUTHENTICATED);
558 if (r < 0)
559 return r;
560 }
561
562 if (IN_SET(key->type, DNS_TYPE_AAAA, DNS_TYPE_ANY)) {
563 _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
564
565 rr = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_AAAA, DNS_RESOURCE_KEY_NAME(key));
566 if (!rr)
567 return -ENOMEM;
568
569 rr->aaaa.in6_addr = in6addr_loopback;
570
571 r = dns_answer_add(*answer, rr, SYNTHESIZE_IFINDEX(q->ifindex), DNS_ANSWER_AUTHENTICATED);
572 if (r < 0)
573 return r;
574 }
575
576 return 0;
577 }
578
579 static int answer_add_ptr(DnsAnswer **answer, const char *from, const char *to, int ifindex, DnsAnswerFlags flags) {
580 _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
581
582 rr = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_PTR, from);
583 if (!rr)
584 return -ENOMEM;
585
586 rr->ptr.name = strdup(to);
587 if (!rr->ptr.name)
588 return -ENOMEM;
589
590 return dns_answer_add(*answer, rr, ifindex, flags);
591 }
592
593 static int synthesize_localhost_ptr(DnsQuery *q, DnsResourceKey *key, DnsAnswer **answer) {
594 int r;
595
596 assert(q);
597 assert(key);
598 assert(answer);
599
600 if (IN_SET(key->type, DNS_TYPE_PTR, DNS_TYPE_ANY)) {
601 r = dns_answer_reserve(answer, 1);
602 if (r < 0)
603 return r;
604
605 r = answer_add_ptr(answer, DNS_RESOURCE_KEY_NAME(key), "localhost", SYNTHESIZE_IFINDEX(q->ifindex), DNS_ANSWER_AUTHENTICATED);
606 if (r < 0)
607 return r;
608 }
609
610 return 0;
611 }
612
613 static int answer_add_addresses_rr(
614 DnsAnswer **answer,
615 const char *name,
616 struct local_address *addresses,
617 unsigned n_addresses) {
618
619 unsigned j;
620 int r;
621
622 assert(answer);
623 assert(name);
624
625 r = dns_answer_reserve(answer, n_addresses);
626 if (r < 0)
627 return r;
628
629 for (j = 0; j < n_addresses; j++) {
630 _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
631
632 r = dns_resource_record_new_address(&rr, addresses[j].family, &addresses[j].address, name);
633 if (r < 0)
634 return r;
635
636 r = dns_answer_add(*answer, rr, addresses[j].ifindex, DNS_ANSWER_AUTHENTICATED);
637 if (r < 0)
638 return r;
639 }
640
641 return 0;
642 }
643
644 static int answer_add_addresses_ptr(
645 DnsAnswer **answer,
646 const char *name,
647 struct local_address *addresses,
648 unsigned n_addresses,
649 int af, const union in_addr_union *match) {
650
651 unsigned j;
652 int r;
653
654 assert(answer);
655 assert(name);
656
657 for (j = 0; j < n_addresses; j++) {
658 _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
659
660 if (af != AF_UNSPEC) {
661
662 if (addresses[j].family != af)
663 continue;
664
665 if (match && !in_addr_equal(af, match, &addresses[j].address))
666 continue;
667 }
668
669 r = dns_answer_reserve(answer, 1);
670 if (r < 0)
671 return r;
672
673 r = dns_resource_record_new_reverse(&rr, addresses[j].family, &addresses[j].address, name);
674 if (r < 0)
675 return r;
676
677 r = dns_answer_add(*answer, rr, addresses[j].ifindex, DNS_ANSWER_AUTHENTICATED);
678 if (r < 0)
679 return r;
680 }
681
682 return 0;
683 }
684
685 static int synthesize_system_hostname_rr(DnsQuery *q, DnsResourceKey *key, DnsAnswer **answer) {
686 _cleanup_free_ struct local_address *addresses = NULL;
687 int n = 0, af;
688
689 assert(q);
690 assert(key);
691 assert(answer);
692
693 af = dns_type_to_af(key->type);
694 if (af >= 0) {
695 n = local_addresses(q->manager->rtnl, q->ifindex, af, &addresses);
696 if (n < 0)
697 return n;
698
699 if (n == 0) {
700 struct local_address buffer[2];
701
702 /* If we have no local addresses then use ::1
703 * and 127.0.0.2 as local ones. */
704
705 if (af == AF_INET || af == AF_UNSPEC)
706 buffer[n++] = (struct local_address) {
707 .family = AF_INET,
708 .ifindex = SYNTHESIZE_IFINDEX(q->ifindex),
709 .address.in.s_addr = htobe32(0x7F000002),
710 };
711
712 if (af == AF_INET6 || af == AF_UNSPEC)
713 buffer[n++] = (struct local_address) {
714 .family = AF_INET6,
715 .ifindex = SYNTHESIZE_IFINDEX(q->ifindex),
716 .address.in6 = in6addr_loopback,
717 };
718
719 return answer_add_addresses_rr(answer, DNS_RESOURCE_KEY_NAME(key), buffer, n);
720 }
721 }
722
723 return answer_add_addresses_rr(answer, DNS_RESOURCE_KEY_NAME(key), addresses, n);
724 }
725
726 static int synthesize_system_hostname_ptr(DnsQuery *q, int af, const union in_addr_union *address, DnsAnswer **answer) {
727 _cleanup_free_ struct local_address *addresses = NULL;
728 int n, r;
729
730 assert(q);
731 assert(address);
732 assert(answer);
733
734 if (af == AF_INET && address->in.s_addr == htobe32(0x7F000002)) {
735
736 /* Always map the IPv4 address 127.0.0.2 to the local
737 * hostname, in addition to "localhost": */
738
739 r = dns_answer_reserve(answer, 3);
740 if (r < 0)
741 return r;
742
743 r = answer_add_ptr(answer, "2.0.0.127.in-addr.arpa", q->manager->llmnr_hostname, SYNTHESIZE_IFINDEX(q->ifindex), DNS_ANSWER_AUTHENTICATED);
744 if (r < 0)
745 return r;
746
747 r = answer_add_ptr(answer, "2.0.0.127.in-addr.arpa", q->manager->mdns_hostname, SYNTHESIZE_IFINDEX(q->ifindex), DNS_ANSWER_AUTHENTICATED);
748 if (r < 0)
749 return r;
750
751 r = answer_add_ptr(answer, "2.0.0.127.in-addr.arpa", "localhost", SYNTHESIZE_IFINDEX(q->ifindex), DNS_ANSWER_AUTHENTICATED);
752 if (r < 0)
753 return r;
754
755 return 0;
756 }
757
758 n = local_addresses(q->manager->rtnl, q->ifindex, af, &addresses);
759 if (n < 0)
760 return n;
761
762 r = answer_add_addresses_ptr(answer, q->manager->llmnr_hostname, addresses, n, af, address);
763 if (r < 0)
764 return r;
765
766 return answer_add_addresses_ptr(answer, q->manager->mdns_hostname, addresses, n, af, address);
767 }
768
769 static int synthesize_gateway_rr(DnsQuery *q, DnsResourceKey *key, DnsAnswer **answer) {
770 _cleanup_free_ struct local_address *addresses = NULL;
771 int n = 0, af;
772
773 assert(q);
774 assert(key);
775 assert(answer);
776
777 af = dns_type_to_af(key->type);
778 if (af >= 0) {
779 n = local_gateways(q->manager->rtnl, q->ifindex, af, &addresses);
780 if (n < 0)
781 return n;
782 }
783
784 return answer_add_addresses_rr(answer, DNS_RESOURCE_KEY_NAME(key), addresses, n);
785 }
786
787 static int synthesize_gateway_ptr(DnsQuery *q, int af, const union in_addr_union *address, DnsAnswer **answer) {
788 _cleanup_free_ struct local_address *addresses = NULL;
789 int n;
790
791 assert(q);
792 assert(address);
793 assert(answer);
794
795 n = local_gateways(q->manager->rtnl, q->ifindex, af, &addresses);
796 if (n < 0)
797 return n;
798
799 return answer_add_addresses_ptr(answer, "gateway", addresses, n, af, address);
800 }
801
802 static int dns_query_synthesize_reply(DnsQuery *q, DnsTransactionState *state) {
803 _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL;
804 unsigned i;
805 int r;
806
807 assert(q);
808 assert(state);
809
810 /* Tries to synthesize localhost RR replies where appropriate */
811
812 if (!IN_SET(*state,
813 DNS_TRANSACTION_RCODE_FAILURE,
814 DNS_TRANSACTION_NO_SERVERS,
815 DNS_TRANSACTION_TIMEOUT,
816 DNS_TRANSACTION_ATTEMPTS_MAX_REACHED))
817 return 0;
818
819 for (i = 0; i < q->question->n_keys; i++) {
820 union in_addr_union address;
821 const char *name;
822 int af;
823
824 if (q->question->keys[i]->class != DNS_CLASS_IN &&
825 q->question->keys[i]->class != DNS_CLASS_ANY)
826 continue;
827
828 name = DNS_RESOURCE_KEY_NAME(q->question->keys[i]);
829
830 if (is_localhost(name)) {
831
832 r = synthesize_localhost_rr(q, q->question->keys[i], &answer);
833 if (r < 0)
834 return log_error_errno(r, "Failed to synthesize localhost RRs: %m");
835
836 } else if (manager_is_own_hostname(q->manager, name)) {
837
838 r = synthesize_system_hostname_rr(q, q->question->keys[i], &answer);
839 if (r < 0)
840 return log_error_errno(r, "Failed to synthesize system hostname RRs: %m");
841
842 } else if (is_gateway_hostname(name)) {
843
844 r = synthesize_gateway_rr(q, q->question->keys[i], &answer);
845 if (r < 0)
846 return log_error_errno(r, "Failed to synthesize gateway RRs: %m");
847
848 } else if ((dns_name_endswith(name, "127.in-addr.arpa") > 0 && dns_name_equal(name, "2.0.0.127.in-addr.arpa") == 0) ||
849 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) {
850
851 r = synthesize_localhost_ptr(q, q->question->keys[i], &answer);
852 if (r < 0)
853 return log_error_errno(r, "Failed to synthesize localhost PTR RRs: %m");
854
855 } else if (dns_name_address(name, &af, &address) > 0) {
856
857 r = synthesize_system_hostname_ptr(q, af, &address, &answer);
858 if (r < 0)
859 return log_error_errno(r, "Failed to synthesize system hostname PTR RR: %m");
860
861 r = synthesize_gateway_ptr(q, af, &address, &answer);
862 if (r < 0)
863 return log_error_errno(r, "Failed to synthesize gateway hostname PTR RR: %m");
864 }
865 }
866
867 if (!answer)
868 return 0;
869
870 dns_answer_unref(q->answer);
871 q->answer = answer;
872 answer = NULL;
873
874 q->answer_rcode = DNS_RCODE_SUCCESS;
875 q->answer_protocol = SYNTHESIZE_PROTOCOL(q->flags);
876 q->answer_family = SYNTHESIZE_FAMILY(q->flags);
877
878 *state = DNS_TRANSACTION_SUCCESS;
879
880 return 1;
881 }
882
883 int dns_query_go(DnsQuery *q) {
884 DnsScopeMatch found = DNS_SCOPE_NO;
885 DnsScope *s, *first = NULL;
886 DnsQueryCandidate *c;
887 const char *name;
888 int r;
889
890 assert(q);
891
892 if (q->state != DNS_TRANSACTION_NULL)
893 return 0;
894
895 assert(q->question);
896 assert(q->question->n_keys > 0);
897
898 name = dns_question_first_name(q->question);
899
900 LIST_FOREACH(scopes, s, q->manager->dns_scopes) {
901 DnsScopeMatch match;
902
903 match = dns_scope_good_domain(s, q->ifindex, q->flags, name);
904 if (match < 0)
905 return match;
906
907 if (match == DNS_SCOPE_NO)
908 continue;
909
910 found = match;
911
912 if (match == DNS_SCOPE_YES) {
913 first = s;
914 break;
915 } else {
916 assert(match == DNS_SCOPE_MAYBE);
917
918 if (!first)
919 first = s;
920 }
921 }
922
923 if (found == DNS_SCOPE_NO) {
924 DnsTransactionState state = DNS_TRANSACTION_NO_SERVERS;
925
926 dns_query_synthesize_reply(q, &state);
927 dns_query_complete(q, state);
928 return 1;
929 }
930
931 r = dns_query_add_candidate(q, first);
932 if (r < 0)
933 goto fail;
934
935 LIST_FOREACH(scopes, s, first->scopes_next) {
936 DnsScopeMatch match;
937
938 match = dns_scope_good_domain(s, q->ifindex, q->flags, name);
939 if (match < 0)
940 goto fail;
941
942 if (match != found)
943 continue;
944
945 r = dns_query_add_candidate(q, s);
946 if (r < 0)
947 goto fail;
948 }
949
950 q->answer = dns_answer_unref(q->answer);
951 q->answer_rcode = 0;
952 q->answer_family = AF_UNSPEC;
953 q->answer_protocol = _DNS_PROTOCOL_INVALID;
954
955 r = sd_event_add_time(
956 q->manager->event,
957 &q->timeout_event_source,
958 clock_boottime_or_monotonic(),
959 now(clock_boottime_or_monotonic()) + QUERY_TIMEOUT_USEC, 0,
960 on_query_timeout, q);
961 if (r < 0)
962 goto fail;
963
964 (void) sd_event_source_set_description(q->timeout_event_source, "query-timeout");
965
966 q->state = DNS_TRANSACTION_PENDING;
967 q->block_ready++;
968
969 /* Start the transactions */
970 LIST_FOREACH(candidates_by_query, c, q->candidates) {
971 r = dns_query_candidate_go(c);
972 if (r < 0) {
973 q->block_ready--;
974 goto fail;
975 }
976 }
977
978 q->block_ready--;
979 dns_query_ready(q);
980
981 return 1;
982
983 fail:
984 dns_query_stop(q);
985 return r;
986 }
987
988 static void dns_query_accept(DnsQuery *q, DnsQueryCandidate *c) {
989 DnsTransactionState state = DNS_TRANSACTION_NO_SERVERS;
990 bool has_authenticated = false, has_non_authenticated = false;
991 DnssecResult dnssec_result_authenticated = _DNSSEC_RESULT_INVALID, dnssec_result_non_authenticated = _DNSSEC_RESULT_INVALID;
992 DnsTransaction *t;
993 Iterator i;
994 int r;
995
996 assert(q);
997
998 if (!c) {
999 dns_query_synthesize_reply(q, &state);
1000 dns_query_complete(q, state);
1001 return;
1002 }
1003
1004 SET_FOREACH(t, c->transactions, i) {
1005
1006 switch (t->state) {
1007
1008 case DNS_TRANSACTION_SUCCESS: {
1009 /* We found a successfuly reply, merge it into the answer */
1010 r = dns_answer_extend(&q->answer, t->answer);
1011 if (r < 0) {
1012 dns_query_complete(q, DNS_TRANSACTION_RESOURCES);
1013 return;
1014 }
1015
1016 q->answer_rcode = t->answer_rcode;
1017
1018 if (t->answer_authenticated) {
1019 has_authenticated = true;
1020 dnssec_result_authenticated = t->answer_dnssec_result;
1021 } else {
1022 has_non_authenticated = true;
1023 dnssec_result_non_authenticated = t->answer_dnssec_result;
1024 }
1025
1026 state = DNS_TRANSACTION_SUCCESS;
1027 break;
1028 }
1029
1030 case DNS_TRANSACTION_NULL:
1031 case DNS_TRANSACTION_PENDING:
1032 case DNS_TRANSACTION_VALIDATING:
1033 case DNS_TRANSACTION_ABORTED:
1034 /* Ignore transactions that didn't complete */
1035 continue;
1036
1037 default:
1038 /* Any kind of failure? Store the data away,
1039 * if there's nothing stored yet. */
1040
1041 if (state == DNS_TRANSACTION_SUCCESS)
1042 continue;
1043
1044 q->answer = dns_answer_unref(q->answer);
1045 q->answer_rcode = t->answer_rcode;
1046 q->answer_dnssec_result = t->answer_dnssec_result;
1047
1048 state = t->state;
1049 break;
1050 }
1051 }
1052
1053 if (state == DNS_TRANSACTION_SUCCESS) {
1054 q->answer_authenticated = has_authenticated && !has_non_authenticated;
1055 q->answer_dnssec_result = q->answer_authenticated ? dnssec_result_authenticated : dnssec_result_non_authenticated;
1056 }
1057
1058 q->answer_protocol = c->scope->protocol;
1059 q->answer_family = c->scope->family;
1060
1061 dns_search_domain_unref(q->answer_search_domain);
1062 q->answer_search_domain = dns_search_domain_ref(c->search_domain);
1063
1064 dns_query_synthesize_reply(q, &state);
1065 dns_query_complete(q, state);
1066 }
1067
1068 void dns_query_ready(DnsQuery *q) {
1069
1070 DnsQueryCandidate *bad = NULL, *c;
1071 bool pending = false;
1072
1073 assert(q);
1074 assert(DNS_TRANSACTION_IS_LIVE(q->state));
1075
1076 /* Note that this call might invalidate the query. Callers
1077 * should hence not attempt to access the query or transaction
1078 * after calling this function, unless the block_ready
1079 * counter was explicitly bumped before doing so. */
1080
1081 if (q->block_ready > 0)
1082 return;
1083
1084 LIST_FOREACH(candidates_by_query, c, q->candidates) {
1085 DnsTransactionState state;
1086
1087 state = dns_query_candidate_state(c);
1088 switch (state) {
1089
1090 case DNS_TRANSACTION_SUCCESS:
1091 /* One of the candidates is successful,
1092 * let's use it, and copy its data out */
1093 dns_query_accept(q, c);
1094 return;
1095
1096 case DNS_TRANSACTION_NULL:
1097 case DNS_TRANSACTION_PENDING:
1098 case DNS_TRANSACTION_VALIDATING:
1099 /* One of the candidates is still going on,
1100 * let's maybe wait for it */
1101 pending = true;
1102 break;
1103
1104 default:
1105 /* Any kind of failure */
1106 bad = c;
1107 break;
1108 }
1109 }
1110
1111 if (pending)
1112 return;
1113
1114 dns_query_accept(q, bad);
1115 }
1116
1117 static int dns_query_cname_redirect(DnsQuery *q, const DnsResourceRecord *cname) {
1118 _cleanup_(dns_question_unrefp) DnsQuestion *nq = NULL;
1119 int r;
1120
1121 assert(q);
1122
1123 q->n_cname_redirects ++;
1124 if (q->n_cname_redirects > CNAME_MAX)
1125 return -ELOOP;
1126
1127 r = dns_question_cname_redirect(q->question, cname, &nq);
1128 if (r < 0)
1129 return r;
1130
1131 log_debug("Following CNAME/DNAME %s → %s", dns_question_first_name(q->question), dns_question_first_name(nq));
1132
1133 dns_question_unref(q->question);
1134 q->question = nq;
1135 nq = NULL;
1136
1137 dns_query_stop(q);
1138 q->state = DNS_TRANSACTION_NULL;
1139
1140 return 0;
1141 }
1142
1143 int dns_query_process_cname(DnsQuery *q) {
1144 _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *cname = NULL;
1145 DnsResourceRecord *rr;
1146 int r;
1147
1148 assert(q);
1149
1150 if (!IN_SET(q->state, DNS_TRANSACTION_SUCCESS, DNS_TRANSACTION_NULL))
1151 return DNS_QUERY_NOMATCH;
1152
1153 DNS_ANSWER_FOREACH(rr, q->answer) {
1154
1155 r = dns_question_matches_rr(q->question, rr, DNS_SEARCH_DOMAIN_NAME(q->answer_search_domain));
1156 if (r < 0)
1157 return r;
1158 if (r > 0)
1159 return DNS_QUERY_MATCH; /* The answer matches directly, no need to follow cnames */
1160
1161 r = dns_question_matches_cname(q->question, rr, DNS_SEARCH_DOMAIN_NAME(q->answer_search_domain));
1162 if (r < 0)
1163 return r;
1164 if (r > 0 && !cname)
1165 cname = dns_resource_record_ref(rr);
1166 }
1167
1168 if (!cname)
1169 return DNS_QUERY_NOMATCH; /* No match and no cname to follow */
1170
1171 if (q->flags & SD_RESOLVED_NO_CNAME)
1172 return -ELOOP;
1173
1174 /* OK, let's actually follow the CNAME */
1175 r = dns_query_cname_redirect(q, cname);
1176 if (r < 0)
1177 return r;
1178
1179 /* Let's see if the answer can already answer the new
1180 * redirected question */
1181 r = dns_query_process_cname(q);
1182 if (r != DNS_QUERY_NOMATCH)
1183 return r;
1184
1185 /* OK, it cannot, let's begin with the new query */
1186 r = dns_query_go(q);
1187 if (r < 0)
1188 return r;
1189
1190 return DNS_QUERY_RESTARTED; /* We restarted the query for a new cname */
1191 }
1192
1193 static int on_bus_track(sd_bus_track *t, void *userdata) {
1194 DnsQuery *q = userdata;
1195
1196 assert(t);
1197 assert(q);
1198
1199 log_debug("Client of active query vanished, aborting query.");
1200 dns_query_complete(q, DNS_TRANSACTION_ABORTED);
1201 return 0;
1202 }
1203
1204 int dns_query_bus_track(DnsQuery *q, sd_bus_message *m) {
1205 int r;
1206
1207 assert(q);
1208 assert(m);
1209
1210 if (!q->bus_track) {
1211 r = sd_bus_track_new(sd_bus_message_get_bus(m), &q->bus_track, on_bus_track, q);
1212 if (r < 0)
1213 return r;
1214 }
1215
1216 r = sd_bus_track_add_sender(q->bus_track, m);
1217 if (r < 0)
1218 return r;
1219
1220 return 0;
1221 }