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