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-llmnr.h"
25 #include "resolved-dns-transaction.h"
26 #include "random-util.h"
27 #include "dns-domain.h"
29 DnsTransaction
* dns_transaction_free(DnsTransaction
*t
) {
36 sd_event_source_unref(t
->timeout_event_source
);
38 dns_packet_unref(t
->sent
);
39 dns_packet_unref(t
->received
);
40 dns_answer_unref(t
->cached
);
42 sd_event_source_unref(t
->dns_event_source
);
43 safe_close(t
->dns_fd
);
45 dns_server_unref(t
->server
);
46 dns_stream_free(t
->stream
);
49 hashmap_remove(t
->scope
->transactions
, t
->key
);
52 hashmap_remove(t
->scope
->manager
->dns_transactions
, UINT_TO_PTR(t
->id
));
55 dns_resource_key_unref(t
->key
);
57 while ((q
= set_steal_first(t
->queries
)))
58 set_remove(q
->transactions
, t
);
61 while ((i
= set_steal_first(t
->zone_items
)))
62 i
->probe_transaction
= NULL
;
63 set_free(t
->zone_items
);
69 DEFINE_TRIVIAL_CLEANUP_FUNC(DnsTransaction
*, dns_transaction_free
);
71 void dns_transaction_gc(DnsTransaction
*t
) {
77 if (set_isempty(t
->queries
) && set_isempty(t
->zone_items
))
78 dns_transaction_free(t
);
81 int dns_transaction_new(DnsTransaction
**ret
, DnsScope
*s
, DnsResourceKey
*key
) {
82 _cleanup_(dns_transaction_freep
) DnsTransaction
*t
= NULL
;
89 r
= hashmap_ensure_allocated(&s
->manager
->dns_transactions
, NULL
);
93 r
= hashmap_ensure_allocated(&s
->transactions
, &dns_resource_key_hash_ops
);
97 t
= new0(DnsTransaction
, 1);
102 t
->key
= dns_resource_key_ref(key
);
104 /* Find a fresh, unused transaction id */
106 random_bytes(&t
->id
, sizeof(t
->id
));
108 hashmap_get(s
->manager
->dns_transactions
, UINT_TO_PTR(t
->id
)));
110 r
= hashmap_put(s
->manager
->dns_transactions
, UINT_TO_PTR(t
->id
), t
);
116 r
= hashmap_put(s
->transactions
, t
->key
, t
);
118 hashmap_remove(s
->manager
->dns_transactions
, UINT_TO_PTR(t
->id
));
132 static void dns_transaction_stop(DnsTransaction
*t
) {
135 t
->timeout_event_source
= sd_event_source_unref(t
->timeout_event_source
);
136 t
->stream
= dns_stream_free(t
->stream
);
139 static void dns_transaction_tentative(DnsTransaction
*t
, DnsPacket
*p
) {
140 _cleanup_free_
char *pretty
= NULL
;
146 if (manager_our_packet(t
->scope
->manager
, p
) != 0)
149 in_addr_to_string(p
->family
, &p
->sender
, &pretty
);
151 log_debug("Transaction on scope %s on %s/%s got tentative packet from %s",
152 dns_protocol_to_string(t
->scope
->protocol
),
153 t
->scope
->link
? t
->scope
->link
->name
: "*",
154 t
->scope
->family
== AF_UNSPEC
? "*" : af_to_name(t
->scope
->family
),
157 /* RFC 4795, Section 4.1 says that the peer with the
158 * lexicographically smaller IP address loses */
159 if (memcmp(&p
->sender
, &p
->destination
, FAMILY_ADDRESS_SIZE(p
->family
)) >= 0) {
160 log_debug("Peer has lexicographically larger IP address and thus lost in the conflict.");
164 log_debug("We have the lexicographically larger IP address and thus lost in the conflict.");
167 while ((z
= set_first(t
->zone_items
))) {
168 /* First, make sure the zone item drops the reference
170 dns_zone_item_probe_stop(z
);
172 /* Secondly, report this as conflict, so that we might
173 * look for a different hostname */
174 dns_zone_item_conflict(z
);
178 dns_transaction_gc(t
);
181 void dns_transaction_complete(DnsTransaction
*t
, DnsTransactionState state
) {
187 assert(!IN_SET(state
, DNS_TRANSACTION_NULL
, DNS_TRANSACTION_PENDING
));
189 /* Note that this call might invalidate the query. Callers
190 * should hence not attempt to access the query or transaction
191 * after calling this function. */
193 log_debug("Transaction on scope %s on %s/%s now complete with <%s>",
194 dns_protocol_to_string(t
->scope
->protocol
),
195 t
->scope
->link
? t
->scope
->link
->name
: "*",
196 t
->scope
->family
== AF_UNSPEC
? "*" : af_to_name(t
->scope
->family
),
197 dns_transaction_state_to_string(state
));
201 dns_transaction_stop(t
);
203 /* Notify all queries that are interested, but make sure the
204 * transaction isn't freed while we are still looking at it */
206 SET_FOREACH(q
, t
->queries
, i
)
208 SET_FOREACH(z
, t
->zone_items
, i
)
209 dns_zone_item_ready(z
);
212 dns_transaction_gc(t
);
215 static int on_stream_complete(DnsStream
*s
, int error
) {
216 _cleanup_(dns_packet_unrefp
) DnsPacket
*p
= NULL
;
220 assert(s
->transaction
);
222 /* Copy the data we care about out of the stream before we
225 p
= dns_packet_ref(s
->read_packet
);
227 t
->stream
= dns_stream_free(t
->stream
);
230 dns_transaction_complete(t
, DNS_TRANSACTION_RESOURCES
);
234 if (dns_packet_validate_reply(p
) <= 0) {
235 log_debug("Invalid LLMNR TCP packet.");
236 dns_transaction_complete(t
, DNS_TRANSACTION_INVALID_REPLY
);
240 dns_scope_check_conflicts(t
->scope
, p
);
243 dns_transaction_process_reply(t
, p
);
246 /* If the response wasn't useful, then complete the transition now */
247 if (t
->state
== DNS_TRANSACTION_PENDING
)
248 dns_transaction_complete(t
, DNS_TRANSACTION_INVALID_REPLY
);
253 static int dns_transaction_open_tcp(DnsTransaction
*t
) {
254 DnsServer
*server
= NULL
;
255 _cleanup_close_
int fd
= -1;
263 if (t
->scope
->protocol
== DNS_PROTOCOL_DNS
)
264 fd
= dns_scope_tcp_socket(t
->scope
, AF_UNSPEC
, NULL
, 53, &server
);
265 else if (t
->scope
->protocol
== DNS_PROTOCOL_LLMNR
) {
267 /* When we already received a reply to this (but it was truncated), send to its sender address */
269 fd
= dns_scope_tcp_socket(t
->scope
, t
->received
->family
, &t
->received
->sender
, t
->received
->sender_port
, NULL
);
271 union in_addr_union address
;
272 int family
= AF_UNSPEC
;
274 /* Otherwise, try to talk to the owner of a
275 * the IP address, in case this is a reverse
278 r
= dns_name_address(DNS_RESOURCE_KEY_NAME(t
->key
), &family
, &address
);
283 if (family
!= t
->scope
->family
)
286 fd
= dns_scope_tcp_socket(t
->scope
, family
, &address
, LLMNR_PORT
, NULL
);
289 return -EAFNOSUPPORT
;
294 r
= dns_stream_new(t
->scope
->manager
, &t
->stream
, t
->scope
->protocol
, fd
);
300 r
= dns_stream_write_packet(t
->stream
, t
->sent
);
302 t
->stream
= dns_stream_free(t
->stream
);
306 dns_server_unref(t
->server
);
307 t
->server
= dns_server_ref(server
);
308 t
->received
= dns_packet_unref(t
->received
);
309 t
->stream
->complete
= on_stream_complete
;
310 t
->stream
->transaction
= t
;
312 /* The interface index is difficult to determine if we are
313 * connecting to the local host, hence fill this in right away
314 * instead of determining it from the socket */
316 t
->stream
->ifindex
= t
->scope
->link
->ifindex
;
321 static void dns_transaction_next_dns_server(DnsTransaction
*t
) {
324 t
->server
= dns_server_unref(t
->server
);
325 t
->dns_event_source
= sd_event_source_unref(t
->dns_event_source
);
326 t
->dns_fd
= safe_close(t
->dns_fd
);
328 dns_scope_next_dns_server(t
->scope
);
331 void dns_transaction_process_reply(DnsTransaction
*t
, DnsPacket
*p
) {
337 assert(t
->state
== DNS_TRANSACTION_PENDING
);
339 assert(t
->scope
->manager
);
341 /* Note that this call might invalidate the query. Callers
342 * should hence not attempt to access the query or transaction
343 * after calling this function. */
345 if (t
->scope
->protocol
== DNS_PROTOCOL_LLMNR
) {
346 assert(t
->scope
->link
);
348 /* For LLMNR we will not accept any packets from other
351 if (p
->ifindex
!= t
->scope
->link
->ifindex
)
354 if (p
->family
!= t
->scope
->family
)
357 /* Tentative packets are not full responses but still
358 * useful for identifying uniqueness conflicts during
360 if (DNS_PACKET_LLMNR_T(p
)) {
361 dns_transaction_tentative(t
, p
);
366 if (t
->received
!= p
) {
367 dns_packet_unref(t
->received
);
368 t
->received
= dns_packet_ref(p
);
371 if (p
->ipproto
== IPPROTO_TCP
) {
372 if (DNS_PACKET_TC(p
)) {
373 /* Truncated via TCP? Somebody must be fucking with us */
374 dns_transaction_complete(t
, DNS_TRANSACTION_INVALID_REPLY
);
378 if (DNS_PACKET_ID(p
) != t
->id
) {
379 /* Not the reply to our query? Somebody must be fucking with us */
380 dns_transaction_complete(t
, DNS_TRANSACTION_INVALID_REPLY
);
385 assert_se(sd_event_now(t
->scope
->manager
->event
, clock_boottime_or_monotonic(), &ts
) >= 0);
387 switch (t
->scope
->protocol
) {
388 case DNS_PROTOCOL_DNS
:
391 dns_server_packet_received(t
->server
, ts
- t
->start_usec
);
394 case DNS_PROTOCOL_LLMNR
:
395 case DNS_PROTOCOL_MDNS
:
396 dns_scope_packet_received(t
->scope
, ts
- t
->start_usec
);
400 assert_not_reached("Invalid DNS protocol.");
403 if (DNS_PACKET_TC(p
)) {
404 /* Response was truncated, let's try again with good old TCP */
405 r
= dns_transaction_open_tcp(t
);
407 /* No servers found? Damn! */
408 dns_transaction_complete(t
, DNS_TRANSACTION_NO_SERVERS
);
412 /* On LLMNR, if we cannot connect to the host,
413 * we immediately give up */
414 if (t
->scope
->protocol
== DNS_PROTOCOL_LLMNR
) {
415 dns_transaction_complete(t
, DNS_TRANSACTION_RESOURCES
);
419 /* On DNS, couldn't send? Try immediately again, with a new server */
420 dns_transaction_next_dns_server(t
);
422 r
= dns_transaction_go(t
);
424 dns_transaction_complete(t
, DNS_TRANSACTION_RESOURCES
);
432 /* Parse and update the cache */
433 r
= dns_packet_extract(p
);
435 dns_transaction_complete(t
, DNS_TRANSACTION_INVALID_REPLY
);
439 /* Only consider responses with equivalent query section to the request */
440 if (p
->question
->n_keys
!= 1 || dns_resource_key_equal(p
->question
->keys
[0], t
->key
) <= 0) {
441 dns_transaction_complete(t
, DNS_TRANSACTION_INVALID_REPLY
);
445 /* According to RFC 4795, section 2.9. only the RRs from the answer section shall be cached */
446 dns_cache_put(&t
->scope
->cache
, p
->question
, DNS_PACKET_RCODE(p
), p
->answer
, DNS_PACKET_ANCOUNT(p
), 0, p
->family
, &p
->sender
);
448 if (DNS_PACKET_RCODE(p
) == DNS_RCODE_SUCCESS
)
449 dns_transaction_complete(t
, DNS_TRANSACTION_SUCCESS
);
451 dns_transaction_complete(t
, DNS_TRANSACTION_FAILURE
);
454 static int on_dns_packet(sd_event_source
*s
, int fd
, uint32_t revents
, void *userdata
) {
455 _cleanup_(dns_packet_unrefp
) DnsPacket
*p
= NULL
;
456 DnsTransaction
*t
= userdata
;
462 r
= manager_recv(t
->scope
->manager
, fd
, DNS_PROTOCOL_DNS
, &p
);
466 if (dns_packet_validate_reply(p
) > 0 &&
467 DNS_PACKET_ID(p
) == t
->id
)
468 dns_transaction_process_reply(t
, p
);
470 log_debug("Invalid DNS packet.");
475 static int dns_transaction_emit(DnsTransaction
*t
) {
480 if (t
->scope
->protocol
== DNS_PROTOCOL_DNS
&& !t
->server
) {
481 DnsServer
*server
= NULL
;
482 _cleanup_close_
int fd
= -1;
484 fd
= dns_scope_udp_dns_socket(t
->scope
, &server
);
488 r
= sd_event_add_io(t
->scope
->manager
->event
, &t
->dns_event_source
, fd
, EPOLLIN
, on_dns_packet
, t
);
494 t
->server
= dns_server_ref(server
);
497 r
= dns_scope_emit(t
->scope
, t
->dns_fd
, t
->sent
);
504 static int on_transaction_timeout(sd_event_source
*s
, usec_t usec
, void *userdata
) {
505 DnsTransaction
*t
= userdata
;
511 /* Timeout reached? Try again, with a new server */
512 dns_transaction_next_dns_server(t
);
514 /* ... and possibly increased timeout */
516 dns_server_packet_lost(t
->server
, usec
- t
->start_usec
);
518 dns_scope_packet_lost(t
->scope
, usec
- t
->start_usec
);
520 r
= dns_transaction_go(t
);
522 dns_transaction_complete(t
, DNS_TRANSACTION_RESOURCES
);
527 static int dns_transaction_make_packet(DnsTransaction
*t
) {
528 _cleanup_(dns_packet_unrefp
) DnsPacket
*p
= NULL
;
536 r
= dns_packet_new_query(&p
, t
->scope
->protocol
, 0);
540 r
= dns_scope_good_key(t
->scope
, t
->key
);
546 r
= dns_packet_append_key(p
, t
->key
, NULL
);
550 DNS_PACKET_HEADER(p
)->qdcount
= htobe16(1);
551 DNS_PACKET_HEADER(p
)->id
= t
->id
;
559 static usec_t
transaction_get_resend_timeout(DnsTransaction
*t
) {
563 switch (t
->scope
->protocol
) {
564 case DNS_PROTOCOL_DNS
:
567 return t
->server
->resend_timeout
;
568 case DNS_PROTOCOL_LLMNR
:
569 case DNS_PROTOCOL_MDNS
:
570 return t
->scope
->resend_timeout
;
572 assert_not_reached("Invalid DNS protocol.");
576 int dns_transaction_go(DnsTransaction
*t
) {
583 had_stream
= !!t
->stream
;
585 dns_transaction_stop(t
);
587 log_debug("Excercising transaction on scope %s on %s/%s",
588 dns_protocol_to_string(t
->scope
->protocol
),
589 t
->scope
->link
? t
->scope
->link
->name
: "*",
590 t
->scope
->family
== AF_UNSPEC
? "*" : af_to_name(t
->scope
->family
));
592 if (t
->n_attempts
>= TRANSACTION_ATTEMPTS_MAX(t
->scope
->protocol
)) {
593 dns_transaction_complete(t
, DNS_TRANSACTION_ATTEMPTS_MAX_REACHED
);
597 if (t
->scope
->protocol
== DNS_PROTOCOL_LLMNR
&& had_stream
) {
598 /* If we already tried via a stream, then we don't
599 * retry on LLMNR. See RFC 4795, Section 2.7. */
600 dns_transaction_complete(t
, DNS_TRANSACTION_ATTEMPTS_MAX_REACHED
);
604 assert_se(sd_event_now(t
->scope
->manager
->event
, clock_boottime_or_monotonic(), &ts
) >= 0);
608 t
->received
= dns_packet_unref(t
->received
);
609 t
->cached
= dns_answer_unref(t
->cached
);
612 /* Check the cache, but only if this transaction is not used
613 * for probing or verifying a zone item. */
614 if (set_isempty(t
->zone_items
)) {
616 /* Before trying the cache, let's make sure we figured out a
617 * server to use. Should this cause a change of server this
618 * might flush the cache. */
619 dns_scope_get_dns_server(t
->scope
);
621 /* Let's then prune all outdated entries */
622 dns_cache_prune(&t
->scope
->cache
);
624 r
= dns_cache_lookup(&t
->scope
->cache
, t
->key
, &t
->cached_rcode
, &t
->cached
);
628 if (t
->cached_rcode
== DNS_RCODE_SUCCESS
)
629 dns_transaction_complete(t
, DNS_TRANSACTION_SUCCESS
);
631 dns_transaction_complete(t
, DNS_TRANSACTION_FAILURE
);
636 if (t
->scope
->protocol
== DNS_PROTOCOL_LLMNR
&& !t
->initial_jitter
) {
639 /* RFC 4795 Section 2.7 suggests all queries should be
640 * delayed by a random time from 0 to JITTER_INTERVAL. */
642 t
->initial_jitter
= true;
644 random_bytes(&jitter
, sizeof(jitter
));
645 jitter
%= LLMNR_JITTER_INTERVAL_USEC
;
647 r
= sd_event_add_time(
648 t
->scope
->manager
->event
,
649 &t
->timeout_event_source
,
650 clock_boottime_or_monotonic(),
652 LLMNR_JITTER_INTERVAL_USEC
,
653 on_transaction_timeout
, t
);
658 t
->state
= DNS_TRANSACTION_PENDING
;
660 log_debug("Delaying LLMNR transaction for " USEC_FMT
"us.", jitter
);
664 /* Otherwise, we need to ask the network */
665 r
= dns_transaction_make_packet(t
);
667 /* Not the right request to make on this network?
668 * (i.e. an A request made on IPv6 or an AAAA request
669 * made on IPv4, on LLMNR or mDNS.) */
670 dns_transaction_complete(t
, DNS_TRANSACTION_NO_SERVERS
);
676 if (t
->scope
->protocol
== DNS_PROTOCOL_LLMNR
&&
677 (dns_name_endswith(DNS_RESOURCE_KEY_NAME(t
->key
), "in-addr.arpa") > 0 ||
678 dns_name_endswith(DNS_RESOURCE_KEY_NAME(t
->key
), "ip6.arpa") > 0)) {
680 /* RFC 4795, Section 2.4. says reverse lookups shall
681 * always be made via TCP on LLMNR */
682 r
= dns_transaction_open_tcp(t
);
684 /* Try via UDP, and if that fails due to large size try via TCP */
685 r
= dns_transaction_emit(t
);
687 r
= dns_transaction_open_tcp(t
);
690 /* No servers to send this to? */
691 dns_transaction_complete(t
, DNS_TRANSACTION_NO_SERVERS
);
694 if (t
->scope
->protocol
!= DNS_PROTOCOL_DNS
) {
695 dns_transaction_complete(t
, DNS_TRANSACTION_RESOURCES
);
699 /* Couldn't send? Try immediately again, with a new server */
700 dns_transaction_next_dns_server(t
);
702 return dns_transaction_go(t
);
705 r
= sd_event_add_time(
706 t
->scope
->manager
->event
,
707 &t
->timeout_event_source
,
708 clock_boottime_or_monotonic(),
709 ts
+ transaction_get_resend_timeout(t
), 0,
710 on_transaction_timeout
, t
);
714 t
->state
= DNS_TRANSACTION_PENDING
;
718 static const char* const dns_transaction_state_table
[_DNS_TRANSACTION_STATE_MAX
] = {
719 [DNS_TRANSACTION_NULL
] = "null",
720 [DNS_TRANSACTION_PENDING
] = "pending",
721 [DNS_TRANSACTION_FAILURE
] = "failure",
722 [DNS_TRANSACTION_SUCCESS
] = "success",
723 [DNS_TRANSACTION_NO_SERVERS
] = "no-servers",
724 [DNS_TRANSACTION_TIMEOUT
] = "timeout",
725 [DNS_TRANSACTION_ATTEMPTS_MAX_REACHED
] = "attempts-max-reached",
726 [DNS_TRANSACTION_INVALID_REPLY
] = "invalid-reply",
727 [DNS_TRANSACTION_RESOURCES
] = "resources",
728 [DNS_TRANSACTION_ABORTED
] = "aborted",
730 DEFINE_STRING_TABLE_LOOKUP(dns_transaction_state
, DnsTransactionState
);