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