]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/resolve/resolved-dns-scope.c
resolved: rework OPT RR generation logic
[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 32#include "resolved-llmnr.h"
b4f1862d 33#include "resolved-mdns.h"
3ffd4af2
LP
34#include "socket-util.h"
35#include "strv.h"
74b2466e 36
aea2429d
LP
37#define MULTICAST_RATELIMIT_INTERVAL_USEC (1*USEC_PER_SEC)
38#define MULTICAST_RATELIMIT_BURST 1000
39
9df3ba6c
TG
40/* After how much time to repeat LLMNR requests, see RFC 4795 Section 7 */
41#define MULTICAST_RESEND_TIMEOUT_MIN_USEC (100 * USEC_PER_MSEC)
42#define MULTICAST_RESEND_TIMEOUT_MAX_USEC (1 * USEC_PER_SEC)
43
0dd25fb9 44int dns_scope_new(Manager *m, DnsScope **ret, Link *l, DnsProtocol protocol, int family) {
74b2466e
LP
45 DnsScope *s;
46
47 assert(m);
48 assert(ret);
49
50 s = new0(DnsScope, 1);
51 if (!s)
52 return -ENOMEM;
53
54 s->manager = m;
1716f6dc
LP
55 s->link = l;
56 s->protocol = protocol;
57 s->family = family;
9df3ba6c 58 s->resend_timeout = MULTICAST_RESEND_TIMEOUT_MIN_USEC;
74b2466e
LP
59
60 LIST_PREPEND(scopes, m->dns_scopes, s);
61
1716f6dc 62 dns_scope_llmnr_membership(s, true);
0db4c90a 63 dns_scope_mdns_membership(s, true);
1716f6dc 64
46f08bea 65 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 66
aea2429d
LP
67 /* Enforce ratelimiting for the multicast protocols */
68 RATELIMIT_INIT(s->ratelimit, MULTICAST_RATELIMIT_INTERVAL_USEC, MULTICAST_RATELIMIT_BURST);
69
74b2466e
LP
70 *ret = s;
71 return 0;
72}
73
801ad6a6 74static void dns_scope_abort_transactions(DnsScope *s) {
801ad6a6 75 assert(s);
1716f6dc 76
f9ebb22a
LP
77 while (s->transactions) {
78 DnsTransaction *t = s->transactions;
79
faa133f3
LP
80 /* Abort the transaction, but make sure it is not
81 * freed while we still look at it */
74b2466e 82
faa133f3 83 t->block_gc++;
f4e38037
LP
84 if (DNS_TRANSACTION_IS_LIVE(t->state))
85 dns_transaction_complete(t, DNS_TRANSACTION_ABORTED);
faa133f3 86 t->block_gc--;
74b2466e 87
ec2c5e43 88 dns_transaction_free(t);
74b2466e 89 }
801ad6a6
LP
90}
91
92DnsScope* dns_scope_free(DnsScope *s) {
93 DnsResourceRecord *rr;
94
95 if (!s)
96 return NULL;
97
98 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));
99
100 dns_scope_llmnr_membership(s, false);
0db4c90a 101 dns_scope_mdns_membership(s, false);
801ad6a6
LP
102 dns_scope_abort_transactions(s);
103
104 while (s->query_candidates)
105 dns_query_candidate_free(s->query_candidates);
74b2466e 106
f9ebb22a 107 hashmap_free(s->transactions_by_key);
da0c630e 108
1e43061b 109 while ((rr = ordered_hashmap_steal_first(s->conflict_queue)))
a4076574
LP
110 dns_resource_record_unref(rr);
111
1e43061b 112 ordered_hashmap_free(s->conflict_queue);
a4076574
LP
113 sd_event_source_unref(s->conflict_event_source);
114
322345fd 115 dns_cache_flush(&s->cache);
623a4c97 116 dns_zone_flush(&s->zone);
322345fd 117
74b2466e 118 LIST_REMOVE(scopes, s->manager->dns_scopes, s);
74b2466e
LP
119 free(s);
120
121 return NULL;
122}
123
2c27fbca 124DnsServer *dns_scope_get_dns_server(DnsScope *s) {
74b2466e
LP
125 assert(s);
126
1716f6dc
LP
127 if (s->protocol != DNS_PROTOCOL_DNS)
128 return NULL;
129
74b2466e
LP
130 if (s->link)
131 return link_get_dns_server(s->link);
132 else
133 return manager_get_dns_server(s->manager);
134}
135
136void dns_scope_next_dns_server(DnsScope *s) {
137 assert(s);
138
1716f6dc
LP
139 if (s->protocol != DNS_PROTOCOL_DNS)
140 return;
141
74b2466e
LP
142 if (s->link)
143 link_next_dns_server(s->link);
144 else
145 manager_next_dns_server(s->manager);
146}
147
9df3ba6c
TG
148void dns_scope_packet_received(DnsScope *s, usec_t rtt) {
149 assert(s);
150
84129d46
LP
151 if (rtt <= s->max_rtt)
152 return;
153
154 s->max_rtt = rtt;
155 s->resend_timeout = MIN(MAX(MULTICAST_RESEND_TIMEOUT_MIN_USEC, s->max_rtt * 2), MULTICAST_RESEND_TIMEOUT_MAX_USEC);
9df3ba6c
TG
156}
157
158void dns_scope_packet_lost(DnsScope *s, usec_t usec) {
159 assert(s);
160
161 if (s->resend_timeout <= usec)
162 s->resend_timeout = MIN(s->resend_timeout * 2, MULTICAST_RESEND_TIMEOUT_MAX_USEC);
163}
164
519ef046 165static int dns_scope_emit_one(DnsScope *s, int fd, DnsPacket *p) {
1716f6dc
LP
166 union in_addr_union addr;
167 int ifindex = 0, r;
0dd25fb9 168 int family;
1716f6dc 169 uint32_t mtu;
74b2466e
LP
170
171 assert(s);
172 assert(p);
1716f6dc 173 assert(p->protocol == s->protocol);
ad867662
LP
174
175 if (s->link) {
1716f6dc 176 mtu = s->link->mtu;
74b2466e 177 ifindex = s->link->ifindex;
1716f6dc 178 } else
e1c95994 179 mtu = manager_find_mtu(s->manager);
74b2466e 180
106784eb 181 switch (s->protocol) {
519ef046 182
106784eb 183 case DNS_PROTOCOL_DNS:
519ef046 184 assert(fd >= 0);
9c5e12a4 185
623a4c97 186 if (DNS_PACKET_QDCOUNT(p) > 1)
15411c0c 187 return -EOPNOTSUPP;
623a4c97 188
1716f6dc
LP
189 if (p->size > DNS_PACKET_UNICAST_SIZE_MAX)
190 return -EMSGSIZE;
191
a0166609 192 if (p->size + UDP_PACKET_HEADER_SIZE > mtu)
1716f6dc
LP
193 return -EMSGSIZE;
194
72290734
TG
195 r = manager_write(s->manager, fd, p);
196 if (r < 0)
197 return r;
198
106784eb 199 break;
1716f6dc 200
106784eb 201 case DNS_PROTOCOL_LLMNR:
519ef046
LP
202 assert(fd < 0);
203
1716f6dc 204 if (DNS_PACKET_QDCOUNT(p) > 1)
15411c0c 205 return -EOPNOTSUPP;
1716f6dc 206
aea2429d
LP
207 if (!ratelimit_test(&s->ratelimit))
208 return -EBUSY;
209
1716f6dc 210 family = s->family;
1716f6dc
LP
211
212 if (family == AF_INET) {
213 addr.in = LLMNR_MULTICAST_IPV4_ADDRESS;
1716f6dc
LP
214 fd = manager_llmnr_ipv4_udp_fd(s->manager);
215 } else if (family == AF_INET6) {
216 addr.in6 = LLMNR_MULTICAST_IPV6_ADDRESS;
217 fd = manager_llmnr_ipv6_udp_fd(s->manager);
1716f6dc
LP
218 } else
219 return -EAFNOSUPPORT;
220 if (fd < 0)
221 return fd;
72290734 222
b4f1862d
DM
223 r = manager_send(s->manager, fd, ifindex, family, &addr, LLMNR_PORT, p);
224 if (r < 0)
225 return r;
226
227 break;
228
229 case DNS_PROTOCOL_MDNS:
519ef046
LP
230 assert(fd < 0);
231
b4f1862d
DM
232 if (!ratelimit_test(&s->ratelimit))
233 return -EBUSY;
234
235 family = s->family;
236
237 if (family == AF_INET) {
238 addr.in = MDNS_MULTICAST_IPV4_ADDRESS;
239 fd = manager_mdns_ipv4_fd(s->manager);
240 } else if (family == AF_INET6) {
241 addr.in6 = MDNS_MULTICAST_IPV6_ADDRESS;
242 fd = manager_mdns_ipv6_fd(s->manager);
243 } else
244 return -EAFNOSUPPORT;
245 if (fd < 0)
246 return fd;
247
248 r = manager_send(s->manager, fd, ifindex, family, &addr, MDNS_PORT, p);
72290734
TG
249 if (r < 0)
250 return r;
106784eb
DM
251
252 break;
253
254 default:
74b2466e 255 return -EAFNOSUPPORT;
106784eb 256 }
74b2466e 257
74b2466e
LP
258 return 1;
259}
260
519ef046 261int dns_scope_emit_udp(DnsScope *s, int fd, DnsPacket *p) {
80a62095
DM
262 int r;
263
264 assert(s);
265 assert(p);
266 assert(p->protocol == s->protocol);
519ef046 267 assert((s->protocol == DNS_PROTOCOL_DNS) == (fd >= 0));
80a62095
DM
268
269 do {
270 /* If there are multiple linked packets, set the TC bit in all but the last of them */
271 if (p->more) {
272 assert(p->protocol == DNS_PROTOCOL_MDNS);
261f3673 273 dns_packet_set_flags(p, true, true);
80a62095
DM
274 }
275
519ef046 276 r = dns_scope_emit_one(s, fd, p);
80a62095
DM
277 if (r < 0)
278 return r;
279
280 p = p->more;
519ef046 281 } while (p);
80a62095
DM
282
283 return 0;
284}
285
519ef046
LP
286static int dns_scope_socket(
287 DnsScope *s,
288 int type,
289 int family,
290 const union in_addr_union *address,
291 DnsServer *server,
292 uint16_t port) {
293
ad867662
LP
294 _cleanup_close_ int fd = -1;
295 union sockaddr_union sa = {};
296 socklen_t salen;
623a4c97
LP
297 static const int one = 1;
298 int ret, r;
ad867662
LP
299
300 assert(s);
be808ea0 301
519ef046
LP
302 if (server) {
303 assert(family == AF_UNSPEC);
304 assert(!address);
be808ea0 305
519ef046
LP
306 sa.sa.sa_family = server->family;
307 if (server->family == AF_INET) {
623a4c97 308 sa.in.sin_port = htobe16(port);
519ef046 309 sa.in.sin_addr = server->address.in;
623a4c97 310 salen = sizeof(sa.in);
519ef046 311 } else if (server->family == AF_INET6) {
623a4c97 312 sa.in6.sin6_port = htobe16(port);
519ef046 313 sa.in6.sin6_addr = server->address.in6;
623a4c97
LP
314 sa.in6.sin6_scope_id = s->link ? s->link->ifindex : 0;
315 salen = sizeof(sa.in6);
316 } else
317 return -EAFNOSUPPORT;
318 } else {
519ef046
LP
319 assert(family != AF_UNSPEC);
320 assert(address);
321
623a4c97
LP
322 sa.sa.sa_family = family;
323
324 if (family == AF_INET) {
325 sa.in.sin_port = htobe16(port);
326 sa.in.sin_addr = address->in;
327 salen = sizeof(sa.in);
328 } else if (family == AF_INET6) {
329 sa.in6.sin6_port = htobe16(port);
330 sa.in6.sin6_addr = address->in6;
331 sa.in6.sin6_scope_id = s->link ? s->link->ifindex : 0;
332 salen = sizeof(sa.in6);
333 } else
334 return -EAFNOSUPPORT;
335 }
ad867662 336
0db64366 337 fd = socket(sa.sa.sa_family, type|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
ad867662
LP
338 if (fd < 0)
339 return -errno;
340
0db64366
TG
341 if (type == SOCK_STREAM) {
342 r = setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &one, sizeof(one));
343 if (r < 0)
344 return -errno;
345 }
623a4c97
LP
346
347 if (s->link) {
348 uint32_t ifindex = htobe32(s->link->ifindex);
349
350 if (sa.sa.sa_family == AF_INET) {
351 r = setsockopt(fd, IPPROTO_IP, IP_UNICAST_IF, &ifindex, sizeof(ifindex));
352 if (r < 0)
353 return -errno;
354 } else if (sa.sa.sa_family == AF_INET6) {
355 r = setsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_IF, &ifindex, sizeof(ifindex));
356 if (r < 0)
357 return -errno;
358 }
359 }
360
361 if (s->protocol == DNS_PROTOCOL_LLMNR) {
bf3f1271 362 /* RFC 4795, section 2.5 requires the TTL to be set to 1 */
623a4c97
LP
363
364 if (sa.sa.sa_family == AF_INET) {
365 r = setsockopt(fd, IPPROTO_IP, IP_TTL, &one, sizeof(one));
366 if (r < 0)
367 return -errno;
368 } else if (sa.sa.sa_family == AF_INET6) {
369 r = setsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &one, sizeof(one));
370 if (r < 0)
371 return -errno;
372 }
373 }
ad867662
LP
374
375 r = connect(fd, &sa.sa, salen);
376 if (r < 0 && errno != EINPROGRESS)
377 return -errno;
378
379 ret = fd;
380 fd = -1;
623a4c97 381
ad867662
LP
382 return ret;
383}
384
519ef046
LP
385int dns_scope_socket_udp(DnsScope *s, DnsServer *server, uint16_t port) {
386 return dns_scope_socket(s, SOCK_DGRAM, AF_UNSPEC, NULL, server, port);
0db64366
TG
387}
388
519ef046
LP
389int dns_scope_socket_tcp(DnsScope *s, int family, const union in_addr_union *address, DnsServer *server, uint16_t port) {
390 return dns_scope_socket(s, SOCK_STREAM, family, address, server, port);
0db64366
TG
391}
392
51323288 393DnsScopeMatch dns_scope_good_domain(DnsScope *s, int ifindex, uint64_t flags, const char *domain) {
a51c1048 394 DnsSearchDomain *d;
74b2466e
LP
395
396 assert(s);
397 assert(domain);
398
28b9b764
LP
399 /* Checks if the specified domain is something to look up on
400 * this scope. Note that this accepts non-qualified hostnames,
401 * i.e. those without any search path prefixed yet. */
402
51323288
LP
403 if (ifindex != 0 && (!s->link || s->link->ifindex != ifindex))
404 return DNS_SCOPE_NO;
405
931851e8 406 if ((SD_RESOLVED_FLAGS_MAKE(s->protocol, s->family, 0) & flags) == 0)
51323288
LP
407 return DNS_SCOPE_NO;
408
78c6a153
LP
409 /* Never resolve any loopback hostname or IP address via DNS,
410 * LLMNR or mDNS. Instead, always rely on synthesized RRs for
411 * these. */
412 if (is_localhost(domain) ||
413 dns_name_endswith(domain, "127.in-addr.arpa") > 0 ||
9436e8ca
LP
414 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)
415 return DNS_SCOPE_NO;
416
c9ad0edb
LP
417 /* Never respond to some of the domains listed in RFC6303 */
418 if (dns_name_endswith(domain, "0.in-addr.arpa") > 0 ||
419 dns_name_equal(domain, "255.255.255.255.in-addr.arpa") > 0 ||
420 dns_name_equal(domain, "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.0.ip6.arpa") > 0)
421 return DNS_SCOPE_NO;
422
7bcffc2e
LP
423 /* Never respond to some of the domains listed in RFC6761 */
424 if (dns_name_endswith(domain, "invalid") > 0)
425 return DNS_SCOPE_NO;
426
801ad6a6
LP
427 /* Always honour search domains for routing queries. Note that
428 * we return DNS_SCOPE_YES here, rather than just
429 * DNS_SCOPE_MAYBE, which means wildcard scopes won't be
430 * considered anymore. */
a51c1048
LP
431 LIST_FOREACH(domains, d, dns_scope_get_search_domains(s))
432 if (dns_name_endswith(domain, d->name) > 0)
9b644bf9
LP
433 return DNS_SCOPE_YES;
434
106784eb 435 switch (s->protocol) {
801ad6a6 436
dc477e73 437 case DNS_PROTOCOL_DNS:
801ad6a6 438
28b9b764
LP
439 /* Exclude link-local IP ranges */
440 if (dns_name_endswith(domain, "254.169.in-addr.arpa") == 0 &&
c9ad0edb
LP
441 dns_name_endswith(domain, "8.e.f.ip6.arpa") == 0 &&
442 dns_name_endswith(domain, "9.e.f.ip6.arpa") == 0 &&
443 dns_name_endswith(domain, "a.e.f.ip6.arpa") == 0 &&
b43d96b0
DM
444 dns_name_endswith(domain, "b.e.f.ip6.arpa") == 0 &&
445 /* If networks use .local in their private setups, they are supposed to also add .local to their search
446 * domains, which we already checked above. Otherwise, we consider .local specific to mDNS and won't
447 * send such queries ordinary DNS servers. */
448 dns_name_endswith(domain, "local") == 0)
faa133f3 449 return DNS_SCOPE_MAYBE;
1716f6dc 450
faa133f3 451 return DNS_SCOPE_NO;
1716f6dc 452
106784eb 453 case DNS_PROTOCOL_MDNS:
78c6a153
LP
454 if ((s->family == AF_INET && dns_name_endswith(domain, "in-addr.arpa") > 0) ||
455 (s->family == AF_INET6 && dns_name_endswith(domain, "ip6.arpa") > 0) ||
456 (dns_name_endswith(domain, "local") > 0 && /* only resolve names ending in .local via mDNS */
457 dns_name_equal(domain, "local") == 0 && /* but not the single-label "local" name itself */
458 manager_is_own_hostname(s->manager, domain) <= 0)) /* never resolve the local hostname via mDNS */
d8b7e75f 459 return DNS_SCOPE_MAYBE;
74b2466e
LP
460
461 return DNS_SCOPE_NO;
74b2466e 462
106784eb 463 case DNS_PROTOCOL_LLMNR:
78c6a153
LP
464 if ((s->family == AF_INET && dns_name_endswith(domain, "in-addr.arpa") > 0) ||
465 (s->family == AF_INET6 && dns_name_endswith(domain, "ip6.arpa") > 0) ||
dc477e73 466 (dns_name_is_single_label(domain) && /* only resolve single label names via LLMNR */
78c6a153
LP
467 !is_gateway_hostname(domain) && /* don't resolve "gateway" with LLMNR, let nss-myhostname handle this */
468 manager_is_own_hostname(s->manager, domain) <= 0)) /* never resolve the local hostname via LLMNR */
1716f6dc 469 return DNS_SCOPE_MAYBE;
74b2466e 470
1716f6dc 471 return DNS_SCOPE_NO;
74b2466e 472
106784eb
DM
473 default:
474 assert_not_reached("Unknown scope protocol");
475 }
1716f6dc
LP
476}
477
478int dns_scope_good_key(DnsScope *s, DnsResourceKey *key) {
479 assert(s);
480 assert(key);
481
28b9b764
LP
482 /* Check if it makes sense to resolve the specified key on
483 * this scope. Note that this call assumes as fully qualified
484 * name, i.e. the search suffixes already appended. */
485
486 if (s->protocol == DNS_PROTOCOL_DNS) {
487
e5abebab 488 /* On classic DNS, looking up non-address RRs is always
28b9b764
LP
489 * fine. (Specifically, we want to permit looking up
490 * DNSKEY and DS records on the root and top-level
491 * domains.) */
492 if (!dns_resource_key_is_address(key))
493 return true;
494
495 /* However, we refuse to look up A and AAAA RRs on the
496 * root and single-label domains, under the assumption
497 * that those should be resolved via LLMNR or search
498 * path only, and should not be leaked onto the
499 * internet. */
500 return !(dns_name_is_single_label(DNS_RESOURCE_KEY_NAME(key)) ||
501 dns_name_is_root(DNS_RESOURCE_KEY_NAME(key)));
502 }
1716f6dc
LP
503
504 /* On mDNS and LLMNR, send A and AAAA queries only on the
505 * respective scopes */
506
507 if (s->family == AF_INET && key->class == DNS_CLASS_IN && key->type == DNS_TYPE_AAAA)
508 return false;
509
510 if (s->family == AF_INET6 && key->class == DNS_CLASS_IN && key->type == DNS_TYPE_A)
511 return false;
512
513 return true;
514}
515
0db4c90a 516static int dns_scope_multicast_membership(DnsScope *s, bool b, struct in_addr in, struct in6_addr in6) {
1716f6dc
LP
517 int fd;
518
5ba73e9b 519 assert(s);
5ba73e9b
LP
520 assert(s->link);
521
1716f6dc
LP
522 if (s->family == AF_INET) {
523 struct ip_mreqn mreqn = {
0db4c90a 524 .imr_multiaddr = in,
1716f6dc
LP
525 .imr_ifindex = s->link->ifindex,
526 };
527
528 fd = manager_llmnr_ipv4_udp_fd(s->manager);
529 if (fd < 0)
530 return fd;
531
7b4c2ee7
LP
532 /* Always first try to drop membership before we add
533 * one. This is necessary on some devices, such as
534 * veth. */
535 if (b)
dc751688 536 (void) setsockopt(fd, IPPROTO_IP, IP_DROP_MEMBERSHIP, &mreqn, sizeof(mreqn));
7b4c2ee7 537
1716f6dc
LP
538 if (setsockopt(fd, IPPROTO_IP, b ? IP_ADD_MEMBERSHIP : IP_DROP_MEMBERSHIP, &mreqn, sizeof(mreqn)) < 0)
539 return -errno;
540
541 } else if (s->family == AF_INET6) {
542 struct ipv6_mreq mreq = {
0db4c90a 543 .ipv6mr_multiaddr = in6,
1716f6dc
LP
544 .ipv6mr_interface = s->link->ifindex,
545 };
546
547 fd = manager_llmnr_ipv6_udp_fd(s->manager);
548 if (fd < 0)
549 return fd;
550
7b4c2ee7 551 if (b)
dc751688 552 (void) setsockopt(fd, IPPROTO_IPV6, IPV6_DROP_MEMBERSHIP, &mreq, sizeof(mreq));
7b4c2ee7 553
1716f6dc
LP
554 if (setsockopt(fd, IPPROTO_IPV6, b ? IPV6_ADD_MEMBERSHIP : IPV6_DROP_MEMBERSHIP, &mreq, sizeof(mreq)) < 0)
555 return -errno;
556 } else
557 return -EAFNOSUPPORT;
558
559 return 0;
74b2466e 560}
623a4c97 561
0db4c90a
DM
562int dns_scope_llmnr_membership(DnsScope *s, bool b) {
563
564 if (s->protocol != DNS_PROTOCOL_LLMNR)
565 return 0;
566
567 return dns_scope_multicast_membership(s, b, LLMNR_MULTICAST_IPV4_ADDRESS, LLMNR_MULTICAST_IPV6_ADDRESS);
568}
569
570int dns_scope_mdns_membership(DnsScope *s, bool b) {
571
572 if (s->protocol != DNS_PROTOCOL_MDNS)
573 return 0;
574
575 return dns_scope_multicast_membership(s, b, MDNS_MULTICAST_IPV4_ADDRESS, MDNS_MULTICAST_IPV6_ADDRESS);
576}
577
ec2c5e43
LP
578static int dns_scope_make_reply_packet(
579 DnsScope *s,
580 uint16_t id,
581 int rcode,
582 DnsQuestion *q,
583 DnsAnswer *answer,
584 DnsAnswer *soa,
585 bool tentative,
586 DnsPacket **ret) {
587
623a4c97
LP
588 _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
589 unsigned i;
590 int r;
591
592 assert(s);
a4076574 593 assert(ret);
623a4c97 594
75cd513e
TA
595 if ((!q || q->n_keys <= 0)
596 && (!answer || answer->n_rrs <= 0)
597 && (!soa || soa->n_rrs <= 0))
623a4c97
LP
598 return -EINVAL;
599
600 r = dns_packet_new(&p, s->protocol, 0);
601 if (r < 0)
602 return r;
603
604 DNS_PACKET_HEADER(p)->id = id;
ea917db9
LP
605 DNS_PACKET_HEADER(p)->flags = htobe16(DNS_PACKET_MAKE_FLAGS(
606 1 /* qr */,
607 0 /* opcode */,
608 0 /* c */,
609 0 /* tc */,
ec2c5e43 610 tentative,
ea917db9
LP
611 0 /* (ra) */,
612 0 /* (ad) */,
613 0 /* (cd) */,
614 rcode));
623a4c97
LP
615
616 if (q) {
617 for (i = 0; i < q->n_keys; i++) {
618 r = dns_packet_append_key(p, q->keys[i], NULL);
619 if (r < 0)
620 return r;
621 }
622
623 DNS_PACKET_HEADER(p)->qdcount = htobe16(q->n_keys);
624 }
625
8bf52d3d
LP
626 if (answer) {
627 for (i = 0; i < answer->n_rrs; i++) {
a8812dd7 628 r = dns_packet_append_rr(p, answer->items[i].rr, NULL, NULL);
623a4c97
LP
629 if (r < 0)
630 return r;
631 }
632
8bf52d3d
LP
633 DNS_PACKET_HEADER(p)->ancount = htobe16(answer->n_rrs);
634 }
635
636 if (soa) {
637 for (i = 0; i < soa->n_rrs; i++) {
a8812dd7 638 r = dns_packet_append_rr(p, soa->items[i].rr, NULL, NULL);
8bf52d3d
LP
639 if (r < 0)
640 return r;
641 }
642
643 DNS_PACKET_HEADER(p)->arcount = htobe16(soa->n_rrs);
623a4c97
LP
644 }
645
646 *ret = p;
647 p = NULL;
648
649 return 0;
650}
651
a4076574
LP
652static void dns_scope_verify_conflicts(DnsScope *s, DnsPacket *p) {
653 unsigned n;
654
655 assert(s);
656 assert(p);
657
658 if (p->question)
659 for (n = 0; n < p->question->n_keys; n++)
660 dns_zone_verify_conflicts(&s->zone, p->question->keys[n]);
661 if (p->answer)
662 for (n = 0; n < p->answer->n_rrs; n++)
78c6a153 663 dns_zone_verify_conflicts(&s->zone, p->answer->items[n].rr->key);
a4076574
LP
664}
665
623a4c97
LP
666void dns_scope_process_query(DnsScope *s, DnsStream *stream, DnsPacket *p) {
667 _cleanup_(dns_packet_unrefp) DnsPacket *reply = NULL;
8bf52d3d 668 _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL, *soa = NULL;
5032b16d 669 DnsResourceKey *key = NULL;
ec2c5e43 670 bool tentative = false;
623a4c97
LP
671 int r, fd;
672
673 assert(s);
674 assert(p);
675
676 if (p->protocol != DNS_PROTOCOL_LLMNR)
677 return;
678
2442b93d
LP
679 if (p->ipproto == IPPROTO_UDP) {
680 /* Don't accept UDP queries directed to anything but
681 * the LLMNR multicast addresses. See RFC 4795,
d076c6f9 682 * section 2.5. */
2442b93d
LP
683
684 if (p->family == AF_INET && !in_addr_equal(AF_INET, &p->destination, (union in_addr_union*) &LLMNR_MULTICAST_IPV4_ADDRESS))
685 return;
686
687 if (p->family == AF_INET6 && !in_addr_equal(AF_INET6, &p->destination, (union in_addr_union*) &LLMNR_MULTICAST_IPV6_ADDRESS))
688 return;
689 }
690
623a4c97
LP
691 r = dns_packet_extract(p);
692 if (r < 0) {
da927ba9 693 log_debug_errno(r, "Failed to extract resources from incoming packet: %m");
623a4c97
LP
694 return;
695 }
696
8b757a38 697 if (DNS_PACKET_LLMNR_C(p)) {
a4076574
LP
698 /* Somebody notified us about a possible conflict */
699 dns_scope_verify_conflicts(s, p);
ea917db9
LP
700 return;
701 }
702
5032b16d
LP
703 assert(p->question->n_keys == 1);
704 key = p->question->keys[0];
705
706 r = dns_zone_lookup(&s->zone, key, &answer, &soa, &tentative);
623a4c97 707 if (r < 0) {
da927ba9 708 log_debug_errno(r, "Failed to lookup key: %m");
623a4c97
LP
709 return;
710 }
711 if (r == 0)
712 return;
713
fcf57f9c
LP
714 if (answer)
715 dns_answer_order_by_scope(answer, in_addr_is_link_local(p->family, &p->sender) > 0);
af93291c 716
ec2c5e43 717 r = dns_scope_make_reply_packet(s, DNS_PACKET_ID(p), DNS_RCODE_SUCCESS, p->question, answer, soa, tentative, &reply);
623a4c97 718 if (r < 0) {
da927ba9 719 log_debug_errno(r, "Failed to build reply packet: %m");
623a4c97
LP
720 return;
721 }
722
723 if (stream)
724 r = dns_stream_write_packet(stream, reply);
725 else {
aea2429d
LP
726 if (!ratelimit_test(&s->ratelimit))
727 return;
728
623a4c97
LP
729 if (p->family == AF_INET)
730 fd = manager_llmnr_ipv4_udp_fd(s->manager);
731 else if (p->family == AF_INET6)
732 fd = manager_llmnr_ipv6_udp_fd(s->manager);
733 else {
734 log_debug("Unknown protocol");
735 return;
736 }
737 if (fd < 0) {
da927ba9 738 log_debug_errno(fd, "Failed to get reply socket: %m");
623a4c97
LP
739 return;
740 }
741
6e068472
LP
742 /* Note that we always immediately reply to all LLMNR
743 * requests, and do not wait any time, since we
744 * verified uniqueness for all records. Also see RFC
745 * 4795, Section 2.7 */
746
623a4c97
LP
747 r = manager_send(s->manager, fd, p->ifindex, p->family, &p->sender, p->sender_port, reply);
748 }
749
750 if (r < 0) {
da927ba9 751 log_debug_errno(r, "Failed to send reply packet: %m");
623a4c97
LP
752 return;
753 }
754}
ec2c5e43 755
f52e61da 756DnsTransaction *dns_scope_find_transaction(DnsScope *scope, DnsResourceKey *key, bool cache_ok) {
ec2c5e43
LP
757 DnsTransaction *t;
758
759 assert(scope);
f52e61da 760 assert(key);
ec2c5e43 761
da0c630e
LP
762 /* Try to find an ongoing transaction that is a equal to the
763 * specified question */
f9ebb22a 764 t = hashmap_get(scope->transactions_by_key, key);
da0c630e
LP
765 if (!t)
766 return NULL;
dc4d47e2 767
da0c630e
LP
768 /* Refuse reusing transactions that completed based on cached
769 * data instead of a real packet, if that's requested. */
770 if (!cache_ok &&
3bbdc31d 771 IN_SET(t->state, DNS_TRANSACTION_SUCCESS, DNS_TRANSACTION_RCODE_FAILURE) &&
c3bc53e6 772 t->answer_source != DNS_TRANSACTION_NETWORK)
da0c630e 773 return NULL;
ec2c5e43 774
da0c630e 775 return t;
ec2c5e43 776}
a4076574
LP
777
778static int dns_scope_make_conflict_packet(
779 DnsScope *s,
780 DnsResourceRecord *rr,
781 DnsPacket **ret) {
782
783 _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
784 int r;
785
786 assert(s);
787 assert(rr);
788 assert(ret);
789
790 r = dns_packet_new(&p, s->protocol, 0);
791 if (r < 0)
792 return r;
793
794 DNS_PACKET_HEADER(p)->flags = htobe16(DNS_PACKET_MAKE_FLAGS(
795 0 /* qr */,
796 0 /* opcode */,
797 1 /* conflict */,
798 0 /* tc */,
799 0 /* t */,
800 0 /* (ra) */,
801 0 /* (ad) */,
802 0 /* (cd) */,
803 0));
fe2dfc8b
DM
804
805 /* For mDNS, the transaction ID should always be 0 */
806 if (s->protocol != DNS_PROTOCOL_MDNS)
807 random_bytes(&DNS_PACKET_HEADER(p)->id, sizeof(uint16_t));
808
a4076574
LP
809 DNS_PACKET_HEADER(p)->qdcount = htobe16(1);
810 DNS_PACKET_HEADER(p)->arcount = htobe16(1);
811
812 r = dns_packet_append_key(p, rr->key, NULL);
813 if (r < 0)
814 return r;
815
a8812dd7 816 r = dns_packet_append_rr(p, rr, NULL, NULL);
a4076574
LP
817 if (r < 0)
818 return r;
819
820 *ret = p;
821 p = NULL;
822
823 return 0;
824}
825
826static int on_conflict_dispatch(sd_event_source *es, usec_t usec, void *userdata) {
827 DnsScope *scope = userdata;
828 int r;
829
830 assert(es);
831 assert(scope);
832
833 scope->conflict_event_source = sd_event_source_unref(scope->conflict_event_source);
834
835 for (;;) {
836 _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
837 _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
838
1e43061b 839 rr = ordered_hashmap_steal_first(scope->conflict_queue);
a4076574
LP
840 if (!rr)
841 break;
842
843 r = dns_scope_make_conflict_packet(scope, rr, &p);
844 if (r < 0) {
da927ba9 845 log_error_errno(r, "Failed to make conflict packet: %m");
a4076574
LP
846 return 0;
847 }
848
519ef046 849 r = dns_scope_emit_udp(scope, -1, p);
a4076574 850 if (r < 0)
da927ba9 851 log_debug_errno(r, "Failed to send conflict packet: %m");
a4076574
LP
852 }
853
854 return 0;
855}
856
857int dns_scope_notify_conflict(DnsScope *scope, DnsResourceRecord *rr) {
858 usec_t jitter;
859 int r;
860
861 assert(scope);
862 assert(rr);
863
864 /* We don't send these queries immediately. Instead, we queue
865 * them, and send them after some jitter delay. */
1e43061b 866 r = ordered_hashmap_ensure_allocated(&scope->conflict_queue, &dns_resource_key_hash_ops);
a4076574
LP
867 if (r < 0) {
868 log_oom();
869 return r;
870 }
871
872 /* We only place one RR per key in the conflict
873 * messages, not all of them. That should be enough to
874 * indicate where there might be a conflict */
1e43061b 875 r = ordered_hashmap_put(scope->conflict_queue, rr->key, rr);
a4076574
LP
876 if (r == -EEXIST || r == 0)
877 return 0;
f647962d
MS
878 if (r < 0)
879 return log_debug_errno(r, "Failed to queue conflicting RR: %m");
a4076574
LP
880
881 dns_resource_record_ref(rr);
882
883 if (scope->conflict_event_source)
884 return 0;
885
886 random_bytes(&jitter, sizeof(jitter));
887 jitter %= LLMNR_JITTER_INTERVAL_USEC;
888
889 r = sd_event_add_time(scope->manager->event,
890 &scope->conflict_event_source,
891 clock_boottime_or_monotonic(),
892 now(clock_boottime_or_monotonic()) + jitter,
893 LLMNR_JITTER_INTERVAL_USEC,
894 on_conflict_dispatch, scope);
f647962d
MS
895 if (r < 0)
896 return log_debug_errno(r, "Failed to add conflict dispatch event: %m");
a4076574
LP
897
898 return 0;
899}
900
901void dns_scope_check_conflicts(DnsScope *scope, DnsPacket *p) {
902 unsigned i;
903 int r;
904
905 assert(scope);
906 assert(p);
907
908 if (p->protocol != DNS_PROTOCOL_LLMNR)
909 return;
910
911 if (DNS_PACKET_RRCOUNT(p) <= 0)
912 return;
913
8b757a38 914 if (DNS_PACKET_LLMNR_C(p) != 0)
a4076574
LP
915 return;
916
8b757a38 917 if (DNS_PACKET_LLMNR_T(p) != 0)
a4076574
LP
918 return;
919
920 if (manager_our_packet(scope->manager, p))
921 return;
922
923 r = dns_packet_extract(p);
924 if (r < 0) {
da927ba9 925 log_debug_errno(r, "Failed to extract packet: %m");
a4076574
LP
926 return;
927 }
928
929 log_debug("Checking for conflicts...");
930
931 for (i = 0; i < p->answer->n_rrs; i++) {
932
933 /* Check for conflicts against the local zone. If we
934 * found one, we won't check any further */
78c6a153 935 r = dns_zone_check_conflicts(&scope->zone, p->answer->items[i].rr);
a4076574
LP
936 if (r != 0)
937 continue;
938
939 /* Check for conflicts against the local cache. If so,
940 * send out an advisory query, to inform everybody */
78c6a153 941 r = dns_cache_check_conflicts(&scope->cache, p->answer->items[i].rr, p->family, &p->sender);
a4076574
LP
942 if (r <= 0)
943 continue;
944
78c6a153 945 dns_scope_notify_conflict(scope, p->answer->items[i].rr);
a4076574
LP
946 }
947}
4d506d6b
LP
948
949void dns_scope_dump(DnsScope *s, FILE *f) {
950 assert(s);
951
952 if (!f)
953 f = stdout;
954
955 fputs("[Scope protocol=", f);
956 fputs(dns_protocol_to_string(s->protocol), f);
957
958 if (s->link) {
959 fputs(" interface=", f);
960 fputs(s->link->name, f);
961 }
962
963 if (s->family != AF_UNSPEC) {
964 fputs(" family=", f);
965 fputs(af_to_name(s->family), f);
966 }
967
968 fputs("]\n", f);
969
970 if (!dns_zone_is_empty(&s->zone)) {
971 fputs("ZONE:\n", f);
972 dns_zone_dump(&s->zone, f);
973 }
974
975 if (!dns_cache_is_empty(&s->cache)) {
976 fputs("CACHE:\n", f);
977 dns_cache_dump(&s->cache, f);
978 }
979}
a51c1048
LP
980
981DnsSearchDomain *dns_scope_get_search_domains(DnsScope *s) {
801ad6a6
LP
982 assert(s);
983
a51c1048
LP
984 if (s->protocol != DNS_PROTOCOL_DNS)
985 return NULL;
986
987 if (s->link)
988 return s->link->search_domains;
989
28b9b764 990 return s->manager->search_domains;
801ad6a6
LP
991}
992
dc477e73 993bool dns_scope_name_needs_search_domain(DnsScope *s, const char *name) {
801ad6a6
LP
994 assert(s);
995
996 if (s->protocol != DNS_PROTOCOL_DNS)
dc477e73 997 return false;
801ad6a6 998
dc477e73 999 return dns_name_is_single_label(name);
801ad6a6 1000}