]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/resolve/resolved-dns-transaction.c
Merge pull request #746 from teg/resolved-connect-udp
[thirdparty/systemd.git] / src / resolve / resolved-dns-transaction.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4 This file is part of systemd.
5
6 Copyright 2014 Lennart Poettering
7
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.
12
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.
17
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/>.
20 ***/
21
22 #include "af-list.h"
23
24 #include "resolved-llmnr.h"
25 #include "resolved-dns-transaction.h"
26 #include "random-util.h"
27
28 DnsTransaction* dns_transaction_free(DnsTransaction *t) {
29 DnsQuery *q;
30 DnsZoneItem *i;
31
32 if (!t)
33 return NULL;
34
35 sd_event_source_unref(t->timeout_event_source);
36
37 dns_question_unref(t->question);
38 dns_packet_unref(t->sent);
39 dns_packet_unref(t->received);
40 dns_answer_unref(t->cached);
41
42 sd_event_source_unref(t->dns_event_source);
43 safe_close(t->dns_fd);
44
45 dns_server_unref(t->server);
46 dns_stream_free(t->stream);
47
48 if (t->scope) {
49 LIST_REMOVE(transactions_by_scope, t->scope->transactions, t);
50
51 if (t->id != 0)
52 hashmap_remove(t->scope->manager->dns_transactions, UINT_TO_PTR(t->id));
53 }
54
55 while ((q = set_steal_first(t->queries)))
56 set_remove(q->transactions, t);
57 set_free(t->queries);
58
59 while ((i = set_steal_first(t->zone_items)))
60 i->probe_transaction = NULL;
61 set_free(t->zone_items);
62
63 free(t);
64 return NULL;
65 }
66
67 DEFINE_TRIVIAL_CLEANUP_FUNC(DnsTransaction*, dns_transaction_free);
68
69 void dns_transaction_gc(DnsTransaction *t) {
70 assert(t);
71
72 if (t->block_gc > 0)
73 return;
74
75 if (set_isempty(t->queries) && set_isempty(t->zone_items))
76 dns_transaction_free(t);
77 }
78
79 int dns_transaction_new(DnsTransaction **ret, DnsScope *s, DnsQuestion *q) {
80 _cleanup_(dns_transaction_freep) DnsTransaction *t = NULL;
81 int r;
82
83 assert(ret);
84 assert(s);
85 assert(q);
86
87 r = hashmap_ensure_allocated(&s->manager->dns_transactions, NULL);
88 if (r < 0)
89 return r;
90
91 t = new0(DnsTransaction, 1);
92 if (!t)
93 return -ENOMEM;
94
95 t->dns_fd = -1;
96
97 t->question = dns_question_ref(q);
98
99 do
100 random_bytes(&t->id, sizeof(t->id));
101 while (t->id == 0 ||
102 hashmap_get(s->manager->dns_transactions, UINT_TO_PTR(t->id)));
103
104 r = hashmap_put(s->manager->dns_transactions, UINT_TO_PTR(t->id), t);
105 if (r < 0) {
106 t->id = 0;
107 return r;
108 }
109
110 LIST_PREPEND(transactions_by_scope, s->transactions, t);
111 t->scope = s;
112
113 if (ret)
114 *ret = t;
115
116 t = NULL;
117
118 return 0;
119 }
120
121 static void dns_transaction_stop(DnsTransaction *t) {
122 assert(t);
123
124 t->timeout_event_source = sd_event_source_unref(t->timeout_event_source);
125 t->stream = dns_stream_free(t->stream);
126 }
127
128 static void dns_transaction_tentative(DnsTransaction *t, DnsPacket *p) {
129 _cleanup_free_ char *pretty = NULL;
130 DnsZoneItem *z;
131
132 assert(t);
133 assert(p);
134
135 if (manager_our_packet(t->scope->manager, p) != 0)
136 return;
137
138 in_addr_to_string(p->family, &p->sender, &pretty);
139
140 log_debug("Transaction on scope %s on %s/%s got tentative packet from %s",
141 dns_protocol_to_string(t->scope->protocol),
142 t->scope->link ? t->scope->link->name : "*",
143 t->scope->family == AF_UNSPEC ? "*" : af_to_name(t->scope->family),
144 pretty);
145
146 /* RFC 4795, Section 4.1 says that the peer with the
147 * lexicographically smaller IP address loses */
148 if (memcmp(&p->sender, &p->destination, FAMILY_ADDRESS_SIZE(p->family)) >= 0) {
149 log_debug("Peer has lexicographically larger IP address and thus lost in the conflict.");
150 return;
151 }
152
153 log_debug("We have the lexicographically larger IP address and thus lost in the conflict.");
154
155 t->block_gc++;
156 while ((z = set_first(t->zone_items))) {
157 /* First, make sure the zone item drops the reference
158 * to us */
159 dns_zone_item_probe_stop(z);
160
161 /* Secondly, report this as conflict, so that we might
162 * look for a different hostname */
163 dns_zone_item_conflict(z);
164 }
165 t->block_gc--;
166
167 dns_transaction_gc(t);
168 }
169
170 void dns_transaction_complete(DnsTransaction *t, DnsTransactionState state) {
171 DnsQuery *q;
172 DnsZoneItem *z;
173 Iterator i;
174
175 assert(t);
176 assert(!IN_SET(state, DNS_TRANSACTION_NULL, DNS_TRANSACTION_PENDING));
177
178 if (!IN_SET(t->state, DNS_TRANSACTION_NULL, DNS_TRANSACTION_PENDING))
179 return;
180
181 /* Note that this call might invalidate the query. Callers
182 * should hence not attempt to access the query or transaction
183 * after calling this function. */
184
185 log_debug("Transaction on scope %s on %s/%s now complete with <%s>",
186 dns_protocol_to_string(t->scope->protocol),
187 t->scope->link ? t->scope->link->name : "*",
188 t->scope->family == AF_UNSPEC ? "*" : af_to_name(t->scope->family),
189 dns_transaction_state_to_string(state));
190
191 t->state = state;
192
193 dns_transaction_stop(t);
194
195 /* Notify all queries that are interested, but make sure the
196 * transaction isn't freed while we are still looking at it */
197 t->block_gc++;
198 SET_FOREACH(q, t->queries, i)
199 dns_query_ready(q);
200 SET_FOREACH(z, t->zone_items, i)
201 dns_zone_item_ready(z);
202 t->block_gc--;
203
204 dns_transaction_gc(t);
205 }
206
207 static int on_stream_complete(DnsStream *s, int error) {
208 _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
209 DnsTransaction *t;
210
211 assert(s);
212 assert(s->transaction);
213
214 /* Copy the data we care about out of the stream before we
215 * destroy it. */
216 t = s->transaction;
217 p = dns_packet_ref(s->read_packet);
218
219 t->stream = dns_stream_free(t->stream);
220
221 if (error != 0) {
222 dns_transaction_complete(t, DNS_TRANSACTION_RESOURCES);
223 return 0;
224 }
225
226 if (dns_packet_validate_reply(p) <= 0) {
227 log_debug("Invalid LLMNR TCP packet.");
228 dns_transaction_complete(t, DNS_TRANSACTION_INVALID_REPLY);
229 return 0;
230 }
231
232 dns_scope_check_conflicts(t->scope, p);
233
234 t->block_gc++;
235 dns_transaction_process_reply(t, p);
236 t->block_gc--;
237
238 /* If the response wasn't useful, then complete the transition now */
239 if (t->state == DNS_TRANSACTION_PENDING)
240 dns_transaction_complete(t, DNS_TRANSACTION_INVALID_REPLY);
241
242 return 0;
243 }
244
245 static int dns_transaction_open_tcp(DnsTransaction *t) {
246 DnsServer *server = NULL;
247 _cleanup_close_ int fd = -1;
248 int r;
249
250 assert(t);
251
252 if (t->stream)
253 return 0;
254
255 if (t->scope->protocol == DNS_PROTOCOL_DNS)
256 fd = dns_scope_tcp_socket(t->scope, AF_UNSPEC, NULL, 53, &server);
257 else if (t->scope->protocol == DNS_PROTOCOL_LLMNR) {
258
259 /* When we already received a query to this (but it was truncated), send to its sender address */
260 if (t->received)
261 fd = dns_scope_tcp_socket(t->scope, t->received->family, &t->received->sender, t->received->sender_port, NULL);
262 else {
263 union in_addr_union address;
264 int family = AF_UNSPEC;
265
266 /* Otherwise, try to talk to the owner of a
267 * the IP address, in case this is a reverse
268 * PTR lookup */
269 r = dns_question_extract_reverse_address(t->question, &family, &address);
270 if (r < 0)
271 return r;
272 if (r == 0)
273 return -EINVAL;
274
275 fd = dns_scope_tcp_socket(t->scope, family, &address, LLMNR_PORT, NULL);
276 }
277 } else
278 return -EAFNOSUPPORT;
279
280 if (fd < 0)
281 return fd;
282
283 r = dns_stream_new(t->scope->manager, &t->stream, t->scope->protocol, fd);
284 if (r < 0)
285 return r;
286
287 fd = -1;
288
289 r = dns_stream_write_packet(t->stream, t->sent);
290 if (r < 0) {
291 t->stream = dns_stream_free(t->stream);
292 return r;
293 }
294
295
296 dns_server_unref(t->server);
297 t->server = dns_server_ref(server);
298 t->received = dns_packet_unref(t->received);
299 t->stream->complete = on_stream_complete;
300 t->stream->transaction = t;
301
302 /* The interface index is difficult to determine if we are
303 * connecting to the local host, hence fill this in right away
304 * instead of determining it from the socket */
305 if (t->scope->link)
306 t->stream->ifindex = t->scope->link->ifindex;
307
308 return 0;
309 }
310
311 static void dns_transaction_next_dns_server(DnsTransaction *t) {
312 assert(t);
313
314 t->server = dns_server_unref(t->server);
315 t->dns_event_source = sd_event_source_unref(t->dns_event_source);
316 t->dns_fd = safe_close(t->dns_fd);
317
318 dns_scope_next_dns_server(t->scope);
319 }
320
321 void dns_transaction_process_reply(DnsTransaction *t, DnsPacket *p) {
322 int r;
323
324 assert(t);
325 assert(p);
326 assert(t->state == DNS_TRANSACTION_PENDING);
327
328 /* Note that this call might invalidate the query. Callers
329 * should hence not attempt to access the query or transaction
330 * after calling this function. */
331
332 if (t->scope->protocol == DNS_PROTOCOL_LLMNR) {
333 assert(t->scope->link);
334
335 /* For LLMNR we will not accept any packets from other
336 * interfaces */
337
338 if (p->ifindex != t->scope->link->ifindex)
339 return;
340
341 if (p->family != t->scope->family)
342 return;
343
344 /* Tentative packets are not full responses but still
345 * useful for identifying uniqueness conflicts during
346 * probing. */
347 if (DNS_PACKET_LLMNR_T(p)) {
348 dns_transaction_tentative(t, p);
349 return;
350 }
351 }
352
353 if (t->received != p) {
354 dns_packet_unref(t->received);
355 t->received = dns_packet_ref(p);
356 }
357
358 if (p->ipproto == IPPROTO_TCP) {
359 if (DNS_PACKET_TC(p)) {
360 /* Truncated via TCP? Somebody must be fucking with us */
361 dns_transaction_complete(t, DNS_TRANSACTION_INVALID_REPLY);
362 return;
363 }
364
365 if (DNS_PACKET_ID(p) != t->id) {
366 /* Not the reply to our query? Somebody must be fucking with us */
367 dns_transaction_complete(t, DNS_TRANSACTION_INVALID_REPLY);
368 return;
369 }
370 }
371
372 if (DNS_PACKET_TC(p)) {
373 /* Response was truncated, let's try again with good old TCP */
374 r = dns_transaction_open_tcp(t);
375 if (r == -ESRCH) {
376 /* No servers found? Damn! */
377 dns_transaction_complete(t, DNS_TRANSACTION_NO_SERVERS);
378 return;
379 }
380 if (r < 0) {
381 /* On LLMNR, if we cannot connect to the host,
382 * we immediately give up */
383 if (t->scope->protocol == DNS_PROTOCOL_LLMNR) {
384 dns_transaction_complete(t, DNS_TRANSACTION_RESOURCES);
385 return;
386 }
387
388 /* On DNS, couldn't send? Try immediately again, with a new server */
389 dns_transaction_next_dns_server(t);
390
391 r = dns_transaction_go(t);
392 if (r < 0) {
393 dns_transaction_complete(t, DNS_TRANSACTION_RESOURCES);
394 return;
395 }
396
397 return;
398 }
399 }
400
401 /* Parse and update the cache */
402 r = dns_packet_extract(p);
403 if (r < 0) {
404 dns_transaction_complete(t, DNS_TRANSACTION_INVALID_REPLY);
405 return;
406 }
407
408 /* Only consider responses with equivalent query section to the request */
409 if (!dns_question_is_superset(p->question, t->question) ||
410 !dns_question_is_superset(t->question, p->question)) {
411 dns_transaction_complete(t, DNS_TRANSACTION_INVALID_REPLY);
412 return;
413 }
414
415 /* According to RFC 4795, section 2.9. only the RRs from the answer section shall be cached */
416 dns_cache_put(&t->scope->cache, p->question, DNS_PACKET_RCODE(p), p->answer, DNS_PACKET_ANCOUNT(p), 0, p->family, &p->sender);
417
418 if (DNS_PACKET_RCODE(p) == DNS_RCODE_SUCCESS)
419 dns_transaction_complete(t, DNS_TRANSACTION_SUCCESS);
420 else
421 dns_transaction_complete(t, DNS_TRANSACTION_FAILURE);
422 }
423
424 static int on_dns_packet(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
425 _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
426 DnsTransaction *t = userdata;
427 int r;
428
429 assert(t);
430 assert(t->scope);
431
432 r = manager_recv(t->scope->manager, fd, DNS_PROTOCOL_DNS, &p);
433 if (r <= 0)
434 return r;
435
436 if (dns_packet_validate_reply(p) > 0 &&
437 DNS_PACKET_ID(p) == t->id) {
438 dns_transaction_process_reply(t, p);
439 } else
440 log_debug("Invalid DNS packet.");
441
442 return 0;
443 }
444
445 static int dns_transaction_emit(DnsTransaction *t) {
446 int r;
447
448 assert(t);
449
450 if (t->scope->protocol == DNS_PROTOCOL_DNS && !t->server) {
451 DnsServer *server = NULL;
452 _cleanup_close_ int fd = -1;
453
454 fd = dns_scope_udp_dns_socket(t->scope, &server);
455 if (fd < 0)
456 return fd;
457
458 r = sd_event_add_io(t->scope->manager->event, &t->dns_event_source, fd, EPOLLIN, on_dns_packet, t);
459 if (r < 0)
460 return r;
461
462 t->dns_fd = fd;
463 fd = -1;
464 t->server = dns_server_ref(server);
465 }
466
467 r = dns_scope_emit(t->scope, t->dns_fd, t->sent);
468 if (r < 0)
469 return r;
470
471 return 0;
472 }
473
474 static int on_transaction_timeout(sd_event_source *s, usec_t usec, void *userdata) {
475 DnsTransaction *t = userdata;
476 int r;
477
478 assert(s);
479 assert(t);
480
481 /* Timeout reached? Try again, with a new server */
482 dns_transaction_next_dns_server(t);
483
484 r = dns_transaction_go(t);
485 if (r < 0)
486 dns_transaction_complete(t, DNS_TRANSACTION_RESOURCES);
487
488 return 0;
489 }
490
491 static int dns_transaction_make_packet(DnsTransaction *t) {
492 _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
493 unsigned n, added = 0;
494 int r;
495
496 assert(t);
497
498 if (t->sent)
499 return 0;
500
501 r = dns_packet_new_query(&p, t->scope->protocol, 0);
502 if (r < 0)
503 return r;
504
505 for (n = 0; n < t->question->n_keys; n++) {
506 r = dns_scope_good_key(t->scope, t->question->keys[n]);
507 if (r < 0)
508 return r;
509 if (r == 0)
510 continue;
511
512 r = dns_packet_append_key(p, t->question->keys[n], NULL);
513 if (r < 0)
514 return r;
515
516 added++;
517 }
518
519 if (added <= 0)
520 return -EDOM;
521
522 DNS_PACKET_HEADER(p)->qdcount = htobe16(added);
523 DNS_PACKET_HEADER(p)->id = t->id;
524
525 t->sent = p;
526 p = NULL;
527
528 return 0;
529 }
530
531 int dns_transaction_go(DnsTransaction *t) {
532 bool had_stream;
533 int r;
534
535 assert(t);
536
537 had_stream = !!t->stream;
538
539 dns_transaction_stop(t);
540
541 log_debug("Excercising transaction on scope %s on %s/%s",
542 dns_protocol_to_string(t->scope->protocol),
543 t->scope->link ? t->scope->link->name : "*",
544 t->scope->family == AF_UNSPEC ? "*" : af_to_name(t->scope->family));
545
546 if (t->n_attempts >= TRANSACTION_ATTEMPTS_MAX(t->scope->protocol)) {
547 dns_transaction_complete(t, DNS_TRANSACTION_ATTEMPTS_MAX_REACHED);
548 return 0;
549 }
550
551 if (t->scope->protocol == DNS_PROTOCOL_LLMNR && had_stream) {
552 /* If we already tried via a stream, then we don't
553 * retry on LLMNR. See RFC 4795, Section 2.7. */
554 dns_transaction_complete(t, DNS_TRANSACTION_ATTEMPTS_MAX_REACHED);
555 return 0;
556 }
557
558 t->n_attempts++;
559 t->received = dns_packet_unref(t->received);
560 t->cached = dns_answer_unref(t->cached);
561 t->cached_rcode = 0;
562
563 /* Check the cache, but only if this transaction is not used
564 * for probing or verifying a zone item. */
565 if (set_isempty(t->zone_items)) {
566
567 /* Before trying the cache, let's make sure we figured out a
568 * server to use. Should this cause a change of server this
569 * might flush the cache. */
570 dns_scope_get_dns_server(t->scope);
571
572 /* Let's then prune all outdated entries */
573 dns_cache_prune(&t->scope->cache);
574
575 r = dns_cache_lookup(&t->scope->cache, t->question, &t->cached_rcode, &t->cached);
576 if (r < 0)
577 return r;
578 if (r > 0) {
579 log_debug("Cache hit!");
580 if (t->cached_rcode == DNS_RCODE_SUCCESS)
581 dns_transaction_complete(t, DNS_TRANSACTION_SUCCESS);
582 else
583 dns_transaction_complete(t, DNS_TRANSACTION_FAILURE);
584 return 0;
585 }
586 }
587
588 if (t->scope->protocol == DNS_PROTOCOL_LLMNR && !t->initial_jitter) {
589 usec_t jitter;
590
591 /* RFC 4795 Section 2.7 suggests all queries should be
592 * delayed by a random time from 0 to JITTER_INTERVAL. */
593
594 t->initial_jitter = true;
595
596 random_bytes(&jitter, sizeof(jitter));
597 jitter %= LLMNR_JITTER_INTERVAL_USEC;
598
599 r = sd_event_add_time(
600 t->scope->manager->event,
601 &t->timeout_event_source,
602 clock_boottime_or_monotonic(),
603 now(clock_boottime_or_monotonic()) + jitter,
604 LLMNR_JITTER_INTERVAL_USEC,
605 on_transaction_timeout, t);
606 if (r < 0)
607 return r;
608
609 t->n_attempts = 0;
610 t->state = DNS_TRANSACTION_PENDING;
611
612 log_debug("Delaying LLMNR transaction for " USEC_FMT "us.", jitter);
613 return 0;
614 }
615
616 log_debug("Cache miss!");
617
618 /* Otherwise, we need to ask the network */
619 r = dns_transaction_make_packet(t);
620 if (r == -EDOM) {
621 /* Not the right request to make on this network?
622 * (i.e. an A request made on IPv6 or an AAAA request
623 * made on IPv4, on LLMNR or mDNS.) */
624 dns_transaction_complete(t, DNS_TRANSACTION_NO_SERVERS);
625 return 0;
626 }
627 if (r < 0)
628 return r;
629
630 if (t->scope->protocol == DNS_PROTOCOL_LLMNR &&
631 (dns_question_endswith(t->question, "in-addr.arpa") > 0 ||
632 dns_question_endswith(t->question, "ip6.arpa") > 0)) {
633
634 /* RFC 4795, Section 2.4. says reverse lookups shall
635 * always be made via TCP on LLMNR */
636 r = dns_transaction_open_tcp(t);
637 } else {
638 /* Try via UDP, and if that fails due to large size try via TCP */
639 r = dns_transaction_emit(t);
640 if (r == -EMSGSIZE)
641 r = dns_transaction_open_tcp(t);
642 }
643 if (r == -ESRCH) {
644 /* No servers to send this to? */
645 dns_transaction_complete(t, DNS_TRANSACTION_NO_SERVERS);
646 return 0;
647 } else if (r < 0) {
648 if (t->scope->protocol != DNS_PROTOCOL_DNS) {
649 dns_transaction_complete(t, DNS_TRANSACTION_RESOURCES);
650 return 0;
651 }
652
653 /* Couldn't send? Try immediately again, with a new server */
654 dns_transaction_next_dns_server(t);
655
656 return dns_transaction_go(t);
657 }
658
659 r = sd_event_add_time(
660 t->scope->manager->event,
661 &t->timeout_event_source,
662 clock_boottime_or_monotonic(),
663 now(clock_boottime_or_monotonic()) + TRANSACTION_TIMEOUT_USEC(t->scope->protocol), 0,
664 on_transaction_timeout, t);
665 if (r < 0)
666 return r;
667
668 t->state = DNS_TRANSACTION_PENDING;
669 return 1;
670 }
671
672 static const char* const dns_transaction_state_table[_DNS_TRANSACTION_STATE_MAX] = {
673 [DNS_TRANSACTION_NULL] = "null",
674 [DNS_TRANSACTION_PENDING] = "pending",
675 [DNS_TRANSACTION_FAILURE] = "failure",
676 [DNS_TRANSACTION_SUCCESS] = "success",
677 [DNS_TRANSACTION_NO_SERVERS] = "no-servers",
678 [DNS_TRANSACTION_TIMEOUT] = "timeout",
679 [DNS_TRANSACTION_ATTEMPTS_MAX_REACHED] = "attempts-max-reached",
680 [DNS_TRANSACTION_INVALID_REPLY] = "invalid-reply",
681 [DNS_TRANSACTION_RESOURCES] = "resources",
682 [DNS_TRANSACTION_ABORTED] = "aborted",
683 };
684 DEFINE_STRING_TABLE_LOOKUP(dns_transaction_state, DnsTransactionState);