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);
169 dns_query_transaction_process_reply(t, p);
172 /* If the response wasn't useful, then complete the transition now */
173 if (t->state == DNS_QUERY_PENDING)
174 dns_query_transaction_complete(t, DNS_QUERY_INVALID_REPLY);
179 static int dns_query_transaction_open_tcp(DnsQueryTransaction *t) {
180 _cleanup_close_ int fd = -1;
188 if (t->scope->protocol == DNS_PROTOCOL_DNS)
189 fd = dns_scope_tcp_socket(t->scope, AF_UNSPEC, NULL, 53);
190 else if (t->scope->protocol == DNS_PROTOCOL_LLMNR) {
192 /* When we already received a query to this (but it was truncated), send to its sender address */
194 fd = dns_scope_tcp_socket(t->scope, t->received->family, &t->received->sender, t->received->sender_port);
196 union in_addr_union address;
199 /* Otherwise, try to talk to the owner of a
200 * the IP address, in case this is a reverse
202 r = dns_question_extract_reverse_address(t->question, &family, &address);
208 fd = dns_scope_tcp_socket(t->scope, family, &address, 5355);
211 return -EAFNOSUPPORT;
216 r = dns_stream_new(t->scope->manager, &t->stream, t->scope->protocol, fd);
222 r = dns_stream_write_packet(t->stream, t->sent);
224 t->stream = dns_stream_free(t->stream);
228 t->received = dns_packet_unref(t->received);
229 t->stream->complete = on_stream_complete;
230 t->stream->transaction = t;
232 /* The interface index is difficult to determine if we are
233 * connecting to the local host, hence fill this in right away
234 * instead of determining it from the socket */
236 t->stream->ifindex = t->scope->link->ifindex;
241 void dns_query_transaction_process_reply(DnsQueryTransaction *t, DnsPacket *p) {
246 assert(t->state == DNS_QUERY_PENDING);
248 /* Note that this call might invalidate the query. Callers
249 * should hence not attempt to access the query or transaction
250 * after calling this function. */
252 if (t->scope->protocol == DNS_PROTOCOL_LLMNR) {
253 assert(t->scope->link);
255 /* For LLMNR we will not accept any packets from other
258 if (p->ifindex != t->scope->link->ifindex)
261 if (p->family != t->scope->family)
264 /* Don't accept UDP packets directed to anything but
265 * the LLMNR multicast addresses. */
267 if (p->ipproto == IPPROTO_UDP) {
268 if (p->family == AF_INET && !in_addr_equal(AF_INET, &p->destination, (union in_addr_union*) &LLMNR_MULTICAST_IPV4_ADDRESS))
271 if (p->family == AF_INET6 && !in_addr_equal(AF_INET6, &p->destination, (union in_addr_union*) &LLMNR_MULTICAST_IPV6_ADDRESS))
275 /* Tentative replies shall be discarded, see RFC 4795,
282 if (t->scope->protocol == DNS_PROTOCOL_DNS) {
284 /* For DNS we are fine with accepting packets on any
285 * interface, but the source IP address must be one of
286 * a valid DNS server */
288 if (!dns_scope_good_dns_server(t->scope, p->family, &p->sender))
291 if (p->sender_port != 53)
295 if (t->received != p) {
296 dns_packet_unref(t->received);
297 t->received = dns_packet_ref(p);
300 if (p->ipproto == IPPROTO_TCP) {
301 if (DNS_PACKET_TC(p)) {
302 /* Truncated via TCP? Somebody must be fucking with us */
303 dns_query_transaction_complete(t, DNS_QUERY_INVALID_REPLY);
307 if (DNS_PACKET_ID(p) != t->id) {
308 /* Not the reply to our query? Somebody must be fucking with us */
309 dns_query_transaction_complete(t, DNS_QUERY_INVALID_REPLY);
314 if (DNS_PACKET_TC(p)) {
315 /* Response was truncated, let's try again with good old TCP */
316 r = dns_query_transaction_open_tcp(t);
318 /* No servers found? Damn! */
319 dns_query_transaction_complete(t, DNS_QUERY_NO_SERVERS);
323 /* On LLMNR, if we cannot connect to the host,
324 * we immediately give up */
325 if (t->scope->protocol == DNS_PROTOCOL_LLMNR) {
326 dns_query_transaction_complete(t, DNS_QUERY_RESOURCES);
330 /* On DNS, couldn't send? Try immediately again, with a new server */
331 dns_scope_next_dns_server(t->scope);
333 r = dns_query_transaction_go(t);
335 dns_query_transaction_complete(t, DNS_QUERY_RESOURCES);
343 /* Parse and update the cache */
344 r = dns_packet_extract(p);
346 dns_query_transaction_complete(t, DNS_QUERY_INVALID_REPLY);
350 dns_cache_put(&t->scope->cache, p->question, DNS_PACKET_RCODE(p), p->answer, 0);
352 if (DNS_PACKET_RCODE(p) == DNS_RCODE_SUCCESS)
353 dns_query_transaction_complete(t, DNS_QUERY_SUCCESS);
355 dns_query_transaction_complete(t, DNS_QUERY_FAILURE);
358 static int on_transaction_timeout(sd_event_source *s, usec_t usec, void *userdata) {
359 DnsQueryTransaction *t = userdata;
365 /* Timeout reached? Try again, with a new server */
366 dns_scope_next_dns_server(t->scope);
368 r = dns_query_transaction_go(t);
370 dns_query_transaction_complete(t, DNS_QUERY_RESOURCES);
375 static int dns_query_make_packet(DnsQueryTransaction *t) {
376 _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
377 unsigned n, added = 0;
385 r = dns_packet_new_query(&p, t->scope->protocol, 0);
389 for (n = 0; n < t->question->n_keys; n++) {
390 r = dns_scope_good_key(t->scope, t->question->keys[n]);
396 r = dns_packet_append_key(p, t->question->keys[n], NULL);
406 DNS_PACKET_HEADER(p)->qdcount = htobe16(added);
407 DNS_PACKET_HEADER(p)->id = t->id;
415 static int dns_query_transaction_go(DnsQueryTransaction *t) {
420 dns_query_transaction_stop(t);
422 if (t->n_attempts >= ATTEMPTS_MAX) {
423 dns_query_transaction_complete(t, DNS_QUERY_ATTEMPTS_MAX);
428 t->received = dns_packet_unref(t->received);
429 t->cached = dns_answer_unref(t->cached);
432 /* First, let's try the cache */
433 dns_cache_prune(&t->scope->cache);
434 r = dns_cache_lookup(&t->scope->cache, t->question, &t->cached_rcode, &t->cached);
438 if (t->cached_rcode == DNS_RCODE_SUCCESS)
439 dns_query_transaction_complete(t, DNS_QUERY_SUCCESS);
441 dns_query_transaction_complete(t, DNS_QUERY_FAILURE);
445 /* Otherwise, we need to ask the network */
446 r = dns_query_make_packet(t);
448 /* Not the right request to make on this network?
449 * (i.e. an A request made on IPv6 or an AAAA request
450 * made on IPv4, on LLMNR or mDNS.) */
451 dns_query_transaction_complete(t, DNS_QUERY_NO_SERVERS);
457 if (t->scope->protocol == DNS_PROTOCOL_LLMNR &&
458 (dns_question_endswith(t->question, "in-addr.arpa") > 0 ||
459 dns_question_endswith(t->question, "ip6.arpa") > 0)) {
461 /* RFC 4795, Section 2.4. says reverse lookups shall
462 * always be made via TCP on LLMNR */
463 r = dns_query_transaction_open_tcp(t);
465 /* Try via UDP, and if that fails due to large size try via TCP */
466 r = dns_scope_send(t->scope, t->sent);
468 r = dns_query_transaction_open_tcp(t);
471 /* No servers to send this to? */
472 dns_query_transaction_complete(t, DNS_QUERY_NO_SERVERS);
476 /* Couldn't send? Try immediately again, with a new server */
477 dns_scope_next_dns_server(t->scope);
479 return dns_query_transaction_go(t);
482 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);
486 t->state = DNS_QUERY_PENDING;
490 DnsQuery *dns_query_free(DnsQuery *q) {
491 DnsQueryTransaction *t;
496 sd_bus_message_unref(q->request);
498 dns_question_unref(q->question);
499 dns_answer_unref(q->answer);
501 sd_event_source_unref(q->timeout_event_source);
503 while ((t = set_steal_first(q->transactions))) {
504 set_remove(t->queries, q);
505 dns_query_transaction_gc(t);
508 set_free(q->transactions);
511 LIST_REMOVE(queries, q->manager->dns_queries, q);
512 q->manager->n_dns_queries--;
520 int dns_query_new(Manager *m, DnsQuery **ret, DnsQuestion *question) {
521 _cleanup_(dns_query_freep) DnsQuery *q = NULL;
528 r = dns_question_is_valid(question);
532 if (m->n_dns_queries >= QUERIES_MAX)
535 q = new0(DnsQuery, 1);
539 q->question = dns_question_ref(question);
541 for (i = 0; i < question->n_keys; i++) {
542 log_debug("Looking up RR for %s %s %s",
543 strna(dns_class_to_string(question->keys[i]->class)),
544 strna(dns_type_to_string(question->keys[i]->type)),
545 DNS_RESOURCE_KEY_NAME(question->keys[i]));
548 LIST_PREPEND(queries, m->dns_queries, q);
559 static void dns_query_stop(DnsQuery *q) {
560 DnsQueryTransaction *t;
564 q->timeout_event_source = sd_event_source_unref(q->timeout_event_source);
566 while ((t = set_steal_first(q->transactions))) {
567 set_remove(t->queries, q);
568 dns_query_transaction_gc(t);
572 static void dns_query_complete(DnsQuery *q, DnsQueryState state) {
574 assert(!IN_SET(state, DNS_QUERY_NULL, DNS_QUERY_PENDING));
575 assert(IN_SET(q->state, DNS_QUERY_NULL, DNS_QUERY_PENDING));
577 /* Note that this call might invalidate the query. Callers
578 * should hence not attempt to access the query or transaction
579 * after calling this function. */
588 static int on_query_timeout(sd_event_source *s, usec_t usec, void *userdata) {
589 DnsQuery *q = userdata;
594 dns_query_complete(q, DNS_QUERY_TIMEOUT);
598 static int dns_query_add_transaction(DnsQuery *q, DnsScope *s, DnsResourceKey *key) {
599 _cleanup_(dns_question_unrefp) DnsQuestion *question = NULL;
600 DnsQueryTransaction *t;
605 r = set_ensure_allocated(&q->transactions, NULL, NULL);
610 question = dns_question_new(1);
614 r = dns_question_add(question, key);
618 question = dns_question_ref(q->question);
620 LIST_FOREACH(transactions_by_scope, t, s->transactions)
621 if (dns_question_is_superset(t->question, question))
625 r = dns_query_transaction_new(&t, s, question);
630 r = set_ensure_allocated(&t->queries, NULL, NULL);
634 r = set_put(t->queries, q);
638 r = set_put(q->transactions, t);
640 set_remove(t->queries, q);
647 dns_query_transaction_gc(t);
651 static int dns_query_add_transaction_split(DnsQuery *q, DnsScope *s) {
657 if (s->protocol == DNS_PROTOCOL_MDNS) {
658 r = dns_query_add_transaction(q, s, NULL);
664 /* On DNS and LLMNR we can only send a single
665 * question per datagram, hence issue multiple
668 for (i = 0; i < q->question->n_keys; i++) {
669 r = dns_query_add_transaction(q, s, q->question->keys[i]);
678 int dns_query_go(DnsQuery *q) {
679 DnsScopeMatch found = DNS_SCOPE_NO;
680 DnsScope *s, *first = NULL;
681 DnsQueryTransaction *t;
688 if (q->state != DNS_QUERY_NULL)
692 assert(q->question->n_keys > 0);
694 name = DNS_RESOURCE_KEY_NAME(q->question->keys[0]);
696 LIST_FOREACH(scopes, s, q->manager->dns_scopes) {
699 match = dns_scope_good_domain(s, name);
703 if (match == DNS_SCOPE_NO)
708 if (match == DNS_SCOPE_YES) {
712 assert(match == DNS_SCOPE_MAYBE);
719 if (found == DNS_SCOPE_NO)
722 r = dns_query_add_transaction_split(q, first);
726 LIST_FOREACH(scopes, s, first->scopes_next) {
729 match = dns_scope_good_domain(s, name);
736 r = dns_query_add_transaction_split(q, s);
741 q->answer = dns_answer_unref(q->answer);
742 q->answer_ifindex = 0;
745 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);
749 q->state = DNS_QUERY_PENDING;
752 SET_FOREACH(t, q->transactions, i) {
753 if (t->state == DNS_QUERY_NULL) {
754 r = dns_query_transaction_go(t);
770 void dns_query_ready(DnsQuery *q) {
771 DnsQueryTransaction *t;
772 DnsQueryState state = DNS_QUERY_NO_SERVERS;
773 _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL;
775 DnsScope *scope = NULL;
779 assert(IN_SET(q->state, DNS_QUERY_NULL, DNS_QUERY_PENDING));
781 /* Note that this call might invalidate the query. Callers
782 * should hence not attempt to access the query or transaction
783 * after calling this function, unless the block_ready
784 * counter was explicitly bumped before doing so. */
786 if (q->block_ready > 0)
789 SET_FOREACH(t, q->transactions, i) {
791 /* If we found a successful answer, ignore all answers from other scopes */
792 if (state == DNS_QUERY_SUCCESS && t->scope != scope)
795 /* One of the transactions is still going on, let's wait for it */
796 if (t->state == DNS_QUERY_PENDING || t->state == DNS_QUERY_NULL)
799 /* One of the transactions is successful, let's use
800 * it, and copy its data out */
801 if (t->state == DNS_QUERY_SUCCESS) {
805 rcode = DNS_PACKET_RCODE(t->received);
806 a = t->received->answer;
808 rcode = t->cached_rcode;
812 if (state == DNS_QUERY_SUCCESS) {
815 merged = dns_answer_merge(answer, a);
817 dns_query_complete(q, DNS_QUERY_RESOURCES);
821 dns_answer_unref(answer);
824 dns_answer_unref(answer);
825 answer = dns_answer_ref(a);
829 state = DNS_QUERY_SUCCESS;
833 /* One of the transactions has failed, let's see
834 * whether we find anything better, but if not, return
835 * its response data */
836 if (state != DNS_QUERY_SUCCESS && t->state == DNS_QUERY_FAILURE) {
840 rcode = DNS_PACKET_RCODE(t->received);
841 a = t->received->answer;
843 rcode = t->cached_rcode;
847 dns_answer_unref(answer);
848 answer = dns_answer_ref(a);
851 state = DNS_QUERY_FAILURE;
855 if (state == DNS_QUERY_NO_SERVERS && t->state != DNS_QUERY_NO_SERVERS)
859 if (IN_SET(state, DNS_QUERY_SUCCESS, DNS_QUERY_FAILURE)) {
860 q->answer = dns_answer_ref(answer);
861 q->answer_rcode = rcode;
862 q->answer_ifindex = (scope && scope->link) ? scope->link->ifindex : 0;
865 dns_query_complete(q, state);
868 int dns_query_cname_redirect(DnsQuery *q, const char *name) {
869 _cleanup_(dns_question_unrefp) DnsQuestion *nq = NULL;
874 if (q->n_cname_redirects > CNAME_MAX)
877 r = dns_question_cname_redirect(q->question, name, &nq);
881 dns_question_unref(q->question);
885 q->n_cname_redirects++;
888 q->state = DNS_QUERY_NULL;