]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/resolve/resolved-llmnr.c
Add SPDX license identifiers to source files under the LGPL
[thirdparty/systemd.git] / src / resolve / resolved-llmnr.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
2 /***
3 This file is part of systemd.
4
5 Copyright 2014 Tom Gundersen <teg@jklm.no>
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
21 #include <netinet/in.h>
22 #include <resolv.h>
23
24 #include "fd-util.h"
25 #include "resolved-llmnr.h"
26 #include "resolved-manager.h"
27
28 void manager_llmnr_stop(Manager *m) {
29 assert(m);
30
31 m->llmnr_ipv4_udp_event_source = sd_event_source_unref(m->llmnr_ipv4_udp_event_source);
32 m->llmnr_ipv4_udp_fd = safe_close(m->llmnr_ipv4_udp_fd);
33
34 m->llmnr_ipv6_udp_event_source = sd_event_source_unref(m->llmnr_ipv6_udp_event_source);
35 m->llmnr_ipv6_udp_fd = safe_close(m->llmnr_ipv6_udp_fd);
36
37 m->llmnr_ipv4_tcp_event_source = sd_event_source_unref(m->llmnr_ipv4_tcp_event_source);
38 m->llmnr_ipv4_tcp_fd = safe_close(m->llmnr_ipv4_tcp_fd);
39
40 m->llmnr_ipv6_tcp_event_source = sd_event_source_unref(m->llmnr_ipv6_tcp_event_source);
41 m->llmnr_ipv6_tcp_fd = safe_close(m->llmnr_ipv6_tcp_fd);
42 }
43
44 int manager_llmnr_start(Manager *m) {
45 int r;
46
47 assert(m);
48
49 if (m->llmnr_support == RESOLVE_SUPPORT_NO)
50 return 0;
51
52 r = manager_llmnr_ipv4_udp_fd(m);
53 if (r == -EADDRINUSE)
54 goto eaddrinuse;
55 if (r < 0)
56 return r;
57
58 r = manager_llmnr_ipv4_tcp_fd(m);
59 if (r == -EADDRINUSE)
60 goto eaddrinuse;
61 if (r < 0)
62 return r;
63
64 if (socket_ipv6_is_supported()) {
65 r = manager_llmnr_ipv6_udp_fd(m);
66 if (r == -EADDRINUSE)
67 goto eaddrinuse;
68 if (r < 0)
69 return r;
70
71 r = manager_llmnr_ipv6_tcp_fd(m);
72 if (r == -EADDRINUSE)
73 goto eaddrinuse;
74 if (r < 0)
75 return r;
76 }
77
78 return 0;
79
80 eaddrinuse:
81 log_warning("Another LLMNR responder prohibits binding the socket to the same port. Turning off LLMNR support.");
82 m->llmnr_support = RESOLVE_SUPPORT_NO;
83 manager_llmnr_stop(m);
84
85 return 0;
86 }
87
88 static int on_llmnr_packet(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
89 _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
90 DnsTransaction *t = NULL;
91 Manager *m = userdata;
92 DnsScope *scope;
93 int r;
94
95 assert(s);
96 assert(fd >= 0);
97 assert(m);
98
99 r = manager_recv(m, fd, DNS_PROTOCOL_LLMNR, &p);
100 if (r <= 0)
101 return r;
102
103 scope = manager_find_scope(m, p);
104 if (!scope)
105 log_warning("Got LLMNR UDP packet on unknown scope. Ignoring.");
106 else if (dns_packet_validate_reply(p) > 0) {
107 log_debug("Got LLMNR UDP reply packet for id %u", DNS_PACKET_ID(p));
108
109 dns_scope_check_conflicts(scope, p);
110
111 t = hashmap_get(m->dns_transactions, UINT_TO_PTR(DNS_PACKET_ID(p)));
112 if (t)
113 dns_transaction_process_reply(t, p);
114
115 } else if (dns_packet_validate_query(p) > 0) {
116 log_debug("Got LLMNR UDP query packet for id %u", DNS_PACKET_ID(p));
117
118 dns_scope_process_query(scope, NULL, p);
119 } else
120 log_debug("Invalid LLMNR UDP packet, ignoring.");
121
122 return 0;
123 }
124
125 int manager_llmnr_ipv4_udp_fd(Manager *m) {
126 union sockaddr_union sa = {
127 .in.sin_family = AF_INET,
128 .in.sin_port = htobe16(LLMNR_PORT),
129 };
130 static const int one = 1, pmtu = IP_PMTUDISC_DONT, ttl = 255;
131 int r;
132
133 assert(m);
134
135 if (m->llmnr_ipv4_udp_fd >= 0)
136 return m->llmnr_ipv4_udp_fd;
137
138 m->llmnr_ipv4_udp_fd = socket(AF_INET, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
139 if (m->llmnr_ipv4_udp_fd < 0)
140 return log_error_errno(errno, "LLMNR-IPv4(UDP): Failed to create socket: %m");
141
142 /* RFC 4795, section 2.5 recommends setting the TTL of UDP packets to 255. */
143 r = setsockopt(m->llmnr_ipv4_udp_fd, IPPROTO_IP, IP_TTL, &ttl, sizeof(ttl));
144 if (r < 0) {
145 r = log_error_errno(errno, "LLMNR-IPv4(UDP): Failed to set IP_TTL: %m");
146 goto fail;
147 }
148
149 r = setsockopt(m->llmnr_ipv4_udp_fd, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl));
150 if (r < 0) {
151 r = log_error_errno(errno, "LLMNR-IPv4(UDP): Failed to set IP_MULTICAST_TTL: %m");
152 goto fail;
153 }
154
155 r = setsockopt(m->llmnr_ipv4_udp_fd, IPPROTO_IP, IP_MULTICAST_LOOP, &one, sizeof(one));
156 if (r < 0) {
157 r = log_error_errno(errno, "LLMNR-IPv4(UDP): Failed to set IP_MULTICAST_LOOP: %m");
158 goto fail;
159 }
160
161 r = setsockopt(m->llmnr_ipv4_udp_fd, IPPROTO_IP, IP_PKTINFO, &one, sizeof(one));
162 if (r < 0) {
163 r = log_error_errno(errno, "LLMNR-IPv4(UDP): Failed to set IP_PKTINFO: %m");
164 goto fail;
165 }
166
167 r = setsockopt(m->llmnr_ipv4_udp_fd, IPPROTO_IP, IP_RECVTTL, &one, sizeof(one));
168 if (r < 0) {
169 r = log_error_errno(errno, "LLMNR-IPv4(UDP): Failed to set IP_RECVTTL: %m");
170 goto fail;
171 }
172
173 /* Disable Don't-Fragment bit in the IP header */
174 r = setsockopt(m->llmnr_ipv4_udp_fd, IPPROTO_IP, IP_MTU_DISCOVER, &pmtu, sizeof(pmtu));
175 if (r < 0) {
176 r = log_error_errno(errno, "LLMNR-IPv4(UDP): Failed to set IP_MTU_DISCOVER: %m");
177 goto fail;
178 }
179
180 /* first try to bind without SO_REUSEADDR to detect another LLMNR responder */
181 r = bind(m->llmnr_ipv4_udp_fd, &sa.sa, sizeof(sa.in));
182 if (r < 0) {
183 if (errno != EADDRINUSE) {
184 r = log_error_errno(errno, "LLMNR-IPv4(UDP): Failed to bind socket: %m");
185 goto fail;
186 }
187
188 log_warning("LLMNR-IPv4(UDP): There appears to be another LLMNR responder running, or previously systemd-resolved crashed with some outstanding transfers.");
189
190 /* try again with SO_REUSEADDR */
191 r = setsockopt(m->llmnr_ipv4_udp_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
192 if (r < 0) {
193 r = log_error_errno(errno, "LLMNR-IPv4(UDP): Failed to set SO_REUSEADDR: %m");
194 goto fail;
195 }
196
197 r = bind(m->llmnr_ipv4_udp_fd, &sa.sa, sizeof(sa.in));
198 if (r < 0) {
199 r = log_error_errno(errno, "LLMNR-IPv4(UDP): Failed to bind socket: %m");
200 goto fail;
201 }
202 } else {
203 /* enable SO_REUSEADDR for the case that the user really wants multiple LLMNR responders */
204 r = setsockopt(m->llmnr_ipv4_udp_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
205 if (r < 0) {
206 r = log_error_errno(errno, "LLMNR-IPv4(UDP): Failed to set SO_REUSEADDR: %m");
207 goto fail;
208 }
209 }
210
211 r = sd_event_add_io(m->event, &m->llmnr_ipv4_udp_event_source, m->llmnr_ipv4_udp_fd, EPOLLIN, on_llmnr_packet, m);
212 if (r < 0)
213 goto fail;
214
215 (void) sd_event_source_set_description(m->llmnr_ipv4_udp_event_source, "llmnr-ipv4-udp");
216
217 return m->llmnr_ipv4_udp_fd;
218
219 fail:
220 m->llmnr_ipv4_udp_fd = safe_close(m->llmnr_ipv4_udp_fd);
221 return r;
222 }
223
224 int manager_llmnr_ipv6_udp_fd(Manager *m) {
225 union sockaddr_union sa = {
226 .in6.sin6_family = AF_INET6,
227 .in6.sin6_port = htobe16(LLMNR_PORT),
228 };
229 static const int one = 1, ttl = 255;
230 int r;
231
232 assert(m);
233
234 if (m->llmnr_ipv6_udp_fd >= 0)
235 return m->llmnr_ipv6_udp_fd;
236
237 m->llmnr_ipv6_udp_fd = socket(AF_INET6, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
238 if (m->llmnr_ipv6_udp_fd < 0)
239 return log_error_errno(errno, "LLMNR-IPv6(UDP): Failed to create socket: %m");
240
241 r = setsockopt(m->llmnr_ipv6_udp_fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &ttl, sizeof(ttl));
242 if (r < 0) {
243 r = log_error_errno(errno, "LLMNR-IPv6(UDP): Failed to set IPV6_UNICAST_HOPS: %m");
244 goto fail;
245 }
246
247 /* RFC 4795, section 2.5 recommends setting the TTL of UDP packets to 255. */
248 r = setsockopt(m->llmnr_ipv6_udp_fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &ttl, sizeof(ttl));
249 if (r < 0) {
250 r = log_error_errno(errno, "LLMNR-IPv6(UDP): Failed to set IPV6_MULTICAST_HOPS: %m");
251 goto fail;
252 }
253
254 r = setsockopt(m->llmnr_ipv6_udp_fd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &one, sizeof(one));
255 if (r < 0) {
256 r = log_error_errno(errno, "LLMNR-IPv6(UDP): Failed to set IPV6_MULTICAST_LOOP: %m");
257 goto fail;
258 }
259
260 r = setsockopt(m->llmnr_ipv6_udp_fd, IPPROTO_IPV6, IPV6_V6ONLY, &one, sizeof(one));
261 if (r < 0) {
262 r = log_error_errno(errno, "LLMNR-IPv6(UDP): Failed to set IPV6_V6ONLY: %m");
263 goto fail;
264 }
265
266 r = setsockopt(m->llmnr_ipv6_udp_fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &one, sizeof(one));
267 if (r < 0) {
268 r = log_error_errno(errno, "LLMNR-IPv6(UDP): Failed to set IPV6_RECVPKTINFO: %m");
269 goto fail;
270 }
271
272 r = setsockopt(m->llmnr_ipv6_udp_fd, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &one, sizeof(one));
273 if (r < 0) {
274 r = log_error_errno(errno, "LLMNR-IPv6(UDP): Failed to set IPV6_RECVHOPLIMIT: %m");
275 goto fail;
276 }
277
278 /* first try to bind without SO_REUSEADDR to detect another LLMNR responder */
279 r = bind(m->llmnr_ipv6_udp_fd, &sa.sa, sizeof(sa.in6));
280 if (r < 0) {
281 if (errno != EADDRINUSE) {
282 r = log_error_errno(errno, "LLMNR-IPv6(UDP): Failed to bind socket: %m");
283 goto fail;
284 }
285
286 log_warning("LLMNR-IPv6(UDP): There appears to be another LLMNR responder running, or previously systemd-resolved crashed with some outstanding transfers.");
287
288 /* try again with SO_REUSEADDR */
289 r = setsockopt(m->llmnr_ipv6_udp_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
290 if (r < 0) {
291 r = log_error_errno(errno, "LLMNR-IPv6(UDP): Failed to set SO_REUSEADDR: %m");
292 goto fail;
293 }
294
295 r = bind(m->llmnr_ipv6_udp_fd, &sa.sa, sizeof(sa.in6));
296 if (r < 0) {
297 r = log_error_errno(errno, "LLMNR-IPv6(UDP): Failed to bind socket: %m");
298 goto fail;
299 }
300 } else {
301 /* enable SO_REUSEADDR for the case that the user really wants multiple LLMNR responders */
302 r = setsockopt(m->llmnr_ipv6_udp_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
303 if (r < 0) {
304 r = log_error_errno(errno, "LLMNR-IPv6(UDP): Failed to set SO_REUSEADDR: %m");
305 goto fail;
306 }
307 }
308
309 r = sd_event_add_io(m->event, &m->llmnr_ipv6_udp_event_source, m->llmnr_ipv6_udp_fd, EPOLLIN, on_llmnr_packet, m);
310 if (r < 0)
311 goto fail;
312
313 (void) sd_event_source_set_description(m->llmnr_ipv6_udp_event_source, "llmnr-ipv6-udp");
314
315 return m->llmnr_ipv6_udp_fd;
316
317 fail:
318 m->llmnr_ipv6_udp_fd = safe_close(m->llmnr_ipv6_udp_fd);
319 return r;
320 }
321
322 static int on_llmnr_stream_packet(DnsStream *s) {
323 DnsScope *scope;
324
325 assert(s);
326 assert(s->read_packet);
327
328 scope = manager_find_scope(s->manager, s->read_packet);
329 if (!scope)
330 log_warning("Got LLMNR TCP packet on unknown scope. Ignoring.");
331 else if (dns_packet_validate_query(s->read_packet) > 0) {
332 log_debug("Got LLMNR TCP query packet for id %u", DNS_PACKET_ID(s->read_packet));
333
334 dns_scope_process_query(scope, s, s->read_packet);
335 } else
336 log_debug("Invalid LLMNR TCP packet, ignoring.");
337
338 dns_stream_unref(s);
339 return 0;
340 }
341
342 static int on_llmnr_stream(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
343 DnsStream *stream;
344 Manager *m = userdata;
345 int cfd, r;
346
347 cfd = accept4(fd, NULL, NULL, SOCK_NONBLOCK|SOCK_CLOEXEC);
348 if (cfd < 0) {
349 if (IN_SET(errno, EAGAIN, EINTR))
350 return 0;
351
352 return -errno;
353 }
354
355 r = dns_stream_new(m, &stream, DNS_PROTOCOL_LLMNR, cfd);
356 if (r < 0) {
357 safe_close(cfd);
358 return r;
359 }
360
361 stream->on_packet = on_llmnr_stream_packet;
362 return 0;
363 }
364
365 int manager_llmnr_ipv4_tcp_fd(Manager *m) {
366 union sockaddr_union sa = {
367 .in.sin_family = AF_INET,
368 .in.sin_port = htobe16(LLMNR_PORT),
369 };
370 static const int one = 1, pmtu = IP_PMTUDISC_DONT;
371 int r;
372
373 assert(m);
374
375 if (m->llmnr_ipv4_tcp_fd >= 0)
376 return m->llmnr_ipv4_tcp_fd;
377
378 m->llmnr_ipv4_tcp_fd = socket(AF_INET, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
379 if (m->llmnr_ipv4_tcp_fd < 0)
380 return log_error_errno(errno, "LLMNR-IPv4(TCP): Failed to create socket: %m");
381
382 /* RFC 4795, section 2.5. requires setting the TTL of TCP streams to 1 */
383 r = setsockopt(m->llmnr_ipv4_tcp_fd, IPPROTO_IP, IP_TTL, &one, sizeof(one));
384 if (r < 0) {
385 r = log_error_errno(errno, "LLMNR-IPv4(TCP): Failed to set IP_TTL: %m");
386 goto fail;
387 }
388
389 r = setsockopt(m->llmnr_ipv4_tcp_fd, IPPROTO_IP, IP_PKTINFO, &one, sizeof(one));
390 if (r < 0) {
391 r = log_error_errno(errno, "LLMNR-IPv4(TCP): Failed to set IP_PKTINFO: %m");
392 goto fail;
393 }
394
395 r = setsockopt(m->llmnr_ipv4_tcp_fd, IPPROTO_IP, IP_RECVTTL, &one, sizeof(one));
396 if (r < 0) {
397 r = log_error_errno(errno, "LLMNR-IPv4(TCP): Failed to set IP_RECVTTL: %m");
398 goto fail;
399 }
400
401 /* Disable Don't-Fragment bit in the IP header */
402 r = setsockopt(m->llmnr_ipv4_tcp_fd, IPPROTO_IP, IP_MTU_DISCOVER, &pmtu, sizeof(pmtu));
403 if (r < 0) {
404 r = log_error_errno(errno, "LLMNR-IPv4(TCP): Failed to set IP_MTU_DISCOVER: %m");
405 goto fail;
406 }
407
408 /* first try to bind without SO_REUSEADDR to detect another LLMNR responder */
409 r = bind(m->llmnr_ipv4_tcp_fd, &sa.sa, sizeof(sa.in));
410 if (r < 0) {
411 if (errno != EADDRINUSE) {
412 r = log_error_errno(errno, "LLMNR-IPv4(TCP): Failed to bind socket: %m");
413 goto fail;
414 }
415
416 log_warning("LLMNR-IPv4(TCP): There appears to be another LLMNR responder running, or previously systemd-resolved crashed with some outstanding transfers.");
417
418 /* try again with SO_REUSEADDR */
419 r = setsockopt(m->llmnr_ipv4_tcp_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
420 if (r < 0) {
421 r = log_error_errno(errno, "LLMNR-IPv4(TCP): Failed to set SO_REUSEADDR: %m");
422 goto fail;
423 }
424
425 r = bind(m->llmnr_ipv4_tcp_fd, &sa.sa, sizeof(sa.in));
426 if (r < 0) {
427 r = log_error_errno(errno, "LLMNR-IPv4(TCP): Failed to bind socket: %m");
428 goto fail;
429 }
430 } else {
431 /* enable SO_REUSEADDR for the case that the user really wants multiple LLMNR responders */
432 r = setsockopt(m->llmnr_ipv4_tcp_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
433 if (r < 0) {
434 r = log_error_errno(errno, "LLMNR-IPv4(TCP): Failed to set SO_REUSEADDR: %m");
435 goto fail;
436 }
437 }
438
439 r = listen(m->llmnr_ipv4_tcp_fd, SOMAXCONN);
440 if (r < 0) {
441 r = log_error_errno(errno, "LLMNR-IPv4(TCP): Failed to listen the stream: %m");
442 goto fail;
443 }
444
445 r = sd_event_add_io(m->event, &m->llmnr_ipv4_tcp_event_source, m->llmnr_ipv4_tcp_fd, EPOLLIN, on_llmnr_stream, m);
446 if (r < 0)
447 goto fail;
448
449 (void) sd_event_source_set_description(m->llmnr_ipv4_tcp_event_source, "llmnr-ipv4-tcp");
450
451 return m->llmnr_ipv4_tcp_fd;
452
453 fail:
454 m->llmnr_ipv4_tcp_fd = safe_close(m->llmnr_ipv4_tcp_fd);
455 return r;
456 }
457
458 int manager_llmnr_ipv6_tcp_fd(Manager *m) {
459 union sockaddr_union sa = {
460 .in6.sin6_family = AF_INET6,
461 .in6.sin6_port = htobe16(LLMNR_PORT),
462 };
463 static const int one = 1;
464 int r;
465
466 assert(m);
467
468 if (m->llmnr_ipv6_tcp_fd >= 0)
469 return m->llmnr_ipv6_tcp_fd;
470
471 m->llmnr_ipv6_tcp_fd = socket(AF_INET6, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
472 if (m->llmnr_ipv6_tcp_fd < 0)
473 return log_error_errno(errno, "LLMNR-IPv6(TCP): Failed to create socket: %m");
474
475 /* RFC 4795, section 2.5. requires setting the TTL of TCP streams to 1 */
476 r = setsockopt(m->llmnr_ipv6_tcp_fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &one, sizeof(one));
477 if (r < 0) {
478 r = log_error_errno(errno, "LLMNR-IPv6(TCP): Failed to set IPV6_UNICAST_HOPS: %m");
479 goto fail;
480 }
481
482 r = setsockopt(m->llmnr_ipv6_tcp_fd, IPPROTO_IPV6, IPV6_V6ONLY, &one, sizeof(one));
483 if (r < 0) {
484 r = log_error_errno(errno, "LLMNR-IPv6(TCP): Failed to set IPV6_V6ONLY: %m");
485 goto fail;
486 }
487
488 r = setsockopt(m->llmnr_ipv6_tcp_fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &one, sizeof(one));
489 if (r < 0) {
490 r = log_error_errno(errno, "LLMNR-IPv6(TCP): Failed to set IPV6_RECVPKTINFO: %m");
491 goto fail;
492 }
493
494 r = setsockopt(m->llmnr_ipv6_tcp_fd, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &one, sizeof(one));
495 if (r < 0) {
496 r = log_error_errno(errno, "LLMNR-IPv6(TCP): Failed to set IPV6_RECVHOPLIMIT: %m");
497 goto fail;
498 }
499
500 /* first try to bind without SO_REUSEADDR to detect another LLMNR responder */
501 r = bind(m->llmnr_ipv6_tcp_fd, &sa.sa, sizeof(sa.in6));
502 if (r < 0) {
503 if (errno != EADDRINUSE) {
504 r = log_error_errno(errno, "LLMNR-IPv6(TCP): Failed to bind socket: %m");
505 goto fail;
506 }
507
508 log_warning("LLMNR-IPv6(TCP): There appears to be another LLMNR responder running, or previously systemd-resolved crashed with some outstanding transfers.");
509
510 /* try again with SO_REUSEADDR */
511 r = setsockopt(m->llmnr_ipv6_tcp_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
512 if (r < 0) {
513 r = log_error_errno(errno, "LLMNR-IPv6(TCP): Failed to set SO_REUSEADDR: %m");
514 goto fail;
515 }
516
517 r = bind(m->llmnr_ipv6_tcp_fd, &sa.sa, sizeof(sa.in6));
518 if (r < 0) {
519 r = log_error_errno(errno, "LLMNR-IPv6(TCP): Failed to bind socket: %m");
520 goto fail;
521 }
522 } else {
523 /* enable SO_REUSEADDR for the case that the user really wants multiple LLMNR responders */
524 r = setsockopt(m->llmnr_ipv6_tcp_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
525 if (r < 0) {
526 r = log_error_errno(errno, "LLMNR-IPv6(TCP): Failed to set SO_REUSEADDR: %m");
527 goto fail;
528 }
529 }
530
531 r = listen(m->llmnr_ipv6_tcp_fd, SOMAXCONN);
532 if (r < 0) {
533 r = log_error_errno(errno, "LLMNR-IPv6(TCP): Failed to listen the stream: %m");
534 goto fail;
535 }
536
537 r = sd_event_add_io(m->event, &m->llmnr_ipv6_tcp_event_source, m->llmnr_ipv6_tcp_fd, EPOLLIN, on_llmnr_stream, m);
538 if (r < 0)
539 goto fail;
540
541 (void) sd_event_source_set_description(m->llmnr_ipv6_tcp_event_source, "llmnr-ipv6-tcp");
542
543 return m->llmnr_ipv6_tcp_fd;
544
545 fail:
546 m->llmnr_ipv6_tcp_fd = safe_close(m->llmnr_ipv6_tcp_fd);
547 return r;
548 }