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