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