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 /* After how much time to repeat classic DNS requests */
28 #define DNS_TRANSACTION_TIMEOUT_USEC (5 * USEC_PER_SEC)
30 /* After how much time to repeat LLMNR requests, see RFC 4795 Section 7 */
31 #define LLMNR_TRANSACTION_TIMEOUT_USEC (1 * USEC_PER_SEC)
33 /* How long to wait for the query in total */
34 #define QUERY_TIMEOUT_USEC (30 * USEC_PER_SEC)
36 /* Maximum attempts to send DNS requests, across all DNS servers */
37 #define DNS_TRANSACTION_ATTEMPTS_MAX 8
39 /* Maximum attempts to send LLMNR requests, see RFC 4795 Section 2.7 */
40 #define LLMNR_TRANSACTION_ATTEMPTS_MAX 3
43 #define QUERIES_MAX 2048
45 #define TRANSACTION_TIMEOUT_USEC(p) ((t)->scope->protocol == DNS_PROTOCOL_LLMNR ? LLMNR_TRANSACTION_TIMEOUT_USEC : DNS_TRANSACTION_TIMEOUT_USEC)
46 #define TRANSACTION_ATTEMPTS_MAX(p) ((t)->scope->protocol == DNS_PROTOCOL_LLMNR ? LLMNR_TRANSACTION_ATTEMPTS_MAX : DNS_TRANSACTION_ATTEMPTS_MAX)
48 static int dns_query_transaction_go(DnsQueryTransaction *t);
50 DnsQueryTransaction* dns_query_transaction_free(DnsQueryTransaction *t) {
56 sd_event_source_unref(t->timeout_event_source);
58 dns_question_unref(t->question);
59 dns_packet_unref(t->sent);
60 dns_packet_unref(t->received);
61 dns_answer_unref(t->cached);
63 dns_stream_free(t->stream);
66 LIST_REMOVE(transactions_by_scope, t->scope->transactions, t);
69 hashmap_remove(t->scope->manager->dns_query_transactions, UINT_TO_PTR(t->id));
72 while ((q = set_steal_first(t->queries)))
73 set_remove(q->transactions, t);
81 DEFINE_TRIVIAL_CLEANUP_FUNC(DnsQueryTransaction*, dns_query_transaction_free);
83 static void dns_query_transaction_gc(DnsQueryTransaction *t) {
89 if (set_isempty(t->queries))
90 dns_query_transaction_free(t);
93 static int dns_query_transaction_new(DnsQueryTransaction **ret, DnsScope *s, DnsQuestion *q) {
94 _cleanup_(dns_query_transaction_freep) DnsQueryTransaction *t = NULL;
101 r = hashmap_ensure_allocated(&s->manager->dns_query_transactions, NULL, NULL);
105 t = new0(DnsQueryTransaction, 1);
109 t->question = dns_question_ref(q);
112 random_bytes(&t->id, sizeof(t->id));
114 hashmap_get(s->manager->dns_query_transactions, UINT_TO_PTR(t->id)));
116 r = hashmap_put(s->manager->dns_query_transactions, UINT_TO_PTR(t->id), t);
122 LIST_PREPEND(transactions_by_scope, s->transactions, t);
133 static void dns_query_transaction_stop(DnsQueryTransaction *t) {
136 t->timeout_event_source = sd_event_source_unref(t->timeout_event_source);
137 t->stream = dns_stream_free(t->stream);
140 void dns_query_transaction_complete(DnsQueryTransaction *t, DnsQueryState state) {
145 assert(!IN_SET(state, DNS_QUERY_NULL, DNS_QUERY_PENDING));
146 assert(IN_SET(t->state, DNS_QUERY_NULL, DNS_QUERY_PENDING));
148 /* Note that this call might invalidate the query. Callers
149 * should hence not attempt to access the query or transaction
150 * after calling this function. */
152 log_debug("Transaction on scope %s on %s/%s now complete with %s",
153 dns_protocol_to_string(t->scope->protocol),
154 t->scope->link ? t->scope->link->name : "*",
155 t->scope->family == AF_UNSPEC ? "*" : af_to_name(t->scope->family),
156 dns_query_state_to_string(state));
160 dns_query_transaction_stop(t);
162 /* Notify all queries that are interested, but make sure the
163 * transaction isn't freed while we are still looking at it */
165 SET_FOREACH(q, t->queries, i)
169 dns_query_transaction_gc(t);
172 static int on_stream_complete(DnsStream *s, int error) {
173 _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
174 DnsQueryTransaction *t;
177 assert(s->transaction);
179 /* Copy the data we care about out of the stream before we
182 p = dns_packet_ref(s->read_packet);
184 t->stream = dns_stream_free(t->stream);
187 dns_query_transaction_complete(t, DNS_QUERY_RESOURCES);
192 dns_query_transaction_process_reply(t, p);
195 /* If the response wasn't useful, then complete the transition now */
196 if (t->state == DNS_QUERY_PENDING)
197 dns_query_transaction_complete(t, DNS_QUERY_INVALID_REPLY);
202 static int dns_query_transaction_open_tcp(DnsQueryTransaction *t) {
203 _cleanup_close_ int fd = -1;
211 if (t->scope->protocol == DNS_PROTOCOL_DNS)
212 fd = dns_scope_tcp_socket(t->scope, AF_UNSPEC, NULL, 53);
213 else if (t->scope->protocol == DNS_PROTOCOL_LLMNR) {
215 /* When we already received a query to this (but it was truncated), send to its sender address */
217 fd = dns_scope_tcp_socket(t->scope, t->received->family, &t->received->sender, t->received->sender_port);
219 union in_addr_union address;
222 /* Otherwise, try to talk to the owner of a
223 * the IP address, in case this is a reverse
225 r = dns_question_extract_reverse_address(t->question, &family, &address);
231 fd = dns_scope_tcp_socket(t->scope, family, &address, 5355);
234 return -EAFNOSUPPORT;
239 r = dns_stream_new(t->scope->manager, &t->stream, t->scope->protocol, fd);
245 r = dns_stream_write_packet(t->stream, t->sent);
247 t->stream = dns_stream_free(t->stream);
251 t->received = dns_packet_unref(t->received);
252 t->stream->complete = on_stream_complete;
253 t->stream->transaction = t;
255 /* The interface index is difficult to determine if we are
256 * connecting to the local host, hence fill this in right away
257 * instead of determining it from the socket */
259 t->stream->ifindex = t->scope->link->ifindex;
264 void dns_query_transaction_process_reply(DnsQueryTransaction *t, DnsPacket *p) {
269 assert(t->state == DNS_QUERY_PENDING);
271 /* Note that this call might invalidate the query. Callers
272 * should hence not attempt to access the query or transaction
273 * after calling this function. */
275 if (t->scope->protocol == DNS_PROTOCOL_LLMNR) {
276 assert(t->scope->link);
278 /* For LLMNR we will not accept any packets from other
281 if (p->ifindex != t->scope->link->ifindex)
284 if (p->family != t->scope->family)
287 /* Tentative replies shall be discarded, see RFC 4795,
294 if (t->scope->protocol == DNS_PROTOCOL_DNS) {
296 /* For DNS we are fine with accepting packets on any
297 * interface, but the source IP address must be one of
298 * a valid DNS server */
300 if (!dns_scope_good_dns_server(t->scope, p->family, &p->sender))
303 if (p->sender_port != 53)
307 if (t->received != p) {
308 dns_packet_unref(t->received);
309 t->received = dns_packet_ref(p);
312 if (p->ipproto == IPPROTO_TCP) {
313 if (DNS_PACKET_TC(p)) {
314 /* Truncated via TCP? Somebody must be fucking with us */
315 dns_query_transaction_complete(t, DNS_QUERY_INVALID_REPLY);
319 if (DNS_PACKET_ID(p) != t->id) {
320 /* Not the reply to our query? Somebody must be fucking with us */
321 dns_query_transaction_complete(t, DNS_QUERY_INVALID_REPLY);
326 if (DNS_PACKET_TC(p)) {
327 /* Response was truncated, let's try again with good old TCP */
328 r = dns_query_transaction_open_tcp(t);
330 /* No servers found? Damn! */
331 dns_query_transaction_complete(t, DNS_QUERY_NO_SERVERS);
335 /* On LLMNR, if we cannot connect to the host,
336 * we immediately give up */
337 if (t->scope->protocol == DNS_PROTOCOL_LLMNR) {
338 dns_query_transaction_complete(t, DNS_QUERY_RESOURCES);
342 /* On DNS, couldn't send? Try immediately again, with a new server */
343 dns_scope_next_dns_server(t->scope);
345 r = dns_query_transaction_go(t);
347 dns_query_transaction_complete(t, DNS_QUERY_RESOURCES);
355 /* Parse and update the cache */
356 r = dns_packet_extract(p);
358 dns_query_transaction_complete(t, DNS_QUERY_INVALID_REPLY);
362 /* According to RFC 4795, section 2.9. only the RRs from the answer section shall be cached */
363 dns_cache_put(&t->scope->cache, p->question, DNS_PACKET_RCODE(p), p->answer, DNS_PACKET_ANCOUNT(p), 0);
365 if (DNS_PACKET_RCODE(p) == DNS_RCODE_SUCCESS)
366 dns_query_transaction_complete(t, DNS_QUERY_SUCCESS);
368 dns_query_transaction_complete(t, DNS_QUERY_FAILURE);
371 static int on_transaction_timeout(sd_event_source *s, usec_t usec, void *userdata) {
372 DnsQueryTransaction *t = userdata;
378 /* Timeout reached? Try again, with a new server */
379 dns_scope_next_dns_server(t->scope);
381 r = dns_query_transaction_go(t);
383 dns_query_transaction_complete(t, DNS_QUERY_RESOURCES);
388 static int dns_query_make_packet(DnsQueryTransaction *t) {
389 _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
390 unsigned n, added = 0;
398 r = dns_packet_new_query(&p, t->scope->protocol, 0);
402 for (n = 0; n < t->question->n_keys; n++) {
403 r = dns_scope_good_key(t->scope, t->question->keys[n]);
409 r = dns_packet_append_key(p, t->question->keys[n], NULL);
419 DNS_PACKET_HEADER(p)->qdcount = htobe16(added);
420 DNS_PACKET_HEADER(p)->id = t->id;
428 static int dns_query_transaction_go(DnsQueryTransaction *t) {
434 had_stream = !!t->stream;
436 dns_query_transaction_stop(t);
438 log_debug("Beginning transaction on scope %s on %s/%s",
439 dns_protocol_to_string(t->scope->protocol),
440 t->scope->link ? t->scope->link->name : "*",
441 t->scope->family == AF_UNSPEC ? "*" : af_to_name(t->scope->family));
443 if (t->n_attempts >= TRANSACTION_ATTEMPTS_MAX(t)) {
444 dns_query_transaction_complete(t, DNS_QUERY_ATTEMPTS_MAX);
448 if (t->scope->protocol == DNS_PROTOCOL_LLMNR && had_stream) {
449 /* If we already tried via a stream, then we don't
450 * retry on LLMNR. See RFC 4795, Section 2.7. */
451 dns_query_transaction_complete(t, DNS_QUERY_ATTEMPTS_MAX);
456 t->received = dns_packet_unref(t->received);
457 t->cached = dns_answer_unref(t->cached);
460 /* First, let's try the cache */
461 dns_cache_prune(&t->scope->cache);
462 r = dns_cache_lookup(&t->scope->cache, t->question, &t->cached_rcode, &t->cached);
466 if (t->cached_rcode == DNS_RCODE_SUCCESS)
467 dns_query_transaction_complete(t, DNS_QUERY_SUCCESS);
469 dns_query_transaction_complete(t, DNS_QUERY_FAILURE);
473 /* Otherwise, we need to ask the network */
474 r = dns_query_make_packet(t);
476 /* Not the right request to make on this network?
477 * (i.e. an A request made on IPv6 or an AAAA request
478 * made on IPv4, on LLMNR or mDNS.) */
479 dns_query_transaction_complete(t, DNS_QUERY_NO_SERVERS);
485 if (t->scope->protocol == DNS_PROTOCOL_LLMNR &&
486 (dns_question_endswith(t->question, "in-addr.arpa") > 0 ||
487 dns_question_endswith(t->question, "ip6.arpa") > 0)) {
489 /* RFC 4795, Section 2.4. says reverse lookups shall
490 * always be made via TCP on LLMNR */
491 r = dns_query_transaction_open_tcp(t);
493 /* Try via UDP, and if that fails due to large size try via TCP */
494 r = dns_scope_send(t->scope, t->sent);
496 r = dns_query_transaction_open_tcp(t);
499 /* No servers to send this to? */
500 dns_query_transaction_complete(t, DNS_QUERY_NO_SERVERS);
504 /* Couldn't send? Try immediately again, with a new server */
505 dns_scope_next_dns_server(t->scope);
507 return dns_query_transaction_go(t);
510 r = sd_event_add_time(t->scope->manager->event, &t->timeout_event_source, CLOCK_MONOTONIC, now(CLOCK_MONOTONIC) + TRANSACTION_TIMEOUT_USEC(t), 0, on_transaction_timeout, t);
514 t->state = DNS_QUERY_PENDING;
518 DnsQuery *dns_query_free(DnsQuery *q) {
519 DnsQueryTransaction *t;
524 sd_bus_message_unref(q->request);
526 dns_question_unref(q->question);
527 dns_answer_unref(q->answer);
529 sd_event_source_unref(q->timeout_event_source);
531 while ((t = set_steal_first(q->transactions))) {
532 set_remove(t->queries, q);
533 dns_query_transaction_gc(t);
536 set_free(q->transactions);
539 LIST_REMOVE(queries, q->manager->dns_queries, q);
540 q->manager->n_dns_queries--;
548 int dns_query_new(Manager *m, DnsQuery **ret, DnsQuestion *question) {
549 _cleanup_(dns_query_freep) DnsQuery *q = NULL;
556 r = dns_question_is_valid(question);
560 if (m->n_dns_queries >= QUERIES_MAX)
563 q = new0(DnsQuery, 1);
567 q->question = dns_question_ref(question);
569 for (i = 0; i < question->n_keys; i++) {
570 log_debug("Looking up RR for %s %s %s",
571 strna(dns_class_to_string(question->keys[i]->class)),
572 strna(dns_type_to_string(question->keys[i]->type)),
573 DNS_RESOURCE_KEY_NAME(question->keys[i]));
576 LIST_PREPEND(queries, m->dns_queries, q);
587 static void dns_query_stop(DnsQuery *q) {
588 DnsQueryTransaction *t;
592 q->timeout_event_source = sd_event_source_unref(q->timeout_event_source);
594 while ((t = set_steal_first(q->transactions))) {
595 set_remove(t->queries, q);
596 dns_query_transaction_gc(t);
600 static void dns_query_complete(DnsQuery *q, DnsQueryState state) {
602 assert(!IN_SET(state, DNS_QUERY_NULL, DNS_QUERY_PENDING));
603 assert(IN_SET(q->state, DNS_QUERY_NULL, DNS_QUERY_PENDING));
605 /* Note that this call might invalidate the query. Callers
606 * should hence not attempt to access the query or transaction
607 * after calling this function. */
616 static int on_query_timeout(sd_event_source *s, usec_t usec, void *userdata) {
617 DnsQuery *q = userdata;
622 dns_query_complete(q, DNS_QUERY_TIMEOUT);
626 static int dns_query_add_transaction(DnsQuery *q, DnsScope *s, DnsResourceKey *key) {
627 _cleanup_(dns_question_unrefp) DnsQuestion *question = NULL;
628 DnsQueryTransaction *t;
633 r = set_ensure_allocated(&q->transactions, NULL, NULL);
638 question = dns_question_new(1);
642 r = dns_question_add(question, key);
646 question = dns_question_ref(q->question);
648 LIST_FOREACH(transactions_by_scope, t, s->transactions)
649 if (dns_question_is_superset(t->question, question))
653 r = dns_query_transaction_new(&t, s, question);
658 r = set_ensure_allocated(&t->queries, NULL, NULL);
662 r = set_put(t->queries, q);
666 r = set_put(q->transactions, t);
668 set_remove(t->queries, q);
675 dns_query_transaction_gc(t);
679 static int dns_query_add_transaction_split(DnsQuery *q, DnsScope *s) {
685 if (s->protocol == DNS_PROTOCOL_MDNS) {
686 r = dns_query_add_transaction(q, s, NULL);
692 /* On DNS and LLMNR we can only send a single
693 * question per datagram, hence issue multiple
696 for (i = 0; i < q->question->n_keys; i++) {
697 r = dns_query_add_transaction(q, s, q->question->keys[i]);
706 int dns_query_go(DnsQuery *q) {
707 DnsScopeMatch found = DNS_SCOPE_NO;
708 DnsScope *s, *first = NULL;
709 DnsQueryTransaction *t;
716 if (q->state != DNS_QUERY_NULL)
720 assert(q->question->n_keys > 0);
722 name = DNS_RESOURCE_KEY_NAME(q->question->keys[0]);
724 LIST_FOREACH(scopes, s, q->manager->dns_scopes) {
727 match = dns_scope_good_domain(s, name);
731 if (match == DNS_SCOPE_NO)
736 if (match == DNS_SCOPE_YES) {
740 assert(match == DNS_SCOPE_MAYBE);
747 if (found == DNS_SCOPE_NO)
750 r = dns_query_add_transaction_split(q, first);
754 LIST_FOREACH(scopes, s, first->scopes_next) {
757 match = dns_scope_good_domain(s, name);
764 r = dns_query_add_transaction_split(q, s);
769 q->answer = dns_answer_unref(q->answer);
770 q->answer_ifindex = 0;
773 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);
777 q->state = DNS_QUERY_PENDING;
780 SET_FOREACH(t, q->transactions, i) {
781 if (t->state == DNS_QUERY_NULL) {
782 r = dns_query_transaction_go(t);
798 void dns_query_ready(DnsQuery *q) {
799 DnsQueryTransaction *t;
800 DnsQueryState state = DNS_QUERY_NO_SERVERS;
801 _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL;
803 DnsScope *scope = NULL;
807 assert(IN_SET(q->state, DNS_QUERY_NULL, DNS_QUERY_PENDING));
809 /* Note that this call might invalidate the query. Callers
810 * should hence not attempt to access the query or transaction
811 * after calling this function, unless the block_ready
812 * counter was explicitly bumped before doing so. */
814 if (q->block_ready > 0)
817 SET_FOREACH(t, q->transactions, i) {
819 /* If we found a successful answer, ignore all answers from other scopes */
820 if (state == DNS_QUERY_SUCCESS && t->scope != scope)
823 /* One of the transactions is still going on, let's wait for it */
824 if (t->state == DNS_QUERY_PENDING || t->state == DNS_QUERY_NULL)
827 /* One of the transactions is successful, let's use
828 * it, and copy its data out */
829 if (t->state == DNS_QUERY_SUCCESS) {
833 rcode = DNS_PACKET_RCODE(t->received);
834 a = t->received->answer;
836 rcode = t->cached_rcode;
840 if (state == DNS_QUERY_SUCCESS) {
843 merged = dns_answer_merge(answer, a);
845 dns_query_complete(q, DNS_QUERY_RESOURCES);
849 dns_answer_unref(answer);
852 dns_answer_unref(answer);
853 answer = dns_answer_ref(a);
857 state = DNS_QUERY_SUCCESS;
861 /* One of the transactions has failed, let's see
862 * whether we find anything better, but if not, return
863 * its response data */
864 if (state != DNS_QUERY_SUCCESS && t->state == DNS_QUERY_FAILURE) {
868 rcode = DNS_PACKET_RCODE(t->received);
869 a = t->received->answer;
871 rcode = t->cached_rcode;
875 dns_answer_unref(answer);
876 answer = dns_answer_ref(a);
879 state = DNS_QUERY_FAILURE;
883 if (state == DNS_QUERY_NO_SERVERS && t->state != DNS_QUERY_NO_SERVERS)
887 if (IN_SET(state, DNS_QUERY_SUCCESS, DNS_QUERY_FAILURE)) {
888 q->answer = dns_answer_ref(answer);
889 q->answer_rcode = rcode;
890 q->answer_ifindex = (scope && scope->link) ? scope->link->ifindex : 0;
893 dns_query_complete(q, state);
896 int dns_query_cname_redirect(DnsQuery *q, const char *name) {
897 _cleanup_(dns_question_unrefp) DnsQuestion *nq = NULL;
902 if (q->n_cname_redirects > CNAME_MAX)
905 r = dns_question_cname_redirect(q->question, name, &nq);
909 dns_question_unref(q->question);
913 q->n_cname_redirects++;
916 q->state = DNS_QUERY_NULL;
921 static const char* const dns_query_state_table[_DNS_QUERY_STATE_MAX] = {
922 [DNS_QUERY_NULL] = "null",
923 [DNS_QUERY_PENDING] = "pending",
924 [DNS_QUERY_FAILURE] = "failure",
925 [DNS_QUERY_SUCCESS] = "success",
926 [DNS_QUERY_NO_SERVERS] = "no-servers",
927 [DNS_QUERY_TIMEOUT] = "timeout",
928 [DNS_QUERY_ATTEMPTS_MAX] = "attempts-max",
929 [DNS_QUERY_INVALID_REPLY] = "invalid-reply",
930 [DNS_QUERY_RESOURCES] = "resources",
931 [DNS_QUERY_ABORTED] = "aborted",
933 DEFINE_STRING_TABLE_LOOKUP(dns_query_state, DnsQueryState);