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