]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/resolve/resolved-dns-scope.c
tree-wide: drop 'This file is part of systemd' blurb
[thirdparty/systemd.git] / src / resolve / resolved-dns-scope.c
CommitLineData
53e1b683 1/* SPDX-License-Identifier: LGPL-2.1+ */
74b2466e 2/***
74b2466e 3 Copyright 2014 Lennart Poettering
74b2466e
LP
4***/
5
ad867662
LP
6#include <netinet/tcp.h>
7
46f08bea 8#include "af-list.h"
b5efdb8a 9#include "alloc-util.h"
4ad7f276 10#include "dns-domain.h"
3ffd4af2
LP
11#include "fd-util.h"
12#include "hostname-util.h"
13#include "missing.h"
14#include "random-util.h"
6db6a464 15#include "resolved-dnssd.h"
74b2466e 16#include "resolved-dns-scope.h"
a2bf8a19 17#include "resolved-dns-zone.h"
3ffd4af2 18#include "resolved-llmnr.h"
b4f1862d 19#include "resolved-mdns.h"
3ffd4af2
LP
20#include "socket-util.h"
21#include "strv.h"
74b2466e 22
aea2429d
LP
23#define MULTICAST_RATELIMIT_INTERVAL_USEC (1*USEC_PER_SEC)
24#define MULTICAST_RATELIMIT_BURST 1000
25
9df3ba6c
TG
26/* After how much time to repeat LLMNR requests, see RFC 4795 Section 7 */
27#define MULTICAST_RESEND_TIMEOUT_MIN_USEC (100 * USEC_PER_MSEC)
28#define MULTICAST_RESEND_TIMEOUT_MAX_USEC (1 * USEC_PER_SEC)
29
0dd25fb9 30int dns_scope_new(Manager *m, DnsScope **ret, Link *l, DnsProtocol protocol, int family) {
74b2466e
LP
31 DnsScope *s;
32
33 assert(m);
34 assert(ret);
35
36 s = new0(DnsScope, 1);
37 if (!s)
38 return -ENOMEM;
39
40 s->manager = m;
1716f6dc
LP
41 s->link = l;
42 s->protocol = protocol;
43 s->family = family;
9df3ba6c 44 s->resend_timeout = MULTICAST_RESEND_TIMEOUT_MIN_USEC;
74b2466e 45
ad6c0475
LP
46 if (protocol == DNS_PROTOCOL_DNS) {
47 /* Copy DNSSEC mode from the link if it is set there,
48 * otherwise take the manager's DNSSEC mode. Note that
49 * we copy this only at scope creation time, and do
50 * not update it from the on, even if the setting
51 * changes. */
52
d050561a 53 if (l) {
c69fa7e3 54 s->dnssec_mode = link_get_dnssec_mode(l);
c9299be2 55 s->dns_over_tls_mode = link_get_dns_over_tls_mode(l);
d050561a 56 } else {
c69fa7e3 57 s->dnssec_mode = manager_get_dnssec_mode(m);
c9299be2 58 s->dns_over_tls_mode = manager_get_dns_over_tls_mode(m);
d050561a 59 }
5d67a7ae 60
5d67a7ae 61 } else {
658f7f02 62 s->dnssec_mode = DNSSEC_NO;
c9299be2 63 s->dns_over_tls_mode = DNS_OVER_TLS_NO;
5d67a7ae 64 }
ad6c0475 65
74b2466e
LP
66 LIST_PREPEND(scopes, m->dns_scopes, s);
67
1716f6dc 68 dns_scope_llmnr_membership(s, true);
0db4c90a 69 dns_scope_mdns_membership(s, true);
1716f6dc 70
46f08bea 71 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 72
aea2429d
LP
73 /* Enforce ratelimiting for the multicast protocols */
74 RATELIMIT_INIT(s->ratelimit, MULTICAST_RATELIMIT_INTERVAL_USEC, MULTICAST_RATELIMIT_BURST);
75
74b2466e
LP
76 *ret = s;
77 return 0;
78}
79
801ad6a6 80static void dns_scope_abort_transactions(DnsScope *s) {
801ad6a6 81 assert(s);
1716f6dc 82
f9ebb22a
LP
83 while (s->transactions) {
84 DnsTransaction *t = s->transactions;
85
faa133f3
LP
86 /* Abort the transaction, but make sure it is not
87 * freed while we still look at it */
74b2466e 88
faa133f3 89 t->block_gc++;
f4e38037
LP
90 if (DNS_TRANSACTION_IS_LIVE(t->state))
91 dns_transaction_complete(t, DNS_TRANSACTION_ABORTED);
faa133f3 92 t->block_gc--;
74b2466e 93
ec2c5e43 94 dns_transaction_free(t);
74b2466e 95 }
801ad6a6
LP
96}
97
98DnsScope* dns_scope_free(DnsScope *s) {
801ad6a6
LP
99 if (!s)
100 return NULL;
101
102 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));
103
104 dns_scope_llmnr_membership(s, false);
0db4c90a 105 dns_scope_mdns_membership(s, false);
801ad6a6
LP
106 dns_scope_abort_transactions(s);
107
108 while (s->query_candidates)
109 dns_query_candidate_free(s->query_candidates);
74b2466e 110
f9ebb22a 111 hashmap_free(s->transactions_by_key);
da0c630e 112
224b0e7a 113 ordered_hashmap_free_with_destructor(s->conflict_queue, dns_resource_record_unref);
a4076574
LP
114 sd_event_source_unref(s->conflict_event_source);
115
53fda2bb
DR
116 sd_event_source_unref(s->announce_event_source);
117
322345fd 118 dns_cache_flush(&s->cache);
623a4c97 119 dns_zone_flush(&s->zone);
322345fd 120
74b2466e 121 LIST_REMOVE(scopes, s->manager->dns_scopes, s);
6b430fdb 122 return mfree(s);
74b2466e
LP
123}
124
2c27fbca 125DnsServer *dns_scope_get_dns_server(DnsScope *s) {
74b2466e
LP
126 assert(s);
127
1716f6dc
LP
128 if (s->protocol != DNS_PROTOCOL_DNS)
129 return NULL;
130
74b2466e
LP
131 if (s->link)
132 return link_get_dns_server(s->link);
133 else
134 return manager_get_dns_server(s->manager);
135}
136
44db02d0
LP
137unsigned dns_scope_get_n_dns_servers(DnsScope *s) {
138 unsigned n = 0;
139 DnsServer *i;
140
141 assert(s);
142
143 if (s->protocol != DNS_PROTOCOL_DNS)
144 return 0;
145
146 if (s->link)
147 i = s->link->dns_servers;
148 else
149 i = s->manager->dns_servers;
150
151 for (; i; i = i->servers_next)
152 n++;
153
154 return n;
155}
156
74b2466e
LP
157void dns_scope_next_dns_server(DnsScope *s) {
158 assert(s);
159
1716f6dc
LP
160 if (s->protocol != DNS_PROTOCOL_DNS)
161 return;
162
74b2466e
LP
163 if (s->link)
164 link_next_dns_server(s->link);
165 else
166 manager_next_dns_server(s->manager);
167}
168
9df3ba6c
TG
169void dns_scope_packet_received(DnsScope *s, usec_t rtt) {
170 assert(s);
171
84129d46
LP
172 if (rtt <= s->max_rtt)
173 return;
174
175 s->max_rtt = rtt;
176 s->resend_timeout = MIN(MAX(MULTICAST_RESEND_TIMEOUT_MIN_USEC, s->max_rtt * 2), MULTICAST_RESEND_TIMEOUT_MAX_USEC);
9df3ba6c
TG
177}
178
179void dns_scope_packet_lost(DnsScope *s, usec_t usec) {
180 assert(s);
181
182 if (s->resend_timeout <= usec)
183 s->resend_timeout = MIN(s->resend_timeout * 2, MULTICAST_RESEND_TIMEOUT_MAX_USEC);
184}
185
519ef046 186static int dns_scope_emit_one(DnsScope *s, int fd, DnsPacket *p) {
1716f6dc
LP
187 union in_addr_union addr;
188 int ifindex = 0, r;
0dd25fb9 189 int family;
1716f6dc 190 uint32_t mtu;
74b2466e
LP
191
192 assert(s);
193 assert(p);
1716f6dc 194 assert(p->protocol == s->protocol);
ad867662
LP
195
196 if (s->link) {
1716f6dc 197 mtu = s->link->mtu;
74b2466e 198 ifindex = s->link->ifindex;
1716f6dc 199 } else
e1c95994 200 mtu = manager_find_mtu(s->manager);
74b2466e 201
106784eb 202 switch (s->protocol) {
519ef046 203
106784eb 204 case DNS_PROTOCOL_DNS:
519ef046 205 assert(fd >= 0);
9c5e12a4 206
623a4c97 207 if (DNS_PACKET_QDCOUNT(p) > 1)
15411c0c 208 return -EOPNOTSUPP;
623a4c97 209
1716f6dc
LP
210 if (p->size > DNS_PACKET_UNICAST_SIZE_MAX)
211 return -EMSGSIZE;
212
a0166609 213 if (p->size + UDP_PACKET_HEADER_SIZE > mtu)
1716f6dc
LP
214 return -EMSGSIZE;
215
72290734
TG
216 r = manager_write(s->manager, fd, p);
217 if (r < 0)
218 return r;
219
106784eb 220 break;
1716f6dc 221
106784eb 222 case DNS_PROTOCOL_LLMNR:
519ef046
LP
223 assert(fd < 0);
224
1716f6dc 225 if (DNS_PACKET_QDCOUNT(p) > 1)
15411c0c 226 return -EOPNOTSUPP;
1716f6dc 227
7994ac1d 228 if (!ratelimit_below(&s->ratelimit))
aea2429d
LP
229 return -EBUSY;
230
1716f6dc 231 family = s->family;
1716f6dc
LP
232
233 if (family == AF_INET) {
234 addr.in = LLMNR_MULTICAST_IPV4_ADDRESS;
1716f6dc
LP
235 fd = manager_llmnr_ipv4_udp_fd(s->manager);
236 } else if (family == AF_INET6) {
237 addr.in6 = LLMNR_MULTICAST_IPV6_ADDRESS;
238 fd = manager_llmnr_ipv6_udp_fd(s->manager);
1716f6dc
LP
239 } else
240 return -EAFNOSUPPORT;
241 if (fd < 0)
242 return fd;
72290734 243
b30bf55d 244 r = manager_send(s->manager, fd, ifindex, family, &addr, LLMNR_PORT, NULL, p);
b4f1862d
DM
245 if (r < 0)
246 return r;
247
248 break;
249
250 case DNS_PROTOCOL_MDNS:
519ef046
LP
251 assert(fd < 0);
252
7994ac1d 253 if (!ratelimit_below(&s->ratelimit))
b4f1862d
DM
254 return -EBUSY;
255
256 family = s->family;
257
258 if (family == AF_INET) {
259 addr.in = MDNS_MULTICAST_IPV4_ADDRESS;
260 fd = manager_mdns_ipv4_fd(s->manager);
261 } else if (family == AF_INET6) {
262 addr.in6 = MDNS_MULTICAST_IPV6_ADDRESS;
263 fd = manager_mdns_ipv6_fd(s->manager);
264 } else
265 return -EAFNOSUPPORT;
266 if (fd < 0)
267 return fd;
268
b30bf55d 269 r = manager_send(s->manager, fd, ifindex, family, &addr, MDNS_PORT, NULL, p);
72290734
TG
270 if (r < 0)
271 return r;
106784eb
DM
272
273 break;
274
275 default:
74b2466e 276 return -EAFNOSUPPORT;
106784eb 277 }
74b2466e 278
74b2466e
LP
279 return 1;
280}
281
519ef046 282int dns_scope_emit_udp(DnsScope *s, int fd, DnsPacket *p) {
80a62095
DM
283 int r;
284
285 assert(s);
286 assert(p);
287 assert(p->protocol == s->protocol);
519ef046 288 assert((s->protocol == DNS_PROTOCOL_DNS) == (fd >= 0));
80a62095
DM
289
290 do {
291 /* If there are multiple linked packets, set the TC bit in all but the last of them */
292 if (p->more) {
293 assert(p->protocol == DNS_PROTOCOL_MDNS);
261f3673 294 dns_packet_set_flags(p, true, true);
80a62095
DM
295 }
296
519ef046 297 r = dns_scope_emit_one(s, fd, p);
80a62095
DM
298 if (r < 0)
299 return r;
300
301 p = p->more;
519ef046 302 } while (p);
80a62095
DM
303
304 return 0;
305}
306
519ef046
LP
307static int dns_scope_socket(
308 DnsScope *s,
309 int type,
310 int family,
311 const union in_addr_union *address,
312 DnsServer *server,
91ccab1e
IT
313 uint16_t port,
314 union sockaddr_union *ret_socket_address) {
519ef046 315
ad867662 316 _cleanup_close_ int fd = -1;
91ccab1e 317 union sockaddr_union sa;
ad867662 318 socklen_t salen;
623a4c97 319 static const int one = 1;
c10d6bdb 320 int r, ifindex;
ad867662
LP
321
322 assert(s);
be808ea0 323
519ef046
LP
324 if (server) {
325 assert(family == AF_UNSPEC);
326 assert(!address);
be808ea0 327
2817157b
LP
328 ifindex = dns_server_ifindex(server);
329
519ef046
LP
330 sa.sa.sa_family = server->family;
331 if (server->family == AF_INET) {
623a4c97 332 sa.in.sin_port = htobe16(port);
519ef046 333 sa.in.sin_addr = server->address.in;
623a4c97 334 salen = sizeof(sa.in);
519ef046 335 } else if (server->family == AF_INET6) {
623a4c97 336 sa.in6.sin6_port = htobe16(port);
519ef046 337 sa.in6.sin6_addr = server->address.in6;
2817157b 338 sa.in6.sin6_scope_id = ifindex;
623a4c97
LP
339 salen = sizeof(sa.in6);
340 } else
341 return -EAFNOSUPPORT;
342 } else {
519ef046
LP
343 assert(family != AF_UNSPEC);
344 assert(address);
345
623a4c97 346 sa.sa.sa_family = family;
2817157b 347 ifindex = s->link ? s->link->ifindex : 0;
623a4c97
LP
348
349 if (family == AF_INET) {
350 sa.in.sin_port = htobe16(port);
351 sa.in.sin_addr = address->in;
352 salen = sizeof(sa.in);
353 } else if (family == AF_INET6) {
354 sa.in6.sin6_port = htobe16(port);
355 sa.in6.sin6_addr = address->in6;
2817157b 356 sa.in6.sin6_scope_id = ifindex;
623a4c97
LP
357 salen = sizeof(sa.in6);
358 } else
359 return -EAFNOSUPPORT;
360 }
ad867662 361
0db64366 362 fd = socket(sa.sa.sa_family, type|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
ad867662
LP
363 if (fd < 0)
364 return -errno;
365
0db64366
TG
366 if (type == SOCK_STREAM) {
367 r = setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &one, sizeof(one));
368 if (r < 0)
369 return -errno;
370 }
623a4c97
LP
371
372 if (s->link) {
2817157b 373 be32_t ifindex_be = htobe32(ifindex);
623a4c97
LP
374
375 if (sa.sa.sa_family == AF_INET) {
2817157b 376 r = setsockopt(fd, IPPROTO_IP, IP_UNICAST_IF, &ifindex_be, sizeof(ifindex_be));
623a4c97
LP
377 if (r < 0)
378 return -errno;
379 } else if (sa.sa.sa_family == AF_INET6) {
2817157b 380 r = setsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_IF, &ifindex_be, sizeof(ifindex_be));
623a4c97
LP
381 if (r < 0)
382 return -errno;
383 }
384 }
385
386 if (s->protocol == DNS_PROTOCOL_LLMNR) {
bf3f1271 387 /* RFC 4795, section 2.5 requires the TTL to be set to 1 */
623a4c97
LP
388
389 if (sa.sa.sa_family == AF_INET) {
390 r = setsockopt(fd, IPPROTO_IP, IP_TTL, &one, sizeof(one));
391 if (r < 0)
392 return -errno;
393 } else if (sa.sa.sa_family == AF_INET6) {
394 r = setsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &one, sizeof(one));
395 if (r < 0)
396 return -errno;
397 }
398 }
ad867662 399
91ccab1e
IT
400 if (ret_socket_address)
401 *ret_socket_address = sa;
402 else {
403 r = connect(fd, &sa.sa, salen);
404 if (r < 0 && errno != EINPROGRESS)
405 return -errno;
406 }
ad867662 407
c10d6bdb 408 return TAKE_FD(fd);
ad867662
LP
409}
410
519ef046 411int dns_scope_socket_udp(DnsScope *s, DnsServer *server, uint16_t port) {
91ccab1e 412 return dns_scope_socket(s, SOCK_DGRAM, AF_UNSPEC, NULL, server, port, NULL);
0db64366
TG
413}
414
91ccab1e
IT
415int dns_scope_socket_tcp(DnsScope *s, int family, const union in_addr_union *address, DnsServer *server, uint16_t port, union sockaddr_union *ret_socket_address) {
416 /* If ret_socket_address is not NULL, the caller is responisble
417 * for calling connect() or sendmsg(). This is required by TCP
418 * Fast Open, to be able to send the initial SYN packet along
419 * with the first data packet. */
420 return dns_scope_socket(s, SOCK_STREAM, family, address, server, port, ret_socket_address);
0db64366
TG
421}
422
51323288 423DnsScopeMatch dns_scope_good_domain(DnsScope *s, int ifindex, uint64_t flags, const char *domain) {
a51c1048 424 DnsSearchDomain *d;
74b2466e
LP
425
426 assert(s);
427 assert(domain);
428
28b9b764
LP
429 /* Checks if the specified domain is something to look up on
430 * this scope. Note that this accepts non-qualified hostnames,
431 * i.e. those without any search path prefixed yet. */
432
51323288
LP
433 if (ifindex != 0 && (!s->link || s->link->ifindex != ifindex))
434 return DNS_SCOPE_NO;
435
931851e8 436 if ((SD_RESOLVED_FLAGS_MAKE(s->protocol, s->family, 0) & flags) == 0)
51323288
LP
437 return DNS_SCOPE_NO;
438
78c6a153
LP
439 /* Never resolve any loopback hostname or IP address via DNS,
440 * LLMNR or mDNS. Instead, always rely on synthesized RRs for
441 * these. */
442 if (is_localhost(domain) ||
443 dns_name_endswith(domain, "127.in-addr.arpa") > 0 ||
9436e8ca
LP
444 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)
445 return DNS_SCOPE_NO;
446
c9ad0edb
LP
447 /* Never respond to some of the domains listed in RFC6303 */
448 if (dns_name_endswith(domain, "0.in-addr.arpa") > 0 ||
449 dns_name_equal(domain, "255.255.255.255.in-addr.arpa") > 0 ||
450 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)
451 return DNS_SCOPE_NO;
452
7bcffc2e
LP
453 /* Never respond to some of the domains listed in RFC6761 */
454 if (dns_name_endswith(domain, "invalid") > 0)
455 return DNS_SCOPE_NO;
456
106784eb 457 switch (s->protocol) {
801ad6a6 458
613dca46
LP
459 case DNS_PROTOCOL_DNS: {
460 DnsServer *dns_server;
461
462 /* Never route things to scopes that lack DNS servers */
463 dns_server = dns_scope_get_dns_server(s);
464 if (!dns_server)
465 return DNS_SCOPE_NO;
466
467 /* Always honour search domains for routing queries, except if this scope lacks DNS servers. Note that
468 * we return DNS_SCOPE_YES here, rather than just DNS_SCOPE_MAYBE, which means other wildcard scopes
469 * won't be considered anymore. */
470 LIST_FOREACH(domains, d, dns_scope_get_search_domains(s))
471 if (dns_name_endswith(domain, d->name) > 0)
472 return DNS_SCOPE_YES;
473
474 /* If the DNS server has route-only domains, don't send other requests to it. This would be a privacy
475 * violation, will most probably fail anyway, and adds unnecessary load. */
476 if (dns_server_limited_domains(dns_server))
477 return DNS_SCOPE_NO;
801ad6a6 478
28b9b764
LP
479 /* Exclude link-local IP ranges */
480 if (dns_name_endswith(domain, "254.169.in-addr.arpa") == 0 &&
c9ad0edb
LP
481 dns_name_endswith(domain, "8.e.f.ip6.arpa") == 0 &&
482 dns_name_endswith(domain, "9.e.f.ip6.arpa") == 0 &&
483 dns_name_endswith(domain, "a.e.f.ip6.arpa") == 0 &&
b43d96b0
DM
484 dns_name_endswith(domain, "b.e.f.ip6.arpa") == 0 &&
485 /* If networks use .local in their private setups, they are supposed to also add .local to their search
486 * domains, which we already checked above. Otherwise, we consider .local specific to mDNS and won't
487 * send such queries ordinary DNS servers. */
488 dns_name_endswith(domain, "local") == 0)
faa133f3 489 return DNS_SCOPE_MAYBE;
1716f6dc 490
faa133f3 491 return DNS_SCOPE_NO;
613dca46 492 }
1716f6dc 493
106784eb 494 case DNS_PROTOCOL_MDNS:
78c6a153
LP
495 if ((s->family == AF_INET && dns_name_endswith(domain, "in-addr.arpa") > 0) ||
496 (s->family == AF_INET6 && dns_name_endswith(domain, "ip6.arpa") > 0) ||
497 (dns_name_endswith(domain, "local") > 0 && /* only resolve names ending in .local via mDNS */
498 dns_name_equal(domain, "local") == 0 && /* but not the single-label "local" name itself */
499 manager_is_own_hostname(s->manager, domain) <= 0)) /* never resolve the local hostname via mDNS */
d8b7e75f 500 return DNS_SCOPE_MAYBE;
74b2466e
LP
501
502 return DNS_SCOPE_NO;
74b2466e 503
106784eb 504 case DNS_PROTOCOL_LLMNR:
78c6a153
LP
505 if ((s->family == AF_INET && dns_name_endswith(domain, "in-addr.arpa") > 0) ||
506 (s->family == AF_INET6 && dns_name_endswith(domain, "ip6.arpa") > 0) ||
dc477e73 507 (dns_name_is_single_label(domain) && /* only resolve single label names via LLMNR */
78c6a153
LP
508 !is_gateway_hostname(domain) && /* don't resolve "gateway" with LLMNR, let nss-myhostname handle this */
509 manager_is_own_hostname(s->manager, domain) <= 0)) /* never resolve the local hostname via LLMNR */
1716f6dc 510 return DNS_SCOPE_MAYBE;
74b2466e 511
1716f6dc 512 return DNS_SCOPE_NO;
74b2466e 513
106784eb
DM
514 default:
515 assert_not_reached("Unknown scope protocol");
516 }
1716f6dc
LP
517}
518
011696f7
LP
519bool dns_scope_good_key(DnsScope *s, const DnsResourceKey *key) {
520 int key_family;
521
1716f6dc
LP
522 assert(s);
523 assert(key);
524
28b9b764
LP
525 /* Check if it makes sense to resolve the specified key on
526 * this scope. Note that this call assumes as fully qualified
527 * name, i.e. the search suffixes already appended. */
528
011696f7
LP
529 if (key->class != DNS_CLASS_IN)
530 return false;
531
28b9b764
LP
532 if (s->protocol == DNS_PROTOCOL_DNS) {
533
e5abebab 534 /* On classic DNS, looking up non-address RRs is always
28b9b764
LP
535 * fine. (Specifically, we want to permit looking up
536 * DNSKEY and DS records on the root and top-level
537 * domains.) */
538 if (!dns_resource_key_is_address(key))
539 return true;
540
541 /* However, we refuse to look up A and AAAA RRs on the
542 * root and single-label domains, under the assumption
543 * that those should be resolved via LLMNR or search
544 * path only, and should not be leaked onto the
545 * internet. */
1c02e7ba
ZJS
546 return !(dns_name_is_single_label(dns_resource_key_name(key)) ||
547 dns_name_is_root(dns_resource_key_name(key)));
28b9b764 548 }
1716f6dc
LP
549
550 /* On mDNS and LLMNR, send A and AAAA queries only on the
551 * respective scopes */
552
011696f7
LP
553 key_family = dns_type_to_af(key->type);
554 if (key_family < 0)
555 return true;
1716f6dc 556
011696f7 557 return key_family == s->family;
1716f6dc
LP
558}
559
0db4c90a 560static int dns_scope_multicast_membership(DnsScope *s, bool b, struct in_addr in, struct in6_addr in6) {
1716f6dc
LP
561 int fd;
562
5ba73e9b 563 assert(s);
5ba73e9b
LP
564 assert(s->link);
565
1716f6dc
LP
566 if (s->family == AF_INET) {
567 struct ip_mreqn mreqn = {
0db4c90a 568 .imr_multiaddr = in,
1716f6dc
LP
569 .imr_ifindex = s->link->ifindex,
570 };
571
d37baf40
DR
572 if (s->protocol == DNS_PROTOCOL_LLMNR)
573 fd = manager_llmnr_ipv4_udp_fd(s->manager);
574 else
575 fd = manager_mdns_ipv4_fd(s->manager);
576
1716f6dc
LP
577 if (fd < 0)
578 return fd;
579
7b4c2ee7
LP
580 /* Always first try to drop membership before we add
581 * one. This is necessary on some devices, such as
582 * veth. */
583 if (b)
dc751688 584 (void) setsockopt(fd, IPPROTO_IP, IP_DROP_MEMBERSHIP, &mreqn, sizeof(mreqn));
7b4c2ee7 585
1716f6dc
LP
586 if (setsockopt(fd, IPPROTO_IP, b ? IP_ADD_MEMBERSHIP : IP_DROP_MEMBERSHIP, &mreqn, sizeof(mreqn)) < 0)
587 return -errno;
588
589 } else if (s->family == AF_INET6) {
590 struct ipv6_mreq mreq = {
0db4c90a 591 .ipv6mr_multiaddr = in6,
1716f6dc
LP
592 .ipv6mr_interface = s->link->ifindex,
593 };
594
d37baf40
DR
595 if (s->protocol == DNS_PROTOCOL_LLMNR)
596 fd = manager_llmnr_ipv6_udp_fd(s->manager);
597 else
598 fd = manager_mdns_ipv6_fd(s->manager);
599
1716f6dc
LP
600 if (fd < 0)
601 return fd;
602
7b4c2ee7 603 if (b)
dc751688 604 (void) setsockopt(fd, IPPROTO_IPV6, IPV6_DROP_MEMBERSHIP, &mreq, sizeof(mreq));
7b4c2ee7 605
1716f6dc
LP
606 if (setsockopt(fd, IPPROTO_IPV6, b ? IPV6_ADD_MEMBERSHIP : IPV6_DROP_MEMBERSHIP, &mreq, sizeof(mreq)) < 0)
607 return -errno;
608 } else
609 return -EAFNOSUPPORT;
610
611 return 0;
74b2466e 612}
623a4c97 613
0db4c90a 614int dns_scope_llmnr_membership(DnsScope *s, bool b) {
f471bc11 615 assert(s);
0db4c90a
DM
616
617 if (s->protocol != DNS_PROTOCOL_LLMNR)
618 return 0;
619
620 return dns_scope_multicast_membership(s, b, LLMNR_MULTICAST_IPV4_ADDRESS, LLMNR_MULTICAST_IPV6_ADDRESS);
621}
622
623int dns_scope_mdns_membership(DnsScope *s, bool b) {
f471bc11 624 assert(s);
0db4c90a
DM
625
626 if (s->protocol != DNS_PROTOCOL_MDNS)
627 return 0;
628
629 return dns_scope_multicast_membership(s, b, MDNS_MULTICAST_IPV4_ADDRESS, MDNS_MULTICAST_IPV6_ADDRESS);
630}
631
3b991089 632int dns_scope_make_reply_packet(
ec2c5e43
LP
633 DnsScope *s,
634 uint16_t id,
635 int rcode,
636 DnsQuestion *q,
637 DnsAnswer *answer,
638 DnsAnswer *soa,
639 bool tentative,
640 DnsPacket **ret) {
641
623a4c97 642 _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
623a4c97
LP
643 int r;
644
645 assert(s);
a4076574 646 assert(ret);
623a4c97 647
501e8eb0
LP
648 if (dns_question_isempty(q) &&
649 dns_answer_isempty(answer) &&
650 dns_answer_isempty(soa))
623a4c97
LP
651 return -EINVAL;
652
51027656 653 r = dns_packet_new(&p, s->protocol, 0, DNS_PACKET_SIZE_MAX);
623a4c97
LP
654 if (r < 0)
655 return r;
656
657 DNS_PACKET_HEADER(p)->id = id;
ea917db9
LP
658 DNS_PACKET_HEADER(p)->flags = htobe16(DNS_PACKET_MAKE_FLAGS(
659 1 /* qr */,
660 0 /* opcode */,
661 0 /* c */,
662 0 /* tc */,
ec2c5e43 663 tentative,
ea917db9
LP
664 0 /* (ra) */,
665 0 /* (ad) */,
666 0 /* (cd) */,
667 rcode));
623a4c97 668
f471bc11
LP
669 r = dns_packet_append_question(p, q);
670 if (r < 0)
671 return r;
672 DNS_PACKET_HEADER(p)->qdcount = htobe16(dns_question_size(q));
8bf52d3d 673
f471bc11
LP
674 r = dns_packet_append_answer(p, answer);
675 if (r < 0)
676 return r;
677 DNS_PACKET_HEADER(p)->ancount = htobe16(dns_answer_size(answer));
8bf52d3d 678
f471bc11
LP
679 r = dns_packet_append_answer(p, soa);
680 if (r < 0)
681 return r;
682 DNS_PACKET_HEADER(p)->arcount = htobe16(dns_answer_size(soa));
623a4c97 683
1cc6c93a 684 *ret = TAKE_PTR(p);
623a4c97
LP
685
686 return 0;
687}
688
a4076574 689static void dns_scope_verify_conflicts(DnsScope *s, DnsPacket *p) {
2a3900d7
LP
690 DnsResourceRecord *rr;
691 DnsResourceKey *key;
a4076574
LP
692
693 assert(s);
694 assert(p);
695
2a3900d7
LP
696 DNS_QUESTION_FOREACH(key, p->question)
697 dns_zone_verify_conflicts(&s->zone, key);
698
699 DNS_ANSWER_FOREACH(rr, p->answer)
700 dns_zone_verify_conflicts(&s->zone, rr->key);
a4076574
LP
701}
702
623a4c97 703void dns_scope_process_query(DnsScope *s, DnsStream *stream, DnsPacket *p) {
8bf52d3d 704 _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL, *soa = NULL;
b30bf55d 705 _cleanup_(dns_packet_unrefp) DnsPacket *reply = NULL;
5032b16d 706 DnsResourceKey *key = NULL;
ec2c5e43 707 bool tentative = false;
b30bf55d 708 int r;
623a4c97
LP
709
710 assert(s);
711 assert(p);
712
713 if (p->protocol != DNS_PROTOCOL_LLMNR)
714 return;
715
2442b93d
LP
716 if (p->ipproto == IPPROTO_UDP) {
717 /* Don't accept UDP queries directed to anything but
718 * the LLMNR multicast addresses. See RFC 4795,
d076c6f9 719 * section 2.5. */
2442b93d
LP
720
721 if (p->family == AF_INET && !in_addr_equal(AF_INET, &p->destination, (union in_addr_union*) &LLMNR_MULTICAST_IPV4_ADDRESS))
722 return;
723
724 if (p->family == AF_INET6 && !in_addr_equal(AF_INET6, &p->destination, (union in_addr_union*) &LLMNR_MULTICAST_IPV6_ADDRESS))
725 return;
726 }
727
623a4c97
LP
728 r = dns_packet_extract(p);
729 if (r < 0) {
b30bf55d 730 log_debug_errno(r, "Failed to extract resource records from incoming packet: %m");
623a4c97
LP
731 return;
732 }
733
8b757a38 734 if (DNS_PACKET_LLMNR_C(p)) {
a4076574
LP
735 /* Somebody notified us about a possible conflict */
736 dns_scope_verify_conflicts(s, p);
ea917db9
LP
737 return;
738 }
739
501e8eb0 740 assert(dns_question_size(p->question) == 1);
5032b16d
LP
741 key = p->question->keys[0];
742
97ebebbc 743 r = dns_zone_lookup(&s->zone, key, 0, &answer, &soa, &tentative);
623a4c97 744 if (r < 0) {
da927ba9 745 log_debug_errno(r, "Failed to lookup key: %m");
623a4c97
LP
746 return;
747 }
748 if (r == 0)
749 return;
750
fcf57f9c
LP
751 if (answer)
752 dns_answer_order_by_scope(answer, in_addr_is_link_local(p->family, &p->sender) > 0);
af93291c 753
ec2c5e43 754 r = dns_scope_make_reply_packet(s, DNS_PACKET_ID(p), DNS_RCODE_SUCCESS, p->question, answer, soa, tentative, &reply);
623a4c97 755 if (r < 0) {
da927ba9 756 log_debug_errno(r, "Failed to build reply packet: %m");
623a4c97
LP
757 return;
758 }
759
b30bf55d 760 if (stream) {
623a4c97 761 r = dns_stream_write_packet(stream, reply);
b30bf55d
LP
762 if (r < 0) {
763 log_debug_errno(r, "Failed to enqueue reply packet: %m");
764 return;
765 }
766
767 /* Let's take an extra reference on this stream, so that it stays around after returning. The reference
768 * will be dangling until the stream is disconnected, and the default completion handler of the stream
769 * will then unref the stream and destroy it */
770 if (DNS_STREAM_QUEUED(stream))
771 dns_stream_ref(stream);
772 } else {
773 int fd;
774
7994ac1d 775 if (!ratelimit_below(&s->ratelimit))
aea2429d
LP
776 return;
777
623a4c97
LP
778 if (p->family == AF_INET)
779 fd = manager_llmnr_ipv4_udp_fd(s->manager);
780 else if (p->family == AF_INET6)
781 fd = manager_llmnr_ipv6_udp_fd(s->manager);
782 else {
783 log_debug("Unknown protocol");
784 return;
785 }
786 if (fd < 0) {
da927ba9 787 log_debug_errno(fd, "Failed to get reply socket: %m");
623a4c97
LP
788 return;
789 }
790
6e068472
LP
791 /* Note that we always immediately reply to all LLMNR
792 * requests, and do not wait any time, since we
793 * verified uniqueness for all records. Also see RFC
794 * 4795, Section 2.7 */
795
b30bf55d
LP
796 r = manager_send(s->manager, fd, p->ifindex, p->family, &p->sender, p->sender_port, NULL, reply);
797 if (r < 0) {
798 log_debug_errno(r, "Failed to send reply packet: %m");
799 return;
800 }
623a4c97
LP
801 }
802}
ec2c5e43 803
f52e61da 804DnsTransaction *dns_scope_find_transaction(DnsScope *scope, DnsResourceKey *key, bool cache_ok) {
ec2c5e43
LP
805 DnsTransaction *t;
806
807 assert(scope);
f52e61da 808 assert(key);
ec2c5e43 809
da0c630e
LP
810 /* Try to find an ongoing transaction that is a equal to the
811 * specified question */
f9ebb22a 812 t = hashmap_get(scope->transactions_by_key, key);
4a46ed1b
LP
813 if (!t)
814 return NULL;
dc4d47e2 815
da0c630e
LP
816 /* Refuse reusing transactions that completed based on cached
817 * data instead of a real packet, if that's requested. */
818 if (!cache_ok &&
3bbdc31d 819 IN_SET(t->state, DNS_TRANSACTION_SUCCESS, DNS_TRANSACTION_RCODE_FAILURE) &&
c3bc53e6 820 t->answer_source != DNS_TRANSACTION_NETWORK)
da0c630e 821 return NULL;
ec2c5e43 822
da0c630e 823 return t;
ec2c5e43 824}
a4076574
LP
825
826static int dns_scope_make_conflict_packet(
827 DnsScope *s,
828 DnsResourceRecord *rr,
829 DnsPacket **ret) {
830
831 _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
832 int r;
833
834 assert(s);
835 assert(rr);
836 assert(ret);
837
51027656 838 r = dns_packet_new(&p, s->protocol, 0, DNS_PACKET_SIZE_MAX);
a4076574
LP
839 if (r < 0)
840 return r;
841
842 DNS_PACKET_HEADER(p)->flags = htobe16(DNS_PACKET_MAKE_FLAGS(
843 0 /* qr */,
844 0 /* opcode */,
845 1 /* conflict */,
846 0 /* tc */,
847 0 /* t */,
848 0 /* (ra) */,
849 0 /* (ad) */,
850 0 /* (cd) */,
851 0));
fe2dfc8b
DM
852
853 /* For mDNS, the transaction ID should always be 0 */
854 if (s->protocol != DNS_PROTOCOL_MDNS)
855 random_bytes(&DNS_PACKET_HEADER(p)->id, sizeof(uint16_t));
856
a4076574
LP
857 DNS_PACKET_HEADER(p)->qdcount = htobe16(1);
858 DNS_PACKET_HEADER(p)->arcount = htobe16(1);
859
58ab31d5 860 r = dns_packet_append_key(p, rr->key, 0, NULL);
a4076574
LP
861 if (r < 0)
862 return r;
863
58ab31d5 864 r = dns_packet_append_rr(p, rr, 0, NULL, NULL);
a4076574
LP
865 if (r < 0)
866 return r;
867
1cc6c93a 868 *ret = TAKE_PTR(p);
a4076574
LP
869
870 return 0;
871}
872
873static int on_conflict_dispatch(sd_event_source *es, usec_t usec, void *userdata) {
874 DnsScope *scope = userdata;
875 int r;
876
877 assert(es);
878 assert(scope);
879
880 scope->conflict_event_source = sd_event_source_unref(scope->conflict_event_source);
881
882 for (;;) {
432d108c 883 _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
a4076574
LP
884 _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
885 _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
886
432d108c
DR
887 key = ordered_hashmap_first_key(scope->conflict_queue);
888 if (!key)
a4076574
LP
889 break;
890
432d108c
DR
891 rr = ordered_hashmap_remove(scope->conflict_queue, key);
892 assert(rr);
893
a4076574
LP
894 r = dns_scope_make_conflict_packet(scope, rr, &p);
895 if (r < 0) {
da927ba9 896 log_error_errno(r, "Failed to make conflict packet: %m");
a4076574
LP
897 return 0;
898 }
899
519ef046 900 r = dns_scope_emit_udp(scope, -1, p);
a4076574 901 if (r < 0)
da927ba9 902 log_debug_errno(r, "Failed to send conflict packet: %m");
a4076574
LP
903 }
904
905 return 0;
906}
907
908int dns_scope_notify_conflict(DnsScope *scope, DnsResourceRecord *rr) {
909 usec_t jitter;
910 int r;
911
912 assert(scope);
913 assert(rr);
914
915 /* We don't send these queries immediately. Instead, we queue
916 * them, and send them after some jitter delay. */
1e43061b 917 r = ordered_hashmap_ensure_allocated(&scope->conflict_queue, &dns_resource_key_hash_ops);
a4076574
LP
918 if (r < 0) {
919 log_oom();
920 return r;
921 }
922
923 /* We only place one RR per key in the conflict
924 * messages, not all of them. That should be enough to
925 * indicate where there might be a conflict */
1e43061b 926 r = ordered_hashmap_put(scope->conflict_queue, rr->key, rr);
4c701096 927 if (IN_SET(r, 0, -EEXIST))
a4076574 928 return 0;
f647962d
MS
929 if (r < 0)
930 return log_debug_errno(r, "Failed to queue conflicting RR: %m");
a4076574 931
432d108c 932 dns_resource_key_ref(rr->key);
a4076574
LP
933 dns_resource_record_ref(rr);
934
935 if (scope->conflict_event_source)
936 return 0;
937
938 random_bytes(&jitter, sizeof(jitter));
939 jitter %= LLMNR_JITTER_INTERVAL_USEC;
940
941 r = sd_event_add_time(scope->manager->event,
942 &scope->conflict_event_source,
943 clock_boottime_or_monotonic(),
944 now(clock_boottime_or_monotonic()) + jitter,
945 LLMNR_JITTER_INTERVAL_USEC,
946 on_conflict_dispatch, scope);
f647962d
MS
947 if (r < 0)
948 return log_debug_errno(r, "Failed to add conflict dispatch event: %m");
a4076574 949
aa4a9deb
LP
950 (void) sd_event_source_set_description(scope->conflict_event_source, "scope-conflict");
951
a4076574
LP
952 return 0;
953}
954
955void dns_scope_check_conflicts(DnsScope *scope, DnsPacket *p) {
c1227a18 956 DnsResourceRecord *rr;
a4076574
LP
957 int r;
958
959 assert(scope);
960 assert(p);
961
53fda2bb 962 if (!IN_SET(p->protocol, DNS_PROTOCOL_LLMNR, DNS_PROTOCOL_MDNS))
a4076574
LP
963 return;
964
965 if (DNS_PACKET_RRCOUNT(p) <= 0)
966 return;
967
53fda2bb
DR
968 if (p->protocol == DNS_PROTOCOL_LLMNR) {
969 if (DNS_PACKET_LLMNR_C(p) != 0)
970 return;
a4076574 971
53fda2bb
DR
972 if (DNS_PACKET_LLMNR_T(p) != 0)
973 return;
974 }
a4076574
LP
975
976 if (manager_our_packet(scope->manager, p))
977 return;
978
979 r = dns_packet_extract(p);
980 if (r < 0) {
da927ba9 981 log_debug_errno(r, "Failed to extract packet: %m");
a4076574
LP
982 return;
983 }
984
985 log_debug("Checking for conflicts...");
986
c1227a18 987 DNS_ANSWER_FOREACH(rr, p->answer) {
cfcc8dcc 988 /* No conflict if it is DNS-SD RR used for service enumeration. */
c1227a18 989 if (dns_resource_key_is_dnssd_ptr(rr->key))
cfcc8dcc
DR
990 continue;
991
a4076574
LP
992 /* Check for conflicts against the local zone. If we
993 * found one, we won't check any further */
c1227a18 994 r = dns_zone_check_conflicts(&scope->zone, rr);
a4076574
LP
995 if (r != 0)
996 continue;
997
998 /* Check for conflicts against the local cache. If so,
999 * send out an advisory query, to inform everybody */
c1227a18 1000 r = dns_cache_check_conflicts(&scope->cache, rr, p->family, &p->sender);
a4076574
LP
1001 if (r <= 0)
1002 continue;
1003
c1227a18 1004 dns_scope_notify_conflict(scope, rr);
a4076574
LP
1005 }
1006}
4d506d6b
LP
1007
1008void dns_scope_dump(DnsScope *s, FILE *f) {
1009 assert(s);
1010
1011 if (!f)
1012 f = stdout;
1013
1014 fputs("[Scope protocol=", f);
1015 fputs(dns_protocol_to_string(s->protocol), f);
1016
1017 if (s->link) {
1018 fputs(" interface=", f);
1019 fputs(s->link->name, f);
1020 }
1021
1022 if (s->family != AF_UNSPEC) {
1023 fputs(" family=", f);
1024 fputs(af_to_name(s->family), f);
1025 }
1026
1027 fputs("]\n", f);
1028
1029 if (!dns_zone_is_empty(&s->zone)) {
1030 fputs("ZONE:\n", f);
1031 dns_zone_dump(&s->zone, f);
1032 }
1033
1034 if (!dns_cache_is_empty(&s->cache)) {
1035 fputs("CACHE:\n", f);
1036 dns_cache_dump(&s->cache, f);
1037 }
1038}
a51c1048
LP
1039
1040DnsSearchDomain *dns_scope_get_search_domains(DnsScope *s) {
801ad6a6
LP
1041 assert(s);
1042
a51c1048
LP
1043 if (s->protocol != DNS_PROTOCOL_DNS)
1044 return NULL;
1045
1046 if (s->link)
1047 return s->link->search_domains;
1048
28b9b764 1049 return s->manager->search_domains;
801ad6a6
LP
1050}
1051
dc477e73 1052bool dns_scope_name_needs_search_domain(DnsScope *s, const char *name) {
801ad6a6
LP
1053 assert(s);
1054
1055 if (s->protocol != DNS_PROTOCOL_DNS)
dc477e73 1056 return false;
801ad6a6 1057
dc477e73 1058 return dns_name_is_single_label(name);
801ad6a6 1059}
edbcc1fd
LP
1060
1061bool dns_scope_network_good(DnsScope *s) {
edbcc1fd
LP
1062 /* Checks whether the network is in good state for lookups on this scope. For mDNS/LLMNR/Classic DNS scopes
1063 * bound to links this is easy, as they don't even exist if the link isn't in a suitable state. For the global
1064 * DNS scope we check whether there are any links that are up and have an address. */
1065
1066 if (s->link)
1067 return true;
1068
011696f7 1069 return manager_routable(s->manager, AF_UNSPEC);
edbcc1fd 1070}
97ebebbc
LP
1071
1072int dns_scope_ifindex(DnsScope *s) {
1073 assert(s);
1074
1075 if (s->link)
1076 return s->link->ifindex;
1077
1078 return 0;
1079}
53fda2bb
DR
1080
1081static int on_announcement_timeout(sd_event_source *s, usec_t usec, void *userdata) {
1082 DnsScope *scope = userdata;
1083
1084 assert(s);
1085
1086 scope->announce_event_source = sd_event_source_unref(scope->announce_event_source);
1087
1a63fc54 1088 (void) dns_scope_announce(scope, false);
53fda2bb
DR
1089 return 0;
1090}
1091
1a63fc54 1092int dns_scope_announce(DnsScope *scope, bool goodbye) {
53fda2bb
DR
1093 _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL;
1094 _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
a2bf8a19
DR
1095 _cleanup_set_free_ Set *types = NULL;
1096 DnsTransaction *t;
400f54fb 1097 DnsZoneItem *z, *i;
a2bf8a19
DR
1098 unsigned size = 0;
1099 Iterator iterator;
1100 char *service_type;
53fda2bb
DR
1101 int r;
1102
1103 if (!scope)
1a63fc54 1104 return 0;
53fda2bb
DR
1105
1106 if (scope->protocol != DNS_PROTOCOL_MDNS)
1a63fc54 1107 return 0;
53fda2bb 1108
a2bf8a19
DR
1109 /* Check if we're done with probing. */
1110 LIST_FOREACH(transactions_by_scope, t, scope->transactions)
1111 if (DNS_TRANSACTION_IS_LIVE(t->state))
1112 return 0;
1113
e7c1b0e4
DR
1114 /* Check if there're services pending conflict resolution. */
1115 if (manager_next_dnssd_names(scope->manager))
1116 return 0; /* we reach this point only if changing hostname didn't help */
1117
a2bf8a19
DR
1118 /* Calculate answer's size. */
1119 HASHMAP_FOREACH(z, scope->zone.by_key, iterator) {
1120 if (z->state != DNS_ZONE_ITEM_ESTABLISHED)
1121 continue;
1122
1123 if (z->rr->key->type == DNS_TYPE_PTR &&
1124 !dns_zone_contains_name(&scope->zone, z->rr->ptr.name)) {
1125 char key_str[DNS_RESOURCE_KEY_STRING_MAX];
1126
1127 log_debug("Skip PTR RR <%s> since its counterparts seem to be withdrawn", dns_resource_key_to_string(z->rr->key, key_str, sizeof key_str));
1128 z->state = DNS_ZONE_ITEM_WITHDRAWN;
1129 continue;
1130 }
1131
1132 /* Collect service types for _services._dns-sd._udp.local RRs in a set */
1133 if (!scope->announced &&
1134 dns_resource_key_is_dnssd_ptr(z->rr->key)) {
1135 if (!set_contains(types, dns_resource_key_name(z->rr->key))) {
1136 r = set_ensure_allocated(&types, &dns_name_hash_ops);
1137 if (r < 0)
1138 return log_debug_errno(r, "Failed to allocate set: %m");
1139
1140 r = set_put(types, dns_resource_key_name(z->rr->key));
1141 if (r < 0)
1142 return log_debug_errno(r, "Failed to add item to set: %m");
1143 }
1144 }
1145
400f54fb
DR
1146 LIST_FOREACH(by_key, i, z)
1147 size++;
a2bf8a19
DR
1148 }
1149
1150 answer = dns_answer_new(size + set_size(types));
1a63fc54
LP
1151 if (!answer)
1152 return log_oom();
1153
a2bf8a19 1154 /* Second iteration, actually add RRs to the answer. */
400f54fb
DR
1155 HASHMAP_FOREACH(z, scope->zone.by_key, iterator)
1156 LIST_FOREACH (by_key, i, z) {
1157 DnsAnswerFlags flags;
a2bf8a19 1158
400f54fb
DR
1159 if (i->state != DNS_ZONE_ITEM_ESTABLISHED)
1160 continue;
a2bf8a19 1161
400f54fb
DR
1162 if (dns_resource_key_is_dnssd_ptr(i->rr->key))
1163 flags = goodbye ? DNS_ANSWER_GOODBYE : 0;
1164 else
1165 flags = goodbye ? (DNS_ANSWER_GOODBYE|DNS_ANSWER_CACHE_FLUSH) : DNS_ANSWER_CACHE_FLUSH;
a2bf8a19 1166
400f54fb
DR
1167 r = dns_answer_add(answer, i->rr, 0 , flags);
1168 if (r < 0)
1169 return log_debug_errno(r, "Failed to add RR to announce: %m");
1170 }
a2bf8a19
DR
1171
1172 /* Since all the active services are in the zone make them discoverable now. */
1173 SET_FOREACH(service_type, types, iterator) {
1174 _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr;
1175
1176 rr = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_PTR,
1177 "_services._dns-sd._udp.local");
1178 rr->ptr.name = strdup(service_type);
1179 rr->ttl = MDNS_DEFAULT_TTL;
1180
1181 r = dns_zone_put(&scope->zone, scope, rr, false);
1a63fc54 1182 if (r < 0)
a2bf8a19 1183 log_warning_errno(r, "Failed to add DNS-SD PTR record to MDNS zone: %m");
1a63fc54 1184
a2bf8a19 1185 r = dns_answer_add(answer, rr, 0 , 0);
1a63fc54 1186 if (r < 0)
a2bf8a19 1187 return log_debug_errno(r, "Failed to add RR to announce: %m");
53fda2bb
DR
1188 }
1189
1190 if (dns_answer_isempty(answer))
1a63fc54 1191 return 0;
53fda2bb
DR
1192
1193 r = dns_scope_make_reply_packet(scope, 0, DNS_RCODE_SUCCESS, NULL, answer, NULL, false, &p);
1a63fc54
LP
1194 if (r < 0)
1195 return log_debug_errno(r, "Failed to build reply packet: %m");
1196
53fda2bb 1197 r = dns_scope_emit_udp(scope, -1, p);
1a63fc54
LP
1198 if (r < 0)
1199 return log_debug_errno(r, "Failed to send reply packet: %m");
53fda2bb
DR
1200
1201 /* In section 8.3 of RFC6762: "The Multicast DNS responder MUST send at least two unsolicited
1202 * responses, one second apart." */
1203 if (!scope->announced) {
1204 usec_t ts;
1205
1206 scope->announced = true;
1207
1208 assert_se(sd_event_now(scope->manager->event, clock_boottime_or_monotonic(), &ts) >= 0);
1209 ts += MDNS_ANNOUNCE_DELAY;
1210
1211 r = sd_event_add_time(
1212 scope->manager->event,
1213 &scope->announce_event_source,
1214 clock_boottime_or_monotonic(),
1215 ts,
1216 MDNS_JITTER_RANGE_USEC,
1217 on_announcement_timeout, scope);
1218 if (r < 0)
1a63fc54 1219 return log_debug_errno(r, "Failed to schedule second announcement: %m");
19fee3ef
LP
1220
1221 (void) sd_event_source_set_description(scope->announce_event_source, "mdns-announce");
53fda2bb 1222 }
1a63fc54
LP
1223
1224 return 0;
53fda2bb 1225}
6db6a464
DR
1226
1227int dns_scope_add_dnssd_services(DnsScope *scope) {
1228 Iterator i;
1229 DnssdService *service;
400f54fb 1230 DnssdTxtData *txt_data;
6db6a464
DR
1231 int r;
1232
1233 assert(scope);
1234
1235 if (hashmap_size(scope->manager->dnssd_services) == 0)
1236 return 0;
1237
1238 scope->announced = false;
1239
1240 HASHMAP_FOREACH(service, scope->manager->dnssd_services, i) {
c3036641
DR
1241 service->withdrawn = false;
1242
6db6a464
DR
1243 r = dns_zone_put(&scope->zone, scope, service->ptr_rr, false);
1244 if (r < 0)
1245 log_warning_errno(r, "Failed to add PTR record to MDNS zone: %m");
1246
1247 r = dns_zone_put(&scope->zone, scope, service->srv_rr, true);
1248 if (r < 0)
1249 log_warning_errno(r, "Failed to add SRV record to MDNS zone: %m");
1250
400f54fb
DR
1251 LIST_FOREACH(items, txt_data, service->txt_data_items) {
1252 r = dns_zone_put(&scope->zone, scope, txt_data->rr, true);
1253 if (r < 0)
1254 log_warning_errno(r, "Failed to add TXT record to MDNS zone: %m");
1255 }
6db6a464
DR
1256 }
1257
1258 return 0;
1259}
1260
1261int dns_scope_remove_dnssd_services(DnsScope *scope) {
1262 _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
1263 Iterator i;
1264 DnssdService *service;
400f54fb 1265 DnssdTxtData *txt_data;
6db6a464
DR
1266 int r;
1267
1268 assert(scope);
1269
1270 key = dns_resource_key_new(DNS_CLASS_IN, DNS_TYPE_PTR,
1271 "_services._dns-sd._udp.local");
1272 if (!key)
1273 return log_oom();
1274
1275 r = dns_zone_remove_rrs_by_key(&scope->zone, key);
1276 if (r < 0)
1277 return r;
1278
1279 HASHMAP_FOREACH(service, scope->manager->dnssd_services, i) {
1280 dns_zone_remove_rr(&scope->zone, service->ptr_rr);
1281 dns_zone_remove_rr(&scope->zone, service->srv_rr);
400f54fb
DR
1282 LIST_FOREACH(items, txt_data, service->txt_data_items)
1283 dns_zone_remove_rr(&scope->zone, txt_data->rr);
6db6a464
DR
1284 }
1285
1286 return 0;
1287}