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