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