]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/resolve/resolved-dns-scope.c
Merge pull request #2040 from keszybz/randomized-delay
[thirdparty/systemd.git] / src / resolve / resolved-dns-scope.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 <netinet/tcp.h>
23
24 #include "af-list.h"
25 #include "alloc-util.h"
26 #include "dns-domain.h"
27 #include "fd-util.h"
28 #include "hostname-util.h"
29 #include "missing.h"
30 #include "random-util.h"
31 #include "resolved-dns-scope.h"
32 #include "resolved-llmnr.h"
33 #include "socket-util.h"
34 #include "strv.h"
35
36 #define MULTICAST_RATELIMIT_INTERVAL_USEC (1*USEC_PER_SEC)
37 #define MULTICAST_RATELIMIT_BURST 1000
38
39 /* After how much time to repeat LLMNR requests, see RFC 4795 Section 7 */
40 #define MULTICAST_RESEND_TIMEOUT_MIN_USEC (100 * USEC_PER_MSEC)
41 #define MULTICAST_RESEND_TIMEOUT_MAX_USEC (1 * USEC_PER_SEC)
42
43 int dns_scope_new(Manager *m, DnsScope **ret, Link *l, DnsProtocol protocol, int family) {
44 DnsScope *s;
45
46 assert(m);
47 assert(ret);
48
49 s = new0(DnsScope, 1);
50 if (!s)
51 return -ENOMEM;
52
53 s->manager = m;
54 s->link = l;
55 s->protocol = protocol;
56 s->family = family;
57 s->resend_timeout = MULTICAST_RESEND_TIMEOUT_MIN_USEC;
58
59 LIST_PREPEND(scopes, m->dns_scopes, s);
60
61 dns_scope_llmnr_membership(s, true);
62
63 log_debug("New scope on link %s, protocol %s, family %s", l ? l->name : "*", dns_protocol_to_string(protocol), family == AF_UNSPEC ? "*" : af_to_name(family));
64
65 /* Enforce ratelimiting for the multicast protocols */
66 RATELIMIT_INIT(s->ratelimit, MULTICAST_RATELIMIT_INTERVAL_USEC, MULTICAST_RATELIMIT_BURST);
67
68 *ret = s;
69 return 0;
70 }
71
72 static void dns_scope_abort_transactions(DnsScope *s) {
73 assert(s);
74
75 while (s->transactions) {
76 DnsTransaction *t = s->transactions;
77
78 /* Abort the transaction, but make sure it is not
79 * freed while we still look at it */
80
81 t->block_gc++;
82 dns_transaction_complete(t, DNS_TRANSACTION_ABORTED);
83 t->block_gc--;
84
85 dns_transaction_free(t);
86 }
87 }
88
89 DnsScope* dns_scope_free(DnsScope *s) {
90 DnsResourceRecord *rr;
91
92 if (!s)
93 return NULL;
94
95 log_debug("Removing scope on link %s, protocol %s, family %s", s->link ? s->link->name : "*", dns_protocol_to_string(s->protocol), s->family == AF_UNSPEC ? "*" : af_to_name(s->family));
96
97 dns_scope_llmnr_membership(s, false);
98 dns_scope_abort_transactions(s);
99
100 while (s->query_candidates)
101 dns_query_candidate_free(s->query_candidates);
102
103 hashmap_free(s->transactions_by_key);
104
105 while ((rr = ordered_hashmap_steal_first(s->conflict_queue)))
106 dns_resource_record_unref(rr);
107
108 ordered_hashmap_free(s->conflict_queue);
109 sd_event_source_unref(s->conflict_event_source);
110
111 dns_cache_flush(&s->cache);
112 dns_zone_flush(&s->zone);
113
114 LIST_REMOVE(scopes, s->manager->dns_scopes, s);
115 free(s);
116
117 return NULL;
118 }
119
120 DnsServer *dns_scope_get_dns_server(DnsScope *s) {
121 assert(s);
122
123 if (s->protocol != DNS_PROTOCOL_DNS)
124 return NULL;
125
126 if (s->link)
127 return link_get_dns_server(s->link);
128 else
129 return manager_get_dns_server(s->manager);
130 }
131
132 void dns_scope_next_dns_server(DnsScope *s) {
133 assert(s);
134
135 if (s->protocol != DNS_PROTOCOL_DNS)
136 return;
137
138 if (s->link)
139 link_next_dns_server(s->link);
140 else
141 manager_next_dns_server(s->manager);
142 }
143
144 void dns_scope_packet_received(DnsScope *s, usec_t rtt) {
145 assert(s);
146
147 if (rtt <= s->max_rtt)
148 return;
149
150 s->max_rtt = rtt;
151 s->resend_timeout = MIN(MAX(MULTICAST_RESEND_TIMEOUT_MIN_USEC, s->max_rtt * 2), MULTICAST_RESEND_TIMEOUT_MAX_USEC);
152 }
153
154 void dns_scope_packet_lost(DnsScope *s, usec_t usec) {
155 assert(s);
156
157 if (s->resend_timeout <= usec)
158 s->resend_timeout = MIN(s->resend_timeout * 2, MULTICAST_RESEND_TIMEOUT_MAX_USEC);
159 }
160
161 int dns_scope_emit(DnsScope *s, int fd, DnsPacket *p) {
162 union in_addr_union addr;
163 int ifindex = 0, r;
164 int family;
165 uint16_t port;
166 uint32_t mtu;
167
168 assert(s);
169 assert(p);
170 assert(p->protocol == s->protocol);
171 assert((s->protocol == DNS_PROTOCOL_DNS) != (fd < 0));
172
173 if (s->link) {
174 mtu = s->link->mtu;
175 ifindex = s->link->ifindex;
176 } else
177 mtu = manager_find_mtu(s->manager);
178
179 switch (s->protocol) {
180 case DNS_PROTOCOL_DNS:
181 if (DNS_PACKET_QDCOUNT(p) > 1)
182 return -EOPNOTSUPP;
183
184 if (p->size > DNS_PACKET_UNICAST_SIZE_MAX)
185 return -EMSGSIZE;
186
187 if (p->size + UDP_PACKET_HEADER_SIZE > mtu)
188 return -EMSGSIZE;
189
190 r = manager_write(s->manager, fd, p);
191 if (r < 0)
192 return r;
193
194 break;
195
196 case DNS_PROTOCOL_LLMNR:
197 if (DNS_PACKET_QDCOUNT(p) > 1)
198 return -EOPNOTSUPP;
199
200 if (!ratelimit_test(&s->ratelimit))
201 return -EBUSY;
202
203 family = s->family;
204 port = LLMNR_PORT;
205
206 if (family == AF_INET) {
207 addr.in = LLMNR_MULTICAST_IPV4_ADDRESS;
208 fd = manager_llmnr_ipv4_udp_fd(s->manager);
209 } else if (family == AF_INET6) {
210 addr.in6 = LLMNR_MULTICAST_IPV6_ADDRESS;
211 fd = manager_llmnr_ipv6_udp_fd(s->manager);
212 } else
213 return -EAFNOSUPPORT;
214 if (fd < 0)
215 return fd;
216
217 r = manager_send(s->manager, fd, ifindex, family, &addr, port, p);
218 if (r < 0)
219 return r;
220
221 break;
222
223 default:
224 return -EAFNOSUPPORT;
225 }
226
227 return 1;
228 }
229
230 static int dns_scope_socket(DnsScope *s, int type, int family, const union in_addr_union *address, uint16_t port, DnsServer **server) {
231 DnsServer *srv = NULL;
232 _cleanup_close_ int fd = -1;
233 union sockaddr_union sa = {};
234 socklen_t salen;
235 static const int one = 1;
236 int ret, r;
237
238 assert(s);
239 assert((family == AF_UNSPEC) == !address);
240
241 if (family == AF_UNSPEC) {
242 srv = dns_scope_get_dns_server(s);
243 if (!srv)
244 return -ESRCH;
245
246 sa.sa.sa_family = srv->family;
247 if (srv->family == AF_INET) {
248 sa.in.sin_port = htobe16(port);
249 sa.in.sin_addr = srv->address.in;
250 salen = sizeof(sa.in);
251 } else if (srv->family == AF_INET6) {
252 sa.in6.sin6_port = htobe16(port);
253 sa.in6.sin6_addr = srv->address.in6;
254 sa.in6.sin6_scope_id = s->link ? s->link->ifindex : 0;
255 salen = sizeof(sa.in6);
256 } else
257 return -EAFNOSUPPORT;
258 } else {
259 sa.sa.sa_family = family;
260
261 if (family == AF_INET) {
262 sa.in.sin_port = htobe16(port);
263 sa.in.sin_addr = address->in;
264 salen = sizeof(sa.in);
265 } else if (family == AF_INET6) {
266 sa.in6.sin6_port = htobe16(port);
267 sa.in6.sin6_addr = address->in6;
268 sa.in6.sin6_scope_id = s->link ? s->link->ifindex : 0;
269 salen = sizeof(sa.in6);
270 } else
271 return -EAFNOSUPPORT;
272 }
273
274 fd = socket(sa.sa.sa_family, type|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
275 if (fd < 0)
276 return -errno;
277
278 if (type == SOCK_STREAM) {
279 r = setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &one, sizeof(one));
280 if (r < 0)
281 return -errno;
282 }
283
284 if (s->link) {
285 uint32_t ifindex = htobe32(s->link->ifindex);
286
287 if (sa.sa.sa_family == AF_INET) {
288 r = setsockopt(fd, IPPROTO_IP, IP_UNICAST_IF, &ifindex, sizeof(ifindex));
289 if (r < 0)
290 return -errno;
291 } else if (sa.sa.sa_family == AF_INET6) {
292 r = setsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_IF, &ifindex, sizeof(ifindex));
293 if (r < 0)
294 return -errno;
295 }
296 }
297
298 if (s->protocol == DNS_PROTOCOL_LLMNR) {
299 /* RFC 4795, section 2.5 requires the TTL to be set to 1 */
300
301 if (sa.sa.sa_family == AF_INET) {
302 r = setsockopt(fd, IPPROTO_IP, IP_TTL, &one, sizeof(one));
303 if (r < 0)
304 return -errno;
305 } else if (sa.sa.sa_family == AF_INET6) {
306 r = setsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &one, sizeof(one));
307 if (r < 0)
308 return -errno;
309 }
310 }
311
312 r = connect(fd, &sa.sa, salen);
313 if (r < 0 && errno != EINPROGRESS)
314 return -errno;
315
316 if (server)
317 *server = srv;
318
319 ret = fd;
320 fd = -1;
321
322 return ret;
323 }
324
325 int dns_scope_udp_dns_socket(DnsScope *s, DnsServer **server) {
326 return dns_scope_socket(s, SOCK_DGRAM, AF_UNSPEC, NULL, 53, server);
327 }
328
329 int dns_scope_tcp_socket(DnsScope *s, int family, const union in_addr_union *address, uint16_t port, DnsServer **server) {
330 return dns_scope_socket(s, SOCK_STREAM, family, address, port, server);
331 }
332
333 DnsScopeMatch dns_scope_good_domain(DnsScope *s, int ifindex, uint64_t flags, const char *domain) {
334 DnsSearchDomain *d;
335
336 assert(s);
337 assert(domain);
338
339 if (ifindex != 0 && (!s->link || s->link->ifindex != ifindex))
340 return DNS_SCOPE_NO;
341
342 if ((SD_RESOLVED_FLAGS_MAKE(s->protocol, s->family) & flags) == 0)
343 return DNS_SCOPE_NO;
344
345 if (dns_name_is_root(domain))
346 return DNS_SCOPE_NO;
347
348 /* Never resolve any loopback hostname or IP address via DNS,
349 * LLMNR or mDNS. Instead, always rely on synthesized RRs for
350 * these. */
351 if (is_localhost(domain) ||
352 dns_name_endswith(domain, "127.in-addr.arpa") > 0 ||
353 dns_name_equal(domain, "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa") > 0)
354 return DNS_SCOPE_NO;
355
356 /* Always honour search domains for routing queries. Note that
357 * we return DNS_SCOPE_YES here, rather than just
358 * DNS_SCOPE_MAYBE, which means wildcard scopes won't be
359 * considered anymore. */
360 LIST_FOREACH(domains, d, dns_scope_get_search_domains(s))
361 if (dns_name_endswith(domain, d->name) > 0)
362 return DNS_SCOPE_YES;
363
364 switch (s->protocol) {
365
366 case DNS_PROTOCOL_DNS:
367
368 if ((!dns_name_is_single_label(domain) ||
369 (!(flags & SD_RESOLVED_NO_SEARCH) && dns_scope_has_search_domains(s))) &&
370 dns_name_endswith(domain, "254.169.in-addr.arpa") == 0 &&
371 dns_name_endswith(domain, "0.8.e.f.ip6.arpa") == 0)
372 return DNS_SCOPE_MAYBE;
373
374 return DNS_SCOPE_NO;
375
376 case DNS_PROTOCOL_MDNS:
377 if ((s->family == AF_INET && dns_name_endswith(domain, "in-addr.arpa") > 0) ||
378 (s->family == AF_INET6 && dns_name_endswith(domain, "ip6.arpa") > 0) ||
379 (dns_name_endswith(domain, "local") > 0 && /* only resolve names ending in .local via mDNS */
380 dns_name_equal(domain, "local") == 0 && /* but not the single-label "local" name itself */
381 manager_is_own_hostname(s->manager, domain) <= 0)) /* never resolve the local hostname via mDNS */
382 return DNS_SCOPE_MAYBE;
383
384 return DNS_SCOPE_NO;
385
386 case DNS_PROTOCOL_LLMNR:
387 if ((s->family == AF_INET && dns_name_endswith(domain, "in-addr.arpa") > 0) ||
388 (s->family == AF_INET6 && dns_name_endswith(domain, "ip6.arpa") > 0) ||
389 (dns_name_is_single_label(domain) && /* only resolve single label names via LLMNR */
390 !is_gateway_hostname(domain) && /* don't resolve "gateway" with LLMNR, let nss-myhostname handle this */
391 manager_is_own_hostname(s->manager, domain) <= 0)) /* never resolve the local hostname via LLMNR */
392 return DNS_SCOPE_MAYBE;
393
394 return DNS_SCOPE_NO;
395
396 default:
397 assert_not_reached("Unknown scope protocol");
398 }
399 }
400
401 int dns_scope_good_key(DnsScope *s, DnsResourceKey *key) {
402 assert(s);
403 assert(key);
404
405 if (s->protocol == DNS_PROTOCOL_DNS)
406 return true;
407
408 /* On mDNS and LLMNR, send A and AAAA queries only on the
409 * respective scopes */
410
411 if (s->family == AF_INET && key->class == DNS_CLASS_IN && key->type == DNS_TYPE_AAAA)
412 return false;
413
414 if (s->family == AF_INET6 && key->class == DNS_CLASS_IN && key->type == DNS_TYPE_A)
415 return false;
416
417 return true;
418 }
419
420 int dns_scope_llmnr_membership(DnsScope *s, bool b) {
421 int fd;
422
423 assert(s);
424
425 if (s->protocol != DNS_PROTOCOL_LLMNR)
426 return 0;
427
428 assert(s->link);
429
430 if (s->family == AF_INET) {
431 struct ip_mreqn mreqn = {
432 .imr_multiaddr = LLMNR_MULTICAST_IPV4_ADDRESS,
433 .imr_ifindex = s->link->ifindex,
434 };
435
436 fd = manager_llmnr_ipv4_udp_fd(s->manager);
437 if (fd < 0)
438 return fd;
439
440 /* Always first try to drop membership before we add
441 * one. This is necessary on some devices, such as
442 * veth. */
443 if (b)
444 (void) setsockopt(fd, IPPROTO_IP, IP_DROP_MEMBERSHIP, &mreqn, sizeof(mreqn));
445
446 if (setsockopt(fd, IPPROTO_IP, b ? IP_ADD_MEMBERSHIP : IP_DROP_MEMBERSHIP, &mreqn, sizeof(mreqn)) < 0)
447 return -errno;
448
449 } else if (s->family == AF_INET6) {
450 struct ipv6_mreq mreq = {
451 .ipv6mr_multiaddr = LLMNR_MULTICAST_IPV6_ADDRESS,
452 .ipv6mr_interface = s->link->ifindex,
453 };
454
455 fd = manager_llmnr_ipv6_udp_fd(s->manager);
456 if (fd < 0)
457 return fd;
458
459 if (b)
460 (void) setsockopt(fd, IPPROTO_IPV6, IPV6_DROP_MEMBERSHIP, &mreq, sizeof(mreq));
461
462 if (setsockopt(fd, IPPROTO_IPV6, b ? IPV6_ADD_MEMBERSHIP : IPV6_DROP_MEMBERSHIP, &mreq, sizeof(mreq)) < 0)
463 return -errno;
464 } else
465 return -EAFNOSUPPORT;
466
467 return 0;
468 }
469
470 static int dns_scope_make_reply_packet(
471 DnsScope *s,
472 uint16_t id,
473 int rcode,
474 DnsQuestion *q,
475 DnsAnswer *answer,
476 DnsAnswer *soa,
477 bool tentative,
478 DnsPacket **ret) {
479
480 _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
481 unsigned i;
482 int r;
483
484 assert(s);
485 assert(ret);
486
487 if ((!q || q->n_keys <= 0)
488 && (!answer || answer->n_rrs <= 0)
489 && (!soa || soa->n_rrs <= 0))
490 return -EINVAL;
491
492 r = dns_packet_new(&p, s->protocol, 0);
493 if (r < 0)
494 return r;
495
496 DNS_PACKET_HEADER(p)->id = id;
497 DNS_PACKET_HEADER(p)->flags = htobe16(DNS_PACKET_MAKE_FLAGS(
498 1 /* qr */,
499 0 /* opcode */,
500 0 /* c */,
501 0 /* tc */,
502 tentative,
503 0 /* (ra) */,
504 0 /* (ad) */,
505 0 /* (cd) */,
506 rcode));
507
508 if (q) {
509 for (i = 0; i < q->n_keys; i++) {
510 r = dns_packet_append_key(p, q->keys[i], NULL);
511 if (r < 0)
512 return r;
513 }
514
515 DNS_PACKET_HEADER(p)->qdcount = htobe16(q->n_keys);
516 }
517
518 if (answer) {
519 for (i = 0; i < answer->n_rrs; i++) {
520 r = dns_packet_append_rr(p, answer->items[i].rr, NULL);
521 if (r < 0)
522 return r;
523 }
524
525 DNS_PACKET_HEADER(p)->ancount = htobe16(answer->n_rrs);
526 }
527
528 if (soa) {
529 for (i = 0; i < soa->n_rrs; i++) {
530 r = dns_packet_append_rr(p, soa->items[i].rr, NULL);
531 if (r < 0)
532 return r;
533 }
534
535 DNS_PACKET_HEADER(p)->arcount = htobe16(soa->n_rrs);
536 }
537
538 *ret = p;
539 p = NULL;
540
541 return 0;
542 }
543
544 static void dns_scope_verify_conflicts(DnsScope *s, DnsPacket *p) {
545 unsigned n;
546
547 assert(s);
548 assert(p);
549
550 if (p->question)
551 for (n = 0; n < p->question->n_keys; n++)
552 dns_zone_verify_conflicts(&s->zone, p->question->keys[n]);
553 if (p->answer)
554 for (n = 0; n < p->answer->n_rrs; n++)
555 dns_zone_verify_conflicts(&s->zone, p->answer->items[n].rr->key);
556 }
557
558 void dns_scope_process_query(DnsScope *s, DnsStream *stream, DnsPacket *p) {
559 _cleanup_(dns_packet_unrefp) DnsPacket *reply = NULL;
560 _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL, *soa = NULL;
561 DnsResourceKey *key = NULL;
562 bool tentative = false;
563 int r, fd;
564
565 assert(s);
566 assert(p);
567
568 if (p->protocol != DNS_PROTOCOL_LLMNR)
569 return;
570
571 if (p->ipproto == IPPROTO_UDP) {
572 /* Don't accept UDP queries directed to anything but
573 * the LLMNR multicast addresses. See RFC 4795,
574 * section 2.5. */
575
576 if (p->family == AF_INET && !in_addr_equal(AF_INET, &p->destination, (union in_addr_union*) &LLMNR_MULTICAST_IPV4_ADDRESS))
577 return;
578
579 if (p->family == AF_INET6 && !in_addr_equal(AF_INET6, &p->destination, (union in_addr_union*) &LLMNR_MULTICAST_IPV6_ADDRESS))
580 return;
581 }
582
583 r = dns_packet_extract(p);
584 if (r < 0) {
585 log_debug_errno(r, "Failed to extract resources from incoming packet: %m");
586 return;
587 }
588
589 if (DNS_PACKET_LLMNR_C(p)) {
590 /* Somebody notified us about a possible conflict */
591 dns_scope_verify_conflicts(s, p);
592 return;
593 }
594
595 assert(p->question->n_keys == 1);
596 key = p->question->keys[0];
597
598 r = dns_zone_lookup(&s->zone, key, &answer, &soa, &tentative);
599 if (r < 0) {
600 log_debug_errno(r, "Failed to lookup key: %m");
601 return;
602 }
603 if (r == 0)
604 return;
605
606 if (answer)
607 dns_answer_order_by_scope(answer, in_addr_is_link_local(p->family, &p->sender) > 0);
608
609 r = dns_scope_make_reply_packet(s, DNS_PACKET_ID(p), DNS_RCODE_SUCCESS, p->question, answer, soa, tentative, &reply);
610 if (r < 0) {
611 log_debug_errno(r, "Failed to build reply packet: %m");
612 return;
613 }
614
615 if (stream)
616 r = dns_stream_write_packet(stream, reply);
617 else {
618 if (!ratelimit_test(&s->ratelimit))
619 return;
620
621 if (p->family == AF_INET)
622 fd = manager_llmnr_ipv4_udp_fd(s->manager);
623 else if (p->family == AF_INET6)
624 fd = manager_llmnr_ipv6_udp_fd(s->manager);
625 else {
626 log_debug("Unknown protocol");
627 return;
628 }
629 if (fd < 0) {
630 log_debug_errno(fd, "Failed to get reply socket: %m");
631 return;
632 }
633
634 /* Note that we always immediately reply to all LLMNR
635 * requests, and do not wait any time, since we
636 * verified uniqueness for all records. Also see RFC
637 * 4795, Section 2.7 */
638
639 r = manager_send(s->manager, fd, p->ifindex, p->family, &p->sender, p->sender_port, reply);
640 }
641
642 if (r < 0) {
643 log_debug_errno(r, "Failed to send reply packet: %m");
644 return;
645 }
646 }
647
648 DnsTransaction *dns_scope_find_transaction(DnsScope *scope, DnsResourceKey *key, bool cache_ok) {
649 DnsTransaction *t;
650
651 assert(scope);
652 assert(key);
653
654 /* Try to find an ongoing transaction that is a equal to the
655 * specified question */
656 t = hashmap_get(scope->transactions_by_key, key);
657 if (!t)
658 return NULL;
659
660 /* Refuse reusing transactions that completed based on cached
661 * data instead of a real packet, if that's requested. */
662 if (!cache_ok &&
663 IN_SET(t->state, DNS_TRANSACTION_SUCCESS, DNS_TRANSACTION_FAILURE) &&
664 t->answer_source != DNS_TRANSACTION_NETWORK)
665 return NULL;
666
667 return t;
668 }
669
670 static int dns_scope_make_conflict_packet(
671 DnsScope *s,
672 DnsResourceRecord *rr,
673 DnsPacket **ret) {
674
675 _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
676 int r;
677
678 assert(s);
679 assert(rr);
680 assert(ret);
681
682 r = dns_packet_new(&p, s->protocol, 0);
683 if (r < 0)
684 return r;
685
686 DNS_PACKET_HEADER(p)->flags = htobe16(DNS_PACKET_MAKE_FLAGS(
687 0 /* qr */,
688 0 /* opcode */,
689 1 /* conflict */,
690 0 /* tc */,
691 0 /* t */,
692 0 /* (ra) */,
693 0 /* (ad) */,
694 0 /* (cd) */,
695 0));
696 random_bytes(&DNS_PACKET_HEADER(p)->id, sizeof(uint16_t));
697 DNS_PACKET_HEADER(p)->qdcount = htobe16(1);
698 DNS_PACKET_HEADER(p)->arcount = htobe16(1);
699
700 r = dns_packet_append_key(p, rr->key, NULL);
701 if (r < 0)
702 return r;
703
704 r = dns_packet_append_rr(p, rr, NULL);
705 if (r < 0)
706 return r;
707
708 *ret = p;
709 p = NULL;
710
711 return 0;
712 }
713
714 static int on_conflict_dispatch(sd_event_source *es, usec_t usec, void *userdata) {
715 DnsScope *scope = userdata;
716 int r;
717
718 assert(es);
719 assert(scope);
720
721 scope->conflict_event_source = sd_event_source_unref(scope->conflict_event_source);
722
723 for (;;) {
724 _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
725 _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
726
727 rr = ordered_hashmap_steal_first(scope->conflict_queue);
728 if (!rr)
729 break;
730
731 r = dns_scope_make_conflict_packet(scope, rr, &p);
732 if (r < 0) {
733 log_error_errno(r, "Failed to make conflict packet: %m");
734 return 0;
735 }
736
737 r = dns_scope_emit(scope, -1, p);
738 if (r < 0)
739 log_debug_errno(r, "Failed to send conflict packet: %m");
740 }
741
742 return 0;
743 }
744
745 int dns_scope_notify_conflict(DnsScope *scope, DnsResourceRecord *rr) {
746 usec_t jitter;
747 int r;
748
749 assert(scope);
750 assert(rr);
751
752 /* We don't send these queries immediately. Instead, we queue
753 * them, and send them after some jitter delay. */
754 r = ordered_hashmap_ensure_allocated(&scope->conflict_queue, &dns_resource_key_hash_ops);
755 if (r < 0) {
756 log_oom();
757 return r;
758 }
759
760 /* We only place one RR per key in the conflict
761 * messages, not all of them. That should be enough to
762 * indicate where there might be a conflict */
763 r = ordered_hashmap_put(scope->conflict_queue, rr->key, rr);
764 if (r == -EEXIST || r == 0)
765 return 0;
766 if (r < 0)
767 return log_debug_errno(r, "Failed to queue conflicting RR: %m");
768
769 dns_resource_record_ref(rr);
770
771 if (scope->conflict_event_source)
772 return 0;
773
774 random_bytes(&jitter, sizeof(jitter));
775 jitter %= LLMNR_JITTER_INTERVAL_USEC;
776
777 r = sd_event_add_time(scope->manager->event,
778 &scope->conflict_event_source,
779 clock_boottime_or_monotonic(),
780 now(clock_boottime_or_monotonic()) + jitter,
781 LLMNR_JITTER_INTERVAL_USEC,
782 on_conflict_dispatch, scope);
783 if (r < 0)
784 return log_debug_errno(r, "Failed to add conflict dispatch event: %m");
785
786 return 0;
787 }
788
789 void dns_scope_check_conflicts(DnsScope *scope, DnsPacket *p) {
790 unsigned i;
791 int r;
792
793 assert(scope);
794 assert(p);
795
796 if (p->protocol != DNS_PROTOCOL_LLMNR)
797 return;
798
799 if (DNS_PACKET_RRCOUNT(p) <= 0)
800 return;
801
802 if (DNS_PACKET_LLMNR_C(p) != 0)
803 return;
804
805 if (DNS_PACKET_LLMNR_T(p) != 0)
806 return;
807
808 if (manager_our_packet(scope->manager, p))
809 return;
810
811 r = dns_packet_extract(p);
812 if (r < 0) {
813 log_debug_errno(r, "Failed to extract packet: %m");
814 return;
815 }
816
817 log_debug("Checking for conflicts...");
818
819 for (i = 0; i < p->answer->n_rrs; i++) {
820
821 /* Check for conflicts against the local zone. If we
822 * found one, we won't check any further */
823 r = dns_zone_check_conflicts(&scope->zone, p->answer->items[i].rr);
824 if (r != 0)
825 continue;
826
827 /* Check for conflicts against the local cache. If so,
828 * send out an advisory query, to inform everybody */
829 r = dns_cache_check_conflicts(&scope->cache, p->answer->items[i].rr, p->family, &p->sender);
830 if (r <= 0)
831 continue;
832
833 dns_scope_notify_conflict(scope, p->answer->items[i].rr);
834 }
835 }
836
837 void dns_scope_dump(DnsScope *s, FILE *f) {
838 assert(s);
839
840 if (!f)
841 f = stdout;
842
843 fputs("[Scope protocol=", f);
844 fputs(dns_protocol_to_string(s->protocol), f);
845
846 if (s->link) {
847 fputs(" interface=", f);
848 fputs(s->link->name, f);
849 }
850
851 if (s->family != AF_UNSPEC) {
852 fputs(" family=", f);
853 fputs(af_to_name(s->family), f);
854 }
855
856 fputs("]\n", f);
857
858 if (!dns_zone_is_empty(&s->zone)) {
859 fputs("ZONE:\n", f);
860 dns_zone_dump(&s->zone, f);
861 }
862
863 if (!dns_cache_is_empty(&s->cache)) {
864 fputs("CACHE:\n", f);
865 dns_cache_dump(&s->cache, f);
866 }
867 }
868
869 DnsSearchDomain *dns_scope_get_search_domains(DnsScope *s) {
870 assert(s);
871
872 /* Returns the list of *local* search domains -- not the
873 * global ones. */
874
875 if (s->protocol != DNS_PROTOCOL_DNS)
876 return NULL;
877
878 if (s->link)
879 return s->link->search_domains;
880
881 return NULL;
882 }
883
884 bool dns_scope_has_search_domains(DnsScope *s) {
885 assert(s);
886
887 /* Tests if there are *any* search domains suitable for this
888 * scope. This means either local or global ones */
889
890 if (s->protocol != DNS_PROTOCOL_DNS)
891 return false;
892
893 if (s->manager->search_domains)
894 return true;
895
896 if (s->link && s->link->search_domains)
897 return true;
898
899 return false;
900 }
901
902 bool dns_scope_name_needs_search_domain(DnsScope *s, const char *name) {
903 assert(s);
904
905 if (s->protocol != DNS_PROTOCOL_DNS)
906 return false;
907
908 return dns_name_is_single_label(name);
909 }