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