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