1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2014 Lennart Poettering
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.
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.
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/>.
22 #include "resolved-dns-query.h"
23 #include "resolved-dns-domain.h"
25 #define TRANSACTION_TIMEOUT_USEC (5 * USEC_PER_SEC)
26 #define QUERY_TIMEOUT_USEC (30 * USEC_PER_SEC)
27 #define ATTEMPTS_MAX 8
29 #define QUERIES_MAX 2048
31 static int dns_query_transaction_go(DnsQueryTransaction *t);
33 DnsQueryTransaction* dns_query_transaction_free(DnsQueryTransaction *t) {
39 sd_event_source_unref(t->timeout_event_source);
41 dns_question_unref(t->question);
42 dns_packet_unref(t->sent);
43 dns_packet_unref(t->received);
44 dns_answer_unref(t->cached);
46 dns_stream_free(t->stream);
49 LIST_REMOVE(transactions_by_scope, t->scope->transactions, t);
52 hashmap_remove(t->scope->manager->dns_query_transactions, UINT_TO_PTR(t->id));
55 while ((q = set_steal_first(t->queries)))
56 set_remove(q->transactions, t);
64 DEFINE_TRIVIAL_CLEANUP_FUNC(DnsQueryTransaction*, dns_query_transaction_free);
66 static void dns_query_transaction_gc(DnsQueryTransaction *t) {
72 if (set_isempty(t->queries))
73 dns_query_transaction_free(t);
76 static int dns_query_transaction_new(DnsQueryTransaction **ret, DnsScope *s, DnsQuestion *q) {
77 _cleanup_(dns_query_transaction_freep) DnsQueryTransaction *t = NULL;
84 r = hashmap_ensure_allocated(&s->manager->dns_query_transactions, NULL, NULL);
88 t = new0(DnsQueryTransaction, 1);
92 t->question = dns_question_ref(q);
95 random_bytes(&t->id, sizeof(t->id));
97 hashmap_get(s->manager->dns_query_transactions, UINT_TO_PTR(t->id)));
99 r = hashmap_put(s->manager->dns_query_transactions, UINT_TO_PTR(t->id), t);
105 LIST_PREPEND(transactions_by_scope, s->transactions, t);
116 static void dns_query_transaction_stop(DnsQueryTransaction *t) {
119 t->timeout_event_source = sd_event_source_unref(t->timeout_event_source);
120 t->stream = dns_stream_free(t->stream);
123 void dns_query_transaction_complete(DnsQueryTransaction *t, DnsQueryState state) {
128 assert(!IN_SET(state, DNS_QUERY_NULL, DNS_QUERY_PENDING));
129 assert(IN_SET(t->state, DNS_QUERY_NULL, DNS_QUERY_PENDING));
131 /* Note that this call might invalidate the query. Callers
132 * should hence not attempt to access the query or transaction
133 * after calling this function. */
137 dns_query_transaction_stop(t);
139 /* Notify all queries that are interested, but make sure the
140 * transaction isn't freed while we are still looking at it */
142 SET_FOREACH(q, t->queries, i)
146 dns_query_transaction_gc(t);
149 static int on_stream_complete(DnsStream *s, int error) {
150 _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
151 DnsQueryTransaction *t;
154 assert(s->transaction);
156 /* Copy the data we care about out of the stream before we
159 p = dns_packet_ref(s->read_packet);
161 t->stream = dns_stream_free(t->stream);
164 dns_query_transaction_complete(t, DNS_QUERY_RESOURCES);
168 dns_query_transaction_process_reply(t, p);
172 static int dns_query_transaction_open_tcp(DnsQueryTransaction *t) {
173 _cleanup_close_ int fd = -1;
181 if (t->scope->protocol == DNS_PROTOCOL_DNS)
182 fd = dns_scope_tcp_socket(t->scope, AF_UNSPEC, NULL, 53);
183 else if (t->scope->protocol == DNS_PROTOCOL_LLMNR) {
187 fd = dns_scope_tcp_socket(t->scope, t->received->family, &t->received->sender, t->received->sender_port);
189 return -EAFNOSUPPORT;
194 r = dns_stream_new(t->scope->manager, &t->stream, t->scope->protocol, fd);
200 r = dns_stream_write_packet(t->stream, t->sent);
202 t->stream = dns_stream_free(t->stream);
206 t->received = dns_packet_unref(t->received);
207 t->stream->complete = on_stream_complete;
212 void dns_query_transaction_process_reply(DnsQueryTransaction *t, DnsPacket *p) {
217 assert(t->state == DNS_QUERY_PENDING);
219 /* Note that this call might invalidate the query. Callers
220 * should hence not attempt to access the query or transaction
221 * after calling this function. */
223 if (t->scope->protocol == DNS_PROTOCOL_LLMNR) {
224 assert(t->scope->link);
226 /* For LLMNR we will not accept any packets from other
229 if (p->ifindex != t->scope->link->ifindex)
232 if (p->family != t->scope->family)
235 if (p->ipproto == IPPROTO_UDP) {
236 if (p->family == AF_INET && !in_addr_equal(AF_INET, &p->destination, (union in_addr_union*) &LLMNR_MULTICAST_IPV4_ADDRESS))
239 if (p->family == AF_INET6 && !in_addr_equal(AF_INET6, &p->destination, (union in_addr_union*) &LLMNR_MULTICAST_IPV6_ADDRESS))
244 if (t->scope->protocol == DNS_PROTOCOL_DNS) {
246 /* For DNS we are fine with accepting packets on any
247 * interface, but the source IP address must be one of
248 * a valid DNS server */
250 if (!dns_scope_good_dns_server(t->scope, p->family, &p->sender))
253 if (p->sender_port != 53)
257 if (t->received != p) {
258 dns_packet_unref(t->received);
259 t->received = dns_packet_ref(p);
262 if (p->ipproto == IPPROTO_TCP) {
263 if (DNS_PACKET_TC(p)) {
264 /* Truncated via TCP? Somebody must be fucking with us */
265 dns_query_transaction_complete(t, DNS_QUERY_INVALID_REPLY);
269 if (DNS_PACKET_ID(p) != t->id) {
270 /* Not the reply to our query? Somebody must be fucking with us */
271 dns_query_transaction_complete(t, DNS_QUERY_INVALID_REPLY);
276 if (DNS_PACKET_TC(p)) {
277 /* Response was truncated, let's try again with good old TCP */
278 r = dns_query_transaction_open_tcp(t);
280 /* No servers found? Damn! */
281 dns_query_transaction_complete(t, DNS_QUERY_NO_SERVERS);
285 /* On LLMNR, if we cannot connect to the host,
286 * we immediately give up */
287 if (t->scope->protocol == DNS_PROTOCOL_LLMNR) {
288 dns_query_transaction_complete(t, DNS_QUERY_RESOURCES);
292 /* On DNS, couldn't send? Try immediately again, with a new server */
293 dns_scope_next_dns_server(t->scope);
295 r = dns_query_transaction_go(t);
297 dns_query_transaction_complete(t, DNS_QUERY_RESOURCES);
305 /* Parse and update the cache */
306 r = dns_packet_extract(p);
308 dns_query_transaction_complete(t, DNS_QUERY_INVALID_REPLY);
312 dns_cache_put(&t->scope->cache, p->question, DNS_PACKET_RCODE(p), p->answer, 0);
314 if (DNS_PACKET_RCODE(p) == DNS_RCODE_SUCCESS)
315 dns_query_transaction_complete(t, DNS_QUERY_SUCCESS);
317 dns_query_transaction_complete(t, DNS_QUERY_FAILURE);
320 static int on_transaction_timeout(sd_event_source *s, usec_t usec, void *userdata) {
321 DnsQueryTransaction *t = userdata;
327 /* Timeout reached? Try again, with a new server */
328 dns_scope_next_dns_server(t->scope);
330 r = dns_query_transaction_go(t);
332 dns_query_transaction_complete(t, DNS_QUERY_RESOURCES);
337 static int dns_query_make_packet(DnsQueryTransaction *t) {
338 _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
339 unsigned n, added = 0;
347 r = dns_packet_new_query(&p, t->scope->protocol, 0);
351 for (n = 0; n < t->question->n_keys; n++) {
352 r = dns_scope_good_key(t->scope, t->question->keys[n]);
358 r = dns_packet_append_key(p, t->question->keys[n], NULL);
368 DNS_PACKET_HEADER(p)->qdcount = htobe16(added);
369 DNS_PACKET_HEADER(p)->id = t->id;
377 static int dns_query_transaction_go(DnsQueryTransaction *t) {
382 dns_query_transaction_stop(t);
384 if (t->n_attempts >= ATTEMPTS_MAX) {
385 dns_query_transaction_complete(t, DNS_QUERY_ATTEMPTS_MAX);
390 t->received = dns_packet_unref(t->received);
391 t->cached = dns_answer_unref(t->cached);
394 /* First, let's try the cache */
395 dns_cache_prune(&t->scope->cache);
396 r = dns_cache_lookup(&t->scope->cache, t->question, &t->cached_rcode, &t->cached);
400 if (t->cached_rcode == DNS_RCODE_SUCCESS)
401 dns_query_transaction_complete(t, DNS_QUERY_SUCCESS);
403 dns_query_transaction_complete(t, DNS_QUERY_FAILURE);
407 /* Otherwise, we need to ask the network */
408 r = dns_query_make_packet(t);
410 /* Not the right request to make on this network?
411 * (i.e. an A request made on IPv6 or an AAAA request
412 * made on IPv4, on LLMNR or mDNS.) */
413 dns_query_transaction_complete(t, DNS_QUERY_NO_SERVERS);
419 /* Try via UDP, and if that fails due to large size try via TCP */
420 r = dns_scope_send(t->scope, t->sent);
422 r = dns_query_transaction_open_tcp(t);
424 /* No servers to send this to? */
425 dns_query_transaction_complete(t, DNS_QUERY_NO_SERVERS);
429 /* Couldn't send? Try immediately again, with a new server */
430 dns_scope_next_dns_server(t->scope);
432 return dns_query_transaction_go(t);
435 r = sd_event_add_time(t->scope->manager->event, &t->timeout_event_source, CLOCK_MONOTONIC, now(CLOCK_MONOTONIC) + TRANSACTION_TIMEOUT_USEC, 0, on_transaction_timeout, t);
439 t->state = DNS_QUERY_PENDING;
443 DnsQuery *dns_query_free(DnsQuery *q) {
444 DnsQueryTransaction *t;
449 sd_bus_message_unref(q->request);
451 dns_question_unref(q->question);
452 dns_answer_unref(q->answer);
454 sd_event_source_unref(q->timeout_event_source);
456 while ((t = set_steal_first(q->transactions))) {
457 set_remove(t->queries, q);
458 dns_query_transaction_gc(t);
461 set_free(q->transactions);
464 LIST_REMOVE(queries, q->manager->dns_queries, q);
465 q->manager->n_dns_queries--;
473 int dns_query_new(Manager *m, DnsQuery **ret, DnsQuestion *question) {
474 _cleanup_(dns_query_freep) DnsQuery *q = NULL;
481 r = dns_question_is_valid(question);
485 if (m->n_dns_queries >= QUERIES_MAX)
488 q = new0(DnsQuery, 1);
492 q->question = dns_question_ref(question);
494 for (i = 0; i < question->n_keys; i++) {
495 log_debug("Looking up RR for %s %s %s",
496 strna(dns_class_to_string(question->keys[i]->class)),
497 strna(dns_type_to_string(question->keys[i]->type)),
498 DNS_RESOURCE_KEY_NAME(question->keys[i]));
501 LIST_PREPEND(queries, m->dns_queries, q);
512 static void dns_query_stop(DnsQuery *q) {
513 DnsQueryTransaction *t;
517 q->timeout_event_source = sd_event_source_unref(q->timeout_event_source);
519 while ((t = set_steal_first(q->transactions))) {
520 set_remove(t->queries, q);
521 dns_query_transaction_gc(t);
525 static void dns_query_complete(DnsQuery *q, DnsQueryState state) {
527 assert(!IN_SET(state, DNS_QUERY_NULL, DNS_QUERY_PENDING));
528 assert(IN_SET(q->state, DNS_QUERY_NULL, DNS_QUERY_PENDING));
530 /* Note that this call might invalidate the query. Callers
531 * should hence not attempt to access the query or transaction
532 * after calling this function. */
541 static int on_query_timeout(sd_event_source *s, usec_t usec, void *userdata) {
542 DnsQuery *q = userdata;
547 dns_query_complete(q, DNS_QUERY_TIMEOUT);
551 static int dns_query_add_transaction(DnsQuery *q, DnsScope *s, DnsResourceKey *key) {
552 _cleanup_(dns_question_unrefp) DnsQuestion *question = NULL;
553 DnsQueryTransaction *t;
558 r = set_ensure_allocated(&q->transactions, NULL, NULL);
563 question = dns_question_new(1);
567 r = dns_question_add(question, key);
571 question = dns_question_ref(q->question);
573 LIST_FOREACH(transactions_by_scope, t, s->transactions)
574 if (dns_question_is_superset(t->question, question))
578 r = dns_query_transaction_new(&t, s, question);
583 r = set_ensure_allocated(&t->queries, NULL, NULL);
587 r = set_put(t->queries, q);
591 r = set_put(q->transactions, t);
593 set_remove(t->queries, q);
600 dns_query_transaction_gc(t);
604 static int dns_query_add_transaction_split(DnsQuery *q, DnsScope *s) {
610 if (s->protocol == DNS_PROTOCOL_MDNS) {
611 r = dns_query_add_transaction(q, s, NULL);
617 /* On DNS and LLMNR we can only send a single
618 * question per datagram, hence issue multiple
621 for (i = 0; i < q->question->n_keys; i++) {
622 r = dns_query_add_transaction(q, s, q->question->keys[i]);
631 int dns_query_go(DnsQuery *q) {
632 DnsScopeMatch found = DNS_SCOPE_NO;
633 DnsScope *s, *first = NULL;
634 DnsQueryTransaction *t;
641 if (q->state != DNS_QUERY_NULL)
645 assert(q->question->n_keys > 0);
647 name = DNS_RESOURCE_KEY_NAME(q->question->keys[0]);
649 LIST_FOREACH(scopes, s, q->manager->dns_scopes) {
652 match = dns_scope_good_domain(s, name);
656 if (match == DNS_SCOPE_NO)
661 if (match == DNS_SCOPE_YES) {
665 assert(match == DNS_SCOPE_MAYBE);
672 if (found == DNS_SCOPE_NO)
675 r = dns_query_add_transaction_split(q, first);
679 LIST_FOREACH(scopes, s, first->scopes_next) {
682 match = dns_scope_good_domain(s, name);
689 r = dns_query_add_transaction_split(q, s);
694 q->answer = dns_answer_unref(q->answer);
695 q->answer_ifindex = 0;
698 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);
702 q->state = DNS_QUERY_PENDING;
705 SET_FOREACH(t, q->transactions, i) {
706 if (t->state == DNS_QUERY_NULL) {
707 r = dns_query_transaction_go(t);
723 void dns_query_ready(DnsQuery *q) {
724 DnsQueryTransaction *t;
725 DnsQueryState state = DNS_QUERY_NO_SERVERS;
726 _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL;
728 DnsScope *scope = NULL;
732 assert(IN_SET(q->state, DNS_QUERY_NULL, DNS_QUERY_PENDING));
734 /* Note that this call might invalidate the query. Callers
735 * should hence not attempt to access the query or transaction
736 * after calling this function, unless the block_ready
737 * counter was explicitly bumped before doing so. */
739 if (q->block_ready > 0)
742 SET_FOREACH(t, q->transactions, i) {
744 /* If we found a successful answer, ignore all answers from other scopes */
745 if (state == DNS_QUERY_SUCCESS && t->scope != scope)
748 /* One of the transactions is still going on, let's wait for it */
749 if (t->state == DNS_QUERY_PENDING || t->state == DNS_QUERY_NULL)
752 /* One of the transactions is successful, let's use
753 * it, and copy its data out */
754 if (t->state == DNS_QUERY_SUCCESS) {
758 rcode = DNS_PACKET_RCODE(t->received);
759 a = t->received->answer;
761 rcode = t->cached_rcode;
765 if (state == DNS_QUERY_SUCCESS) {
768 merged = dns_answer_merge(answer, a);
770 dns_query_complete(q, DNS_QUERY_RESOURCES);
774 dns_answer_unref(answer);
777 dns_answer_unref(answer);
778 answer = dns_answer_ref(a);
782 state = DNS_QUERY_SUCCESS;
786 /* One of the transactions has failed, let's see
787 * whether we find anything better, but if not, return
788 * its response data */
789 if (state != DNS_QUERY_SUCCESS && t->state == DNS_QUERY_FAILURE) {
793 rcode = DNS_PACKET_RCODE(t->received);
794 a = t->received->answer;
796 rcode = t->cached_rcode;
800 dns_answer_unref(answer);
801 answer = dns_answer_ref(a);
804 state = DNS_QUERY_FAILURE;
808 if (state == DNS_QUERY_NO_SERVERS && t->state != DNS_QUERY_NO_SERVERS)
812 if (IN_SET(state, DNS_QUERY_SUCCESS, DNS_QUERY_FAILURE)) {
813 q->answer = dns_answer_ref(answer);
814 q->answer_rcode = rcode;
815 q->answer_ifindex = (scope && scope->link) ? scope->link->ifindex : 0;
818 dns_query_complete(q, state);
821 int dns_query_cname_redirect(DnsQuery *q, const char *name) {
822 _cleanup_(dns_question_unrefp) DnsQuestion *nq = NULL;
827 if (q->n_cname_redirects > CNAME_MAX)
830 r = dns_question_cname_redirect(q->question, name, &nq);
834 dns_question_unref(q->question);
838 q->n_cname_redirects++;
841 q->state = DNS_QUERY_NULL;