chiark / gitweb /
resolved: skip IPv6 LLMNR if IPv6 is not available
[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, const char *domain) {
295         char **i;
296
297         assert(s);
298         assert(domain);
299
300         STRV_FOREACH(i, s->domains)
301                 if (dns_name_endswith(domain, *i) > 0)
302                         return DNS_SCOPE_YES;
303
304         if (dns_name_root(domain) != 0)
305                 return DNS_SCOPE_NO;
306
307         if (is_localhost(domain))
308                 return DNS_SCOPE_NO;
309
310         if (s->protocol == DNS_PROTOCOL_DNS) {
311                 if (dns_name_endswith(domain, "254.169.in-addr.arpa") == 0 &&
312                     dns_name_endswith(domain, "0.8.e.f.ip6.arpa") == 0 &&
313                     dns_name_single_label(domain) == 0)
314                         return DNS_SCOPE_MAYBE;
315
316                 return DNS_SCOPE_NO;
317         }
318
319         if (s->protocol == DNS_PROTOCOL_MDNS) {
320                 if (dns_name_endswith(domain, "254.169.in-addr.arpa") > 0 ||
321                     dns_name_endswith(domain, "0.8.e.f.ip6.arpa") > 0 ||
322                     (dns_name_endswith(domain, "local") > 0 && dns_name_equal(domain, "local") == 0))
323                         return DNS_SCOPE_MAYBE;
324
325                 return DNS_SCOPE_NO;
326         }
327
328         if (s->protocol == DNS_PROTOCOL_LLMNR) {
329                 if (dns_name_endswith(domain, "in-addr.arpa") > 0 ||
330                     dns_name_endswith(domain, "ip6.arpa") > 0 ||
331                     dns_name_single_label(domain) > 0)
332                         return DNS_SCOPE_MAYBE;
333
334                 return DNS_SCOPE_NO;
335         }
336
337         assert_not_reached("Unknown scope protocol");
338 }
339
340 int dns_scope_good_key(DnsScope *s, DnsResourceKey *key) {
341         assert(s);
342         assert(key);
343
344         if (s->protocol == DNS_PROTOCOL_DNS)
345                 return true;
346
347         /* On mDNS and LLMNR, send A and AAAA queries only on the
348          * respective scopes */
349
350         if (s->family == AF_INET && key->class == DNS_CLASS_IN && key->type == DNS_TYPE_AAAA)
351                 return false;
352
353         if (s->family == AF_INET6 && key->class == DNS_CLASS_IN && key->type == DNS_TYPE_A)
354                 return false;
355
356         return true;
357 }
358
359 int dns_scope_llmnr_membership(DnsScope *s, bool b) {
360         int fd;
361
362         if (s->family == AF_INET) {
363                 struct ip_mreqn mreqn = {
364                         .imr_multiaddr = LLMNR_MULTICAST_IPV4_ADDRESS,
365                         .imr_ifindex = s->link->ifindex,
366                 };
367
368                 fd = manager_llmnr_ipv4_udp_fd(s->manager);
369                 if (fd < 0)
370                         return fd;
371
372                 /* Always first try to drop membership before we add
373                  * one. This is necessary on some devices, such as
374                  * veth. */
375                 if (b)
376                         setsockopt(fd, IPPROTO_IP, IP_DROP_MEMBERSHIP, &mreqn, sizeof(mreqn));
377
378                 if (setsockopt(fd, IPPROTO_IP, b ? IP_ADD_MEMBERSHIP : IP_DROP_MEMBERSHIP, &mreqn, sizeof(mreqn)) < 0)
379                         return -errno;
380
381         } else if (s->family == AF_INET6) {
382                 struct ipv6_mreq mreq = {
383                         .ipv6mr_multiaddr = LLMNR_MULTICAST_IPV6_ADDRESS,
384                         .ipv6mr_interface = s->link->ifindex,
385                 };
386
387                 fd = manager_llmnr_ipv6_udp_fd(s->manager);
388                 if (fd < 0)
389                         return fd;
390
391                 if (b)
392                         setsockopt(fd, IPPROTO_IPV6, IPV6_DROP_MEMBERSHIP, &mreq, sizeof(mreq));
393
394                 if (setsockopt(fd, IPPROTO_IPV6, b ? IPV6_ADD_MEMBERSHIP : IPV6_DROP_MEMBERSHIP, &mreq, sizeof(mreq)) < 0)
395                         return -errno;
396         } else
397                 return -EAFNOSUPPORT;
398
399         return 0;
400 }
401
402 int dns_scope_good_dns_server(DnsScope *s, int family, const union in_addr_union *address) {
403         assert(s);
404         assert(address);
405
406         if (s->protocol != DNS_PROTOCOL_DNS)
407                 return 1;
408
409         if (s->link)
410                 return !!link_find_dns_server(s->link,  family, address);
411         else
412                 return !!manager_find_dns_server(s->manager, family, address);
413 }
414
415 static int dns_scope_make_reply_packet(
416                 DnsScope *s,
417                 uint16_t id,
418                 int rcode,
419                 DnsQuestion *q,
420                 DnsAnswer *answer,
421                 DnsAnswer *soa,
422                 bool tentative,
423                 DnsPacket **ret) {
424
425         _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
426         unsigned i;
427         int r;
428
429         assert(s);
430         assert(ret);
431
432         if ((!q || q->n_keys <= 0)
433             && (!answer || answer->n_rrs <= 0)
434             && (!soa || soa->n_rrs <= 0))
435                 return -EINVAL;
436
437         r = dns_packet_new(&p, s->protocol, 0);
438         if (r < 0)
439                 return r;
440
441         DNS_PACKET_HEADER(p)->id = id;
442         DNS_PACKET_HEADER(p)->flags = htobe16(DNS_PACKET_MAKE_FLAGS(
443                                                               1 /* qr */,
444                                                               0 /* opcode */,
445                                                               0 /* c */,
446                                                               0 /* tc */,
447                                                               tentative,
448                                                               0 /* (ra) */,
449                                                               0 /* (ad) */,
450                                                               0 /* (cd) */,
451                                                               rcode));
452
453         if (q) {
454                 for (i = 0; i < q->n_keys; i++) {
455                         r = dns_packet_append_key(p, q->keys[i], NULL);
456                         if (r < 0)
457                                 return r;
458                 }
459
460                 DNS_PACKET_HEADER(p)->qdcount = htobe16(q->n_keys);
461         }
462
463         if (answer) {
464                 for (i = 0; i < answer->n_rrs; i++) {
465                         r = dns_packet_append_rr(p, answer->rrs[i], NULL);
466                         if (r < 0)
467                                 return r;
468                 }
469
470                 DNS_PACKET_HEADER(p)->ancount = htobe16(answer->n_rrs);
471         }
472
473         if (soa) {
474                 for (i = 0; i < soa->n_rrs; i++) {
475                         r = dns_packet_append_rr(p, soa->rrs[i], NULL);
476                         if (r < 0)
477                                 return r;
478                 }
479
480                 DNS_PACKET_HEADER(p)->arcount = htobe16(soa->n_rrs);
481         }
482
483         *ret = p;
484         p = NULL;
485
486         return 0;
487 }
488
489 static void dns_scope_verify_conflicts(DnsScope *s, DnsPacket *p) {
490         unsigned n;
491
492         assert(s);
493         assert(p);
494
495         if (p->question)
496                 for (n = 0; n < p->question->n_keys; n++)
497                         dns_zone_verify_conflicts(&s->zone, p->question->keys[n]);
498         if (p->answer)
499                 for (n = 0; n < p->answer->n_rrs; n++)
500                         dns_zone_verify_conflicts(&s->zone, p->answer->rrs[n]->key);
501 }
502
503 void dns_scope_process_query(DnsScope *s, DnsStream *stream, DnsPacket *p) {
504         _cleanup_(dns_packet_unrefp) DnsPacket *reply = NULL;
505         _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL, *soa = NULL;
506         bool tentative = false;
507         int r, fd;
508
509         assert(s);
510         assert(p);
511
512         if (p->protocol != DNS_PROTOCOL_LLMNR)
513                 return;
514
515         if (p->ipproto == IPPROTO_UDP) {
516                 /* Don't accept UDP queries directed to anything but
517                  * the LLMNR multicast addresses. See RFC 4795,
518                  * section 2.5.*/
519
520                 if (p->family == AF_INET && !in_addr_equal(AF_INET, &p->destination, (union in_addr_union*) &LLMNR_MULTICAST_IPV4_ADDRESS))
521                         return;
522
523                 if (p->family == AF_INET6 && !in_addr_equal(AF_INET6, &p->destination, (union in_addr_union*) &LLMNR_MULTICAST_IPV6_ADDRESS))
524                         return;
525         }
526
527         r = dns_packet_extract(p);
528         if (r < 0) {
529                 log_debug("Failed to extract resources from incoming packet: %s", strerror(-r));
530                 return;
531         }
532
533         if (DNS_PACKET_C(p)) {
534                 /* Somebody notified us about a possible conflict */
535                 dns_scope_verify_conflicts(s, p);
536                 return;
537         }
538
539         r = dns_zone_lookup(&s->zone, p->question, &answer, &soa, &tentative);
540         if (r < 0) {
541                 log_debug("Failed to lookup key: %s", strerror(-r));
542                 return;
543         }
544         if (r == 0)
545                 return;
546
547         if (answer)
548                 dns_answer_order_by_scope(answer, in_addr_is_link_local(p->family, &p->sender) > 0);
549
550         r = dns_scope_make_reply_packet(s, DNS_PACKET_ID(p), DNS_RCODE_SUCCESS, p->question, answer, soa, tentative, &reply);
551         if (r < 0) {
552                 log_debug("Failed to build reply packet: %s", strerror(-r));
553                 return;
554         }
555
556         if (stream)
557                 r = dns_stream_write_packet(stream, reply);
558         else {
559                 if (!ratelimit_test(&s->ratelimit))
560                         return;
561
562                 if (p->family == AF_INET)
563                         fd = manager_llmnr_ipv4_udp_fd(s->manager);
564                 else if (p->family == AF_INET6)
565                         fd = manager_llmnr_ipv6_udp_fd(s->manager);
566                 else {
567                         log_debug("Unknown protocol");
568                         return;
569                 }
570                 if (fd < 0) {
571                         log_debug("Failed to get reply socket: %s", strerror(-fd));
572                         return;
573                 }
574
575                 /* Note that we always immediately reply to all LLMNR
576                  * requests, and do not wait any time, since we
577                  * verified uniqueness for all records. Also see RFC
578                  * 4795, Section 2.7 */
579
580                 r = manager_send(s->manager, fd, p->ifindex, p->family, &p->sender, p->sender_port, reply);
581         }
582
583         if (r < 0) {
584                 log_debug("Failed to send reply packet: %s", strerror(-r));
585                 return;
586         }
587 }
588
589 DnsTransaction *dns_scope_find_transaction(DnsScope *scope, DnsQuestion *question, bool cache_ok) {
590         DnsTransaction *t;
591
592         assert(scope);
593         assert(question);
594
595         /* Try to find an ongoing transaction that is a equal or a
596          * superset of the specified question */
597
598         LIST_FOREACH(transactions_by_scope, t, scope->transactions) {
599
600                 /* Refuse reusing transactions that completed based on
601                  * cached data instead of a real packet, if that's
602                  * requested. */
603                 if (!cache_ok &&
604                     IN_SET(t->state, DNS_TRANSACTION_SUCCESS, DNS_TRANSACTION_FAILURE) &&
605                     !t->received)
606                         continue;
607
608                 if (dns_question_is_superset(t->question, question) > 0)
609                         return t;
610         }
611
612         return NULL;
613 }
614
615 static int dns_scope_make_conflict_packet(
616                 DnsScope *s,
617                 DnsResourceRecord *rr,
618                 DnsPacket **ret) {
619
620         _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
621         int r;
622
623         assert(s);
624         assert(rr);
625         assert(ret);
626
627         r = dns_packet_new(&p, s->protocol, 0);
628         if (r < 0)
629                 return r;
630
631         DNS_PACKET_HEADER(p)->flags = htobe16(DNS_PACKET_MAKE_FLAGS(
632                                                               0 /* qr */,
633                                                               0 /* opcode */,
634                                                               1 /* conflict */,
635                                                               0 /* tc */,
636                                                               0 /* t */,
637                                                               0 /* (ra) */,
638                                                               0 /* (ad) */,
639                                                               0 /* (cd) */,
640                                                               0));
641         random_bytes(&DNS_PACKET_HEADER(p)->id, sizeof(uint16_t));
642         DNS_PACKET_HEADER(p)->qdcount = htobe16(1);
643         DNS_PACKET_HEADER(p)->arcount = htobe16(1);
644
645         r = dns_packet_append_key(p, rr->key, NULL);
646         if (r < 0)
647                 return r;
648
649         r = dns_packet_append_rr(p, rr, NULL);
650         if (r < 0)
651                 return r;
652
653         *ret = p;
654         p = NULL;
655
656         return 0;
657 }
658
659 static int on_conflict_dispatch(sd_event_source *es, usec_t usec, void *userdata) {
660         DnsScope *scope = userdata;
661         int r;
662
663         assert(es);
664         assert(scope);
665
666         scope->conflict_event_source = sd_event_source_unref(scope->conflict_event_source);
667
668         for (;;) {
669                 _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
670                 _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
671
672                 rr = hashmap_steal_first(scope->conflict_queue);
673                 if (!rr)
674                         break;
675
676                 r = dns_scope_make_conflict_packet(scope, rr, &p);
677                 if (r < 0) {
678                         log_error("Failed to make conflict packet: %s", strerror(-r));
679                         return 0;
680                 }
681
682                 r = dns_scope_emit(scope, p);
683                 if (r < 0)
684                         log_debug("Failed to send conflict packet: %s", strerror(-r));
685         }
686
687         return 0;
688 }
689
690 int dns_scope_notify_conflict(DnsScope *scope, DnsResourceRecord *rr) {
691         usec_t jitter;
692         int r;
693
694         assert(scope);
695         assert(rr);
696
697         /* We don't send these queries immediately. Instead, we queue
698          * them, and send them after some jitter delay. */
699         r = hashmap_ensure_allocated(&scope->conflict_queue, dns_resource_key_hash_func, dns_resource_key_compare_func);
700         if (r < 0) {
701                 log_oom();
702                 return r;
703         }
704
705         /* We only place one RR per key in the conflict
706          * messages, not all of them. That should be enough to
707          * indicate where there might be a conflict */
708         r = hashmap_put(scope->conflict_queue, rr->key, rr);
709         if (r == -EEXIST || r == 0)
710                 return 0;
711         if (r < 0) {
712                 log_debug("Failed to queue conflicting RR: %s", strerror(-r));
713                 return r;
714         }
715
716         dns_resource_record_ref(rr);
717
718         if (scope->conflict_event_source)
719                 return 0;
720
721         random_bytes(&jitter, sizeof(jitter));
722         jitter %= LLMNR_JITTER_INTERVAL_USEC;
723
724         r = sd_event_add_time(scope->manager->event,
725                               &scope->conflict_event_source,
726                               clock_boottime_or_monotonic(),
727                               now(clock_boottime_or_monotonic()) + jitter,
728                               LLMNR_JITTER_INTERVAL_USEC,
729                               on_conflict_dispatch, scope);
730         if (r < 0) {
731                 log_debug("Failed to add conflict dispatch event: %s", strerror(-r));
732                 return r;
733         }
734
735         return 0;
736 }
737
738 void dns_scope_check_conflicts(DnsScope *scope, DnsPacket *p) {
739         unsigned i;
740         int r;
741
742         assert(scope);
743         assert(p);
744
745         if (p->protocol != DNS_PROTOCOL_LLMNR)
746                 return;
747
748         if (DNS_PACKET_RRCOUNT(p) <= 0)
749                 return;
750
751         if (DNS_PACKET_C(p) != 0)
752                 return;
753
754         if (DNS_PACKET_T(p) != 0)
755                 return;
756
757         if (manager_our_packet(scope->manager, p))
758                 return;
759
760         r = dns_packet_extract(p);
761         if (r < 0) {
762                 log_debug("Failed to extract packet: %s", strerror(-r));
763                 return;
764         }
765
766         log_debug("Checking for conflicts...");
767
768         for (i = 0; i < p->answer->n_rrs; i++) {
769
770                 /* Check for conflicts against the local zone. If we
771                  * found one, we won't check any further */
772                 r = dns_zone_check_conflicts(&scope->zone, p->answer->rrs[i]);
773                 if (r != 0)
774                         continue;
775
776                 /* Check for conflicts against the local cache. If so,
777                  * send out an advisory query, to inform everybody */
778                 r = dns_cache_check_conflicts(&scope->cache, p->answer->rrs[i], p->family, &p->sender);
779                 if (r <= 0)
780                         continue;
781
782                 dns_scope_notify_conflict(scope, p->answer->rrs[i]);
783         }
784 }