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/>.
24 #include "resolved-dns-query.h"
25 #include "resolved-dns-domain.h"
27 #define TRANSACTION_TIMEOUT_USEC (5 * USEC_PER_SEC)
28 #define QUERY_TIMEOUT_USEC (30 * USEC_PER_SEC)
29 #define ATTEMPTS_MAX 8
31 #define QUERIES_MAX 2048
33 static int dns_query_transaction_go(DnsQueryTransaction *t);
35 DnsQueryTransaction* dns_query_transaction_free(DnsQueryTransaction *t) {
41 sd_event_source_unref(t->timeout_event_source);
43 dns_question_unref(t->question);
44 dns_packet_unref(t->sent);
45 dns_packet_unref(t->received);
46 dns_answer_unref(t->cached);
48 dns_stream_free(t->stream);
51 LIST_REMOVE(transactions_by_scope, t->scope->transactions, t);
54 hashmap_remove(t->scope->manager->dns_query_transactions, UINT_TO_PTR(t->id));
57 while ((q = set_steal_first(t->queries)))
58 set_remove(q->transactions, t);
66 DEFINE_TRIVIAL_CLEANUP_FUNC(DnsQueryTransaction*, dns_query_transaction_free);
68 static void dns_query_transaction_gc(DnsQueryTransaction *t) {
74 if (set_isempty(t->queries))
75 dns_query_transaction_free(t);
78 static int dns_query_transaction_new(DnsQueryTransaction **ret, DnsScope *s, DnsQuestion *q) {
79 _cleanup_(dns_query_transaction_freep) DnsQueryTransaction *t = NULL;
86 r = hashmap_ensure_allocated(&s->manager->dns_query_transactions, NULL, NULL);
90 t = new0(DnsQueryTransaction, 1);
94 t->question = dns_question_ref(q);
97 random_bytes(&t->id, sizeof(t->id));
99 hashmap_get(s->manager->dns_query_transactions, UINT_TO_PTR(t->id)));
101 r = hashmap_put(s->manager->dns_query_transactions, UINT_TO_PTR(t->id), t);
107 LIST_PREPEND(transactions_by_scope, s->transactions, t);
118 static void dns_query_transaction_stop(DnsQueryTransaction *t) {
121 t->timeout_event_source = sd_event_source_unref(t->timeout_event_source);
122 t->stream = dns_stream_free(t->stream);
125 void dns_query_transaction_complete(DnsQueryTransaction *t, DnsQueryState state) {
130 assert(!IN_SET(state, DNS_QUERY_NULL, DNS_QUERY_PENDING));
131 assert(IN_SET(t->state, DNS_QUERY_NULL, DNS_QUERY_PENDING));
133 /* Note that this call might invalidate the query. Callers
134 * should hence not attempt to access the query or transaction
135 * after calling this function. */
137 log_debug("Transaction on scope %s on %s/%s now complete with %s",
138 dns_protocol_to_string(t->scope->protocol),
139 t->scope->link ? t->scope->link->name : "*",
140 t->scope->family == AF_UNSPEC ? "*" : af_to_name(t->scope->family),
141 dns_query_state_to_string(state));
145 dns_query_transaction_stop(t);
147 /* Notify all queries that are interested, but make sure the
148 * transaction isn't freed while we are still looking at it */
150 SET_FOREACH(q, t->queries, i)
154 dns_query_transaction_gc(t);
157 static int on_stream_complete(DnsStream *s, int error) {
158 _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
159 DnsQueryTransaction *t;
162 assert(s->transaction);
164 /* Copy the data we care about out of the stream before we
167 p = dns_packet_ref(s->read_packet);
169 t->stream = dns_stream_free(t->stream);
172 dns_query_transaction_complete(t, DNS_QUERY_RESOURCES);
177 dns_query_transaction_process_reply(t, p);
180 /* If the response wasn't useful, then complete the transition now */
181 if (t->state == DNS_QUERY_PENDING)
182 dns_query_transaction_complete(t, DNS_QUERY_INVALID_REPLY);
187 static int dns_query_transaction_open_tcp(DnsQueryTransaction *t) {
188 _cleanup_close_ int fd = -1;
196 if (t->scope->protocol == DNS_PROTOCOL_DNS)
197 fd = dns_scope_tcp_socket(t->scope, AF_UNSPEC, NULL, 53);
198 else if (t->scope->protocol == DNS_PROTOCOL_LLMNR) {
200 /* When we already received a query to this (but it was truncated), send to its sender address */
202 fd = dns_scope_tcp_socket(t->scope, t->received->family, &t->received->sender, t->received->sender_port);
204 union in_addr_union address;
207 /* Otherwise, try to talk to the owner of a
208 * the IP address, in case this is a reverse
210 r = dns_question_extract_reverse_address(t->question, &family, &address);
216 fd = dns_scope_tcp_socket(t->scope, family, &address, 5355);
219 return -EAFNOSUPPORT;
224 r = dns_stream_new(t->scope->manager, &t->stream, t->scope->protocol, fd);
230 r = dns_stream_write_packet(t->stream, t->sent);
232 t->stream = dns_stream_free(t->stream);
236 t->received = dns_packet_unref(t->received);
237 t->stream->complete = on_stream_complete;
238 t->stream->transaction = t;
240 /* The interface index is difficult to determine if we are
241 * connecting to the local host, hence fill this in right away
242 * instead of determining it from the socket */
244 t->stream->ifindex = t->scope->link->ifindex;
249 void dns_query_transaction_process_reply(DnsQueryTransaction *t, DnsPacket *p) {
254 assert(t->state == DNS_QUERY_PENDING);
256 /* Note that this call might invalidate the query. Callers
257 * should hence not attempt to access the query or transaction
258 * after calling this function. */
260 if (t->scope->protocol == DNS_PROTOCOL_LLMNR) {
261 assert(t->scope->link);
263 /* For LLMNR we will not accept any packets from other
266 if (p->ifindex != t->scope->link->ifindex)
269 if (p->family != t->scope->family)
272 /* Tentative replies shall be discarded, see RFC 4795,
279 if (t->scope->protocol == DNS_PROTOCOL_DNS) {
281 /* For DNS we are fine with accepting packets on any
282 * interface, but the source IP address must be one of
283 * a valid DNS server */
285 if (!dns_scope_good_dns_server(t->scope, p->family, &p->sender))
288 if (p->sender_port != 53)
292 if (t->received != p) {
293 dns_packet_unref(t->received);
294 t->received = dns_packet_ref(p);
297 if (p->ipproto == IPPROTO_TCP) {
298 if (DNS_PACKET_TC(p)) {
299 /* Truncated via TCP? Somebody must be fucking with us */
300 dns_query_transaction_complete(t, DNS_QUERY_INVALID_REPLY);
304 if (DNS_PACKET_ID(p) != t->id) {
305 /* Not the reply to our query? Somebody must be fucking with us */
306 dns_query_transaction_complete(t, DNS_QUERY_INVALID_REPLY);
311 if (DNS_PACKET_TC(p)) {
312 /* Response was truncated, let's try again with good old TCP */
313 r = dns_query_transaction_open_tcp(t);
315 /* No servers found? Damn! */
316 dns_query_transaction_complete(t, DNS_QUERY_NO_SERVERS);
320 /* On LLMNR, if we cannot connect to the host,
321 * we immediately give up */
322 if (t->scope->protocol == DNS_PROTOCOL_LLMNR) {
323 dns_query_transaction_complete(t, DNS_QUERY_RESOURCES);
327 /* On DNS, couldn't send? Try immediately 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);
340 /* Parse and update the cache */
341 r = dns_packet_extract(p);
343 dns_query_transaction_complete(t, DNS_QUERY_INVALID_REPLY);
347 dns_cache_put(&t->scope->cache, p->question, DNS_PACKET_RCODE(p), p->answer, 0);
349 if (DNS_PACKET_RCODE(p) == DNS_RCODE_SUCCESS)
350 dns_query_transaction_complete(t, DNS_QUERY_SUCCESS);
352 dns_query_transaction_complete(t, DNS_QUERY_FAILURE);
355 static int on_transaction_timeout(sd_event_source *s, usec_t usec, void *userdata) {
356 DnsQueryTransaction *t = userdata;
362 /* Timeout reached? Try again, with a new server */
363 dns_scope_next_dns_server(t->scope);
365 r = dns_query_transaction_go(t);
367 dns_query_transaction_complete(t, DNS_QUERY_RESOURCES);
372 static int dns_query_make_packet(DnsQueryTransaction *t) {
373 _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
374 unsigned n, added = 0;
382 r = dns_packet_new_query(&p, t->scope->protocol, 0);
386 for (n = 0; n < t->question->n_keys; n++) {
387 r = dns_scope_good_key(t->scope, t->question->keys[n]);
393 r = dns_packet_append_key(p, t->question->keys[n], NULL);
403 DNS_PACKET_HEADER(p)->qdcount = htobe16(added);
404 DNS_PACKET_HEADER(p)->id = t->id;
412 static int dns_query_transaction_go(DnsQueryTransaction *t) {
417 dns_query_transaction_stop(t);
419 log_debug("Beginning transaction on scope %s on %s/%s",
420 dns_protocol_to_string(t->scope->protocol),
421 t->scope->link ? t->scope->link->name : "*",
422 t->scope->family == AF_UNSPEC ? "*" : af_to_name(t->scope->family));
424 if (t->n_attempts >= ATTEMPTS_MAX) {
425 dns_query_transaction_complete(t, DNS_QUERY_ATTEMPTS_MAX);
430 t->received = dns_packet_unref(t->received);
431 t->cached = dns_answer_unref(t->cached);
434 /* First, let's try the cache */
435 dns_cache_prune(&t->scope->cache);
436 r = dns_cache_lookup(&t->scope->cache, t->question, &t->cached_rcode, &t->cached);
440 if (t->cached_rcode == DNS_RCODE_SUCCESS)
441 dns_query_transaction_complete(t, DNS_QUERY_SUCCESS);
443 dns_query_transaction_complete(t, DNS_QUERY_FAILURE);
447 /* Otherwise, we need to ask the network */
448 r = dns_query_make_packet(t);
450 /* Not the right request to make on this network?
451 * (i.e. an A request made on IPv6 or an AAAA request
452 * made on IPv4, on LLMNR or mDNS.) */
453 dns_query_transaction_complete(t, DNS_QUERY_NO_SERVERS);
459 if (t->scope->protocol == DNS_PROTOCOL_LLMNR &&
460 (dns_question_endswith(t->question, "in-addr.arpa") > 0 ||
461 dns_question_endswith(t->question, "ip6.arpa") > 0)) {
463 /* RFC 4795, Section 2.4. says reverse lookups shall
464 * always be made via TCP on LLMNR */
465 r = dns_query_transaction_open_tcp(t);
467 /* Try via UDP, and if that fails due to large size try via TCP */
468 r = dns_scope_send(t->scope, t->sent);
470 r = dns_query_transaction_open_tcp(t);
473 /* No servers to send this to? */
474 dns_query_transaction_complete(t, DNS_QUERY_NO_SERVERS);
478 /* Couldn't send? Try immediately again, with a new server */
479 dns_scope_next_dns_server(t->scope);
481 return dns_query_transaction_go(t);
484 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);
488 t->state = DNS_QUERY_PENDING;
492 DnsQuery *dns_query_free(DnsQuery *q) {
493 DnsQueryTransaction *t;
498 sd_bus_message_unref(q->request);
500 dns_question_unref(q->question);
501 dns_answer_unref(q->answer);
503 sd_event_source_unref(q->timeout_event_source);
505 while ((t = set_steal_first(q->transactions))) {
506 set_remove(t->queries, q);
507 dns_query_transaction_gc(t);
510 set_free(q->transactions);
513 LIST_REMOVE(queries, q->manager->dns_queries, q);
514 q->manager->n_dns_queries--;
522 int dns_query_new(Manager *m, DnsQuery **ret, DnsQuestion *question) {
523 _cleanup_(dns_query_freep) DnsQuery *q = NULL;
530 r = dns_question_is_valid(question);
534 if (m->n_dns_queries >= QUERIES_MAX)
537 q = new0(DnsQuery, 1);
541 q->question = dns_question_ref(question);
543 for (i = 0; i < question->n_keys; i++) {
544 log_debug("Looking up RR for %s %s %s",
545 strna(dns_class_to_string(question->keys[i]->class)),
546 strna(dns_type_to_string(question->keys[i]->type)),
547 DNS_RESOURCE_KEY_NAME(question->keys[i]));
550 LIST_PREPEND(queries, m->dns_queries, q);
561 static void dns_query_stop(DnsQuery *q) {
562 DnsQueryTransaction *t;
566 q->timeout_event_source = sd_event_source_unref(q->timeout_event_source);
568 while ((t = set_steal_first(q->transactions))) {
569 set_remove(t->queries, q);
570 dns_query_transaction_gc(t);
574 static void dns_query_complete(DnsQuery *q, DnsQueryState state) {
576 assert(!IN_SET(state, DNS_QUERY_NULL, DNS_QUERY_PENDING));
577 assert(IN_SET(q->state, DNS_QUERY_NULL, DNS_QUERY_PENDING));
579 /* Note that this call might invalidate the query. Callers
580 * should hence not attempt to access the query or transaction
581 * after calling this function. */
590 static int on_query_timeout(sd_event_source *s, usec_t usec, void *userdata) {
591 DnsQuery *q = userdata;
596 dns_query_complete(q, DNS_QUERY_TIMEOUT);
600 static int dns_query_add_transaction(DnsQuery *q, DnsScope *s, DnsResourceKey *key) {
601 _cleanup_(dns_question_unrefp) DnsQuestion *question = NULL;
602 DnsQueryTransaction *t;
607 r = set_ensure_allocated(&q->transactions, NULL, NULL);
612 question = dns_question_new(1);
616 r = dns_question_add(question, key);
620 question = dns_question_ref(q->question);
622 LIST_FOREACH(transactions_by_scope, t, s->transactions)
623 if (dns_question_is_superset(t->question, question))
627 r = dns_query_transaction_new(&t, s, question);
632 r = set_ensure_allocated(&t->queries, NULL, NULL);
636 r = set_put(t->queries, q);
640 r = set_put(q->transactions, t);
642 set_remove(t->queries, q);
649 dns_query_transaction_gc(t);
653 static int dns_query_add_transaction_split(DnsQuery *q, DnsScope *s) {
659 if (s->protocol == DNS_PROTOCOL_MDNS) {
660 r = dns_query_add_transaction(q, s, NULL);
666 /* On DNS and LLMNR we can only send a single
667 * question per datagram, hence issue multiple
670 for (i = 0; i < q->question->n_keys; i++) {
671 r = dns_query_add_transaction(q, s, q->question->keys[i]);
680 int dns_query_go(DnsQuery *q) {
681 DnsScopeMatch found = DNS_SCOPE_NO;
682 DnsScope *s, *first = NULL;
683 DnsQueryTransaction *t;
690 if (q->state != DNS_QUERY_NULL)
694 assert(q->question->n_keys > 0);
696 name = DNS_RESOURCE_KEY_NAME(q->question->keys[0]);
698 LIST_FOREACH(scopes, s, q->manager->dns_scopes) {
701 match = dns_scope_good_domain(s, name);
705 if (match == DNS_SCOPE_NO)
710 if (match == DNS_SCOPE_YES) {
714 assert(match == DNS_SCOPE_MAYBE);
721 if (found == DNS_SCOPE_NO)
724 r = dns_query_add_transaction_split(q, first);
728 LIST_FOREACH(scopes, s, first->scopes_next) {
731 match = dns_scope_good_domain(s, name);
738 r = dns_query_add_transaction_split(q, s);
743 q->answer = dns_answer_unref(q->answer);
744 q->answer_ifindex = 0;
747 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);
751 q->state = DNS_QUERY_PENDING;
754 SET_FOREACH(t, q->transactions, i) {
755 if (t->state == DNS_QUERY_NULL) {
756 r = dns_query_transaction_go(t);
772 void dns_query_ready(DnsQuery *q) {
773 DnsQueryTransaction *t;
774 DnsQueryState state = DNS_QUERY_NO_SERVERS;
775 _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL;
777 DnsScope *scope = NULL;
781 assert(IN_SET(q->state, DNS_QUERY_NULL, DNS_QUERY_PENDING));
783 /* Note that this call might invalidate the query. Callers
784 * should hence not attempt to access the query or transaction
785 * after calling this function, unless the block_ready
786 * counter was explicitly bumped before doing so. */
788 if (q->block_ready > 0)
791 SET_FOREACH(t, q->transactions, i) {
793 /* If we found a successful answer, ignore all answers from other scopes */
794 if (state == DNS_QUERY_SUCCESS && t->scope != scope)
797 /* One of the transactions is still going on, let's wait for it */
798 if (t->state == DNS_QUERY_PENDING || t->state == DNS_QUERY_NULL)
801 /* One of the transactions is successful, let's use
802 * it, and copy its data out */
803 if (t->state == DNS_QUERY_SUCCESS) {
807 rcode = DNS_PACKET_RCODE(t->received);
808 a = t->received->answer;
810 rcode = t->cached_rcode;
814 if (state == DNS_QUERY_SUCCESS) {
817 merged = dns_answer_merge(answer, a);
819 dns_query_complete(q, DNS_QUERY_RESOURCES);
823 dns_answer_unref(answer);
826 dns_answer_unref(answer);
827 answer = dns_answer_ref(a);
831 state = DNS_QUERY_SUCCESS;
835 /* One of the transactions has failed, let's see
836 * whether we find anything better, but if not, return
837 * its response data */
838 if (state != DNS_QUERY_SUCCESS && t->state == DNS_QUERY_FAILURE) {
842 rcode = DNS_PACKET_RCODE(t->received);
843 a = t->received->answer;
845 rcode = t->cached_rcode;
849 dns_answer_unref(answer);
850 answer = dns_answer_ref(a);
853 state = DNS_QUERY_FAILURE;
857 if (state == DNS_QUERY_NO_SERVERS && t->state != DNS_QUERY_NO_SERVERS)
861 if (IN_SET(state, DNS_QUERY_SUCCESS, DNS_QUERY_FAILURE)) {
862 q->answer = dns_answer_ref(answer);
863 q->answer_rcode = rcode;
864 q->answer_ifindex = (scope && scope->link) ? scope->link->ifindex : 0;
867 dns_query_complete(q, state);
870 int dns_query_cname_redirect(DnsQuery *q, const char *name) {
871 _cleanup_(dns_question_unrefp) DnsQuestion *nq = NULL;
876 if (q->n_cname_redirects > CNAME_MAX)
879 r = dns_question_cname_redirect(q->question, name, &nq);
883 dns_question_unref(q->question);
887 q->n_cname_redirects++;
890 q->state = DNS_QUERY_NULL;
895 static const char* const dns_query_state_table[_DNS_QUERY_STATE_MAX] = {
896 [DNS_QUERY_NULL] = "null",
897 [DNS_QUERY_PENDING] = "pending",
898 [DNS_QUERY_FAILURE] = "failure",
899 [DNS_QUERY_SUCCESS] = "success",
900 [DNS_QUERY_NO_SERVERS] = "no-servers",
901 [DNS_QUERY_TIMEOUT] = "timeout",
902 [DNS_QUERY_ATTEMPTS_MAX] = "attempts-max",
903 [DNS_QUERY_INVALID_REPLY] = "invalid-reply",
904 [DNS_QUERY_RESOURCES] = "resources",
905 [DNS_QUERY_ABORTED] = "aborted",
907 DEFINE_STRING_TABLE_LOOKUP(dns_query_state, DnsQueryState);