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