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