]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/resolve/resolved-dns-scope.c
resolved: add a generic DnsSearchDomain concept
[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 "alloc-util.h"
26 #include "dns-domain.h"
27 #include "fd-util.h"
28 #include "hostname-util.h"
29 #include "missing.h"
30 #include "random-util.h"
31 #include "resolved-dns-scope.h"
32 #include "resolved-llmnr.h"
33 #include "socket-util.h"
34 #include "strv.h"
35
36 #define MULTICAST_RATELIMIT_INTERVAL_USEC (1*USEC_PER_SEC)
37 #define MULTICAST_RATELIMIT_BURST 1000
38
39 /* After how much time to repeat LLMNR requests, see RFC 4795 Section 7 */
40 #define MULTICAST_RESEND_TIMEOUT_MIN_USEC (100 * USEC_PER_MSEC)
41 #define MULTICAST_RESEND_TIMEOUT_MAX_USEC (1 * USEC_PER_SEC)
42
43 int dns_scope_new(Manager *m, DnsScope **ret, Link *l, DnsProtocol protocol, int family) {
44 DnsScope *s;
45
46 assert(m);
47 assert(ret);
48
49 s = new0(DnsScope, 1);
50 if (!s)
51 return -ENOMEM;
52
53 s->manager = m;
54 s->link = l;
55 s->protocol = protocol;
56 s->family = family;
57 s->resend_timeout = MULTICAST_RESEND_TIMEOUT_MIN_USEC;
58
59 LIST_PREPEND(scopes, m->dns_scopes, s);
60
61 dns_scope_llmnr_membership(s, true);
62
63 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));
64
65 /* Enforce ratelimiting for the multicast protocols */
66 RATELIMIT_INIT(s->ratelimit, MULTICAST_RATELIMIT_INTERVAL_USEC, MULTICAST_RATELIMIT_BURST);
67
68 *ret = s;
69 return 0;
70 }
71
72 DnsScope* dns_scope_free(DnsScope *s) {
73 DnsTransaction *t;
74 DnsResourceRecord *rr;
75
76 if (!s)
77 return NULL;
78
79 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));
80
81 dns_scope_llmnr_membership(s, false);
82
83 while ((t = hashmap_steal_first(s->transactions))) {
84 /* Abort the transaction, but make sure it is not
85 * freed while we still look at it */
86
87 t->block_gc++;
88 dns_transaction_complete(t, DNS_TRANSACTION_ABORTED);
89 t->block_gc--;
90
91 dns_transaction_free(t);
92 }
93
94 hashmap_free(s->transactions);
95
96 while ((rr = ordered_hashmap_steal_first(s->conflict_queue)))
97 dns_resource_record_unref(rr);
98
99 ordered_hashmap_free(s->conflict_queue);
100 sd_event_source_unref(s->conflict_event_source);
101
102 dns_cache_flush(&s->cache);
103 dns_zone_flush(&s->zone);
104
105 LIST_REMOVE(scopes, s->manager->dns_scopes, s);
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 return;
140
141 s->max_rtt = rtt;
142 s->resend_timeout = MIN(MAX(MULTICAST_RESEND_TIMEOUT_MIN_USEC, s->max_rtt * 2), MULTICAST_RESEND_TIMEOUT_MAX_USEC);
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 DnsSearchDomain *d;
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 LIST_FOREACH(domains, d, dns_scope_get_search_domains(s))
348 if (dns_name_endswith(domain, d->name) > 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 DnsResourceKey *key = NULL;
546 bool tentative = false;
547 int r, fd;
548
549 assert(s);
550 assert(p);
551
552 if (p->protocol != DNS_PROTOCOL_LLMNR)
553 return;
554
555 if (p->ipproto == IPPROTO_UDP) {
556 /* Don't accept UDP queries directed to anything but
557 * the LLMNR multicast addresses. See RFC 4795,
558 * section 2.5. */
559
560 if (p->family == AF_INET && !in_addr_equal(AF_INET, &p->destination, (union in_addr_union*) &LLMNR_MULTICAST_IPV4_ADDRESS))
561 return;
562
563 if (p->family == AF_INET6 && !in_addr_equal(AF_INET6, &p->destination, (union in_addr_union*) &LLMNR_MULTICAST_IPV6_ADDRESS))
564 return;
565 }
566
567 r = dns_packet_extract(p);
568 if (r < 0) {
569 log_debug_errno(r, "Failed to extract resources from incoming packet: %m");
570 return;
571 }
572
573 if (DNS_PACKET_LLMNR_C(p)) {
574 /* Somebody notified us about a possible conflict */
575 dns_scope_verify_conflicts(s, p);
576 return;
577 }
578
579 assert(p->question->n_keys == 1);
580 key = p->question->keys[0];
581
582 r = dns_zone_lookup(&s->zone, key, &answer, &soa, &tentative);
583 if (r < 0) {
584 log_debug_errno(r, "Failed to lookup key: %m");
585 return;
586 }
587 if (r == 0)
588 return;
589
590 if (answer)
591 dns_answer_order_by_scope(answer, in_addr_is_link_local(p->family, &p->sender) > 0);
592
593 r = dns_scope_make_reply_packet(s, DNS_PACKET_ID(p), DNS_RCODE_SUCCESS, p->question, answer, soa, tentative, &reply);
594 if (r < 0) {
595 log_debug_errno(r, "Failed to build reply packet: %m");
596 return;
597 }
598
599 if (stream)
600 r = dns_stream_write_packet(stream, reply);
601 else {
602 if (!ratelimit_test(&s->ratelimit))
603 return;
604
605 if (p->family == AF_INET)
606 fd = manager_llmnr_ipv4_udp_fd(s->manager);
607 else if (p->family == AF_INET6)
608 fd = manager_llmnr_ipv6_udp_fd(s->manager);
609 else {
610 log_debug("Unknown protocol");
611 return;
612 }
613 if (fd < 0) {
614 log_debug_errno(fd, "Failed to get reply socket: %m");
615 return;
616 }
617
618 /* Note that we always immediately reply to all LLMNR
619 * requests, and do not wait any time, since we
620 * verified uniqueness for all records. Also see RFC
621 * 4795, Section 2.7 */
622
623 r = manager_send(s->manager, fd, p->ifindex, p->family, &p->sender, p->sender_port, reply);
624 }
625
626 if (r < 0) {
627 log_debug_errno(r, "Failed to send reply packet: %m");
628 return;
629 }
630 }
631
632 DnsTransaction *dns_scope_find_transaction(DnsScope *scope, DnsResourceKey *key, bool cache_ok) {
633 DnsTransaction *t;
634
635 assert(scope);
636 assert(key);
637
638 /* Try to find an ongoing transaction that is a equal to the
639 * specified question */
640 t = hashmap_get(scope->transactions, key);
641 if (!t)
642 return NULL;
643
644 /* Refuse reusing transactions that completed based on cached
645 * data instead of a real packet, if that's requested. */
646 if (!cache_ok &&
647 IN_SET(t->state, DNS_TRANSACTION_SUCCESS, DNS_TRANSACTION_FAILURE) &&
648 !t->received)
649 return NULL;
650
651 return t;
652 }
653
654 static int dns_scope_make_conflict_packet(
655 DnsScope *s,
656 DnsResourceRecord *rr,
657 DnsPacket **ret) {
658
659 _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
660 int r;
661
662 assert(s);
663 assert(rr);
664 assert(ret);
665
666 r = dns_packet_new(&p, s->protocol, 0);
667 if (r < 0)
668 return r;
669
670 DNS_PACKET_HEADER(p)->flags = htobe16(DNS_PACKET_MAKE_FLAGS(
671 0 /* qr */,
672 0 /* opcode */,
673 1 /* conflict */,
674 0 /* tc */,
675 0 /* t */,
676 0 /* (ra) */,
677 0 /* (ad) */,
678 0 /* (cd) */,
679 0));
680 random_bytes(&DNS_PACKET_HEADER(p)->id, sizeof(uint16_t));
681 DNS_PACKET_HEADER(p)->qdcount = htobe16(1);
682 DNS_PACKET_HEADER(p)->arcount = htobe16(1);
683
684 r = dns_packet_append_key(p, rr->key, NULL);
685 if (r < 0)
686 return r;
687
688 r = dns_packet_append_rr(p, rr, NULL);
689 if (r < 0)
690 return r;
691
692 *ret = p;
693 p = NULL;
694
695 return 0;
696 }
697
698 static int on_conflict_dispatch(sd_event_source *es, usec_t usec, void *userdata) {
699 DnsScope *scope = userdata;
700 int r;
701
702 assert(es);
703 assert(scope);
704
705 scope->conflict_event_source = sd_event_source_unref(scope->conflict_event_source);
706
707 for (;;) {
708 _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
709 _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
710
711 rr = ordered_hashmap_steal_first(scope->conflict_queue);
712 if (!rr)
713 break;
714
715 r = dns_scope_make_conflict_packet(scope, rr, &p);
716 if (r < 0) {
717 log_error_errno(r, "Failed to make conflict packet: %m");
718 return 0;
719 }
720
721 r = dns_scope_emit(scope, -1, p);
722 if (r < 0)
723 log_debug_errno(r, "Failed to send conflict packet: %m");
724 }
725
726 return 0;
727 }
728
729 int dns_scope_notify_conflict(DnsScope *scope, DnsResourceRecord *rr) {
730 usec_t jitter;
731 int r;
732
733 assert(scope);
734 assert(rr);
735
736 /* We don't send these queries immediately. Instead, we queue
737 * them, and send them after some jitter delay. */
738 r = ordered_hashmap_ensure_allocated(&scope->conflict_queue, &dns_resource_key_hash_ops);
739 if (r < 0) {
740 log_oom();
741 return r;
742 }
743
744 /* We only place one RR per key in the conflict
745 * messages, not all of them. That should be enough to
746 * indicate where there might be a conflict */
747 r = ordered_hashmap_put(scope->conflict_queue, rr->key, rr);
748 if (r == -EEXIST || r == 0)
749 return 0;
750 if (r < 0)
751 return log_debug_errno(r, "Failed to queue conflicting RR: %m");
752
753 dns_resource_record_ref(rr);
754
755 if (scope->conflict_event_source)
756 return 0;
757
758 random_bytes(&jitter, sizeof(jitter));
759 jitter %= LLMNR_JITTER_INTERVAL_USEC;
760
761 r = sd_event_add_time(scope->manager->event,
762 &scope->conflict_event_source,
763 clock_boottime_or_monotonic(),
764 now(clock_boottime_or_monotonic()) + jitter,
765 LLMNR_JITTER_INTERVAL_USEC,
766 on_conflict_dispatch, scope);
767 if (r < 0)
768 return log_debug_errno(r, "Failed to add conflict dispatch event: %m");
769
770 return 0;
771 }
772
773 void dns_scope_check_conflicts(DnsScope *scope, DnsPacket *p) {
774 unsigned i;
775 int r;
776
777 assert(scope);
778 assert(p);
779
780 if (p->protocol != DNS_PROTOCOL_LLMNR)
781 return;
782
783 if (DNS_PACKET_RRCOUNT(p) <= 0)
784 return;
785
786 if (DNS_PACKET_LLMNR_C(p) != 0)
787 return;
788
789 if (DNS_PACKET_LLMNR_T(p) != 0)
790 return;
791
792 if (manager_our_packet(scope->manager, p))
793 return;
794
795 r = dns_packet_extract(p);
796 if (r < 0) {
797 log_debug_errno(r, "Failed to extract packet: %m");
798 return;
799 }
800
801 log_debug("Checking for conflicts...");
802
803 for (i = 0; i < p->answer->n_rrs; i++) {
804
805 /* Check for conflicts against the local zone. If we
806 * found one, we won't check any further */
807 r = dns_zone_check_conflicts(&scope->zone, p->answer->items[i].rr);
808 if (r != 0)
809 continue;
810
811 /* Check for conflicts against the local cache. If so,
812 * send out an advisory query, to inform everybody */
813 r = dns_cache_check_conflicts(&scope->cache, p->answer->items[i].rr, p->family, &p->sender);
814 if (r <= 0)
815 continue;
816
817 dns_scope_notify_conflict(scope, p->answer->items[i].rr);
818 }
819 }
820
821 void dns_scope_dump(DnsScope *s, FILE *f) {
822 assert(s);
823
824 if (!f)
825 f = stdout;
826
827 fputs("[Scope protocol=", f);
828 fputs(dns_protocol_to_string(s->protocol), f);
829
830 if (s->link) {
831 fputs(" interface=", f);
832 fputs(s->link->name, f);
833 }
834
835 if (s->family != AF_UNSPEC) {
836 fputs(" family=", f);
837 fputs(af_to_name(s->family), f);
838 }
839
840 fputs("]\n", f);
841
842 if (!dns_zone_is_empty(&s->zone)) {
843 fputs("ZONE:\n", f);
844 dns_zone_dump(&s->zone, f);
845 }
846
847 if (!dns_cache_is_empty(&s->cache)) {
848 fputs("CACHE:\n", f);
849 dns_cache_dump(&s->cache, f);
850 }
851 }
852
853 DnsSearchDomain *dns_scope_get_search_domains(DnsScope *s) {
854
855 if (s->protocol != DNS_PROTOCOL_DNS)
856 return NULL;
857
858 if (s->link)
859 return s->link->search_domains;
860
861 return NULL;
862 }