]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/resolve/resolved-llmnr.c
resolved: respond to local resolver requests on 127.0.0.53:53
[thirdparty/systemd.git] / src / resolve / resolved-llmnr.c
1 /***
2 This file is part of systemd.
3
4 Copyright 2014 Tom Gundersen <teg@jklm.no>
5
6 systemd is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation; either version 2.1 of the License, or
9 (at your option) any later version.
10
11 systemd is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
15
16 You should have received a copy of the GNU Lesser General Public License
17 along with systemd; If not, see <http://www.gnu.org/licenses/>.
18 ***/
19
20 #include <netinet/in.h>
21 #include <resolv.h>
22
23 #include "fd-util.h"
24 #include "resolved-llmnr.h"
25 #include "resolved-manager.h"
26
27 void manager_llmnr_stop(Manager *m) {
28 assert(m);
29
30 m->llmnr_ipv4_udp_event_source = sd_event_source_unref(m->llmnr_ipv4_udp_event_source);
31 m->llmnr_ipv4_udp_fd = safe_close(m->llmnr_ipv4_udp_fd);
32
33 m->llmnr_ipv6_udp_event_source = sd_event_source_unref(m->llmnr_ipv6_udp_event_source);
34 m->llmnr_ipv6_udp_fd = safe_close(m->llmnr_ipv6_udp_fd);
35
36 m->llmnr_ipv4_tcp_event_source = sd_event_source_unref(m->llmnr_ipv4_tcp_event_source);
37 m->llmnr_ipv4_tcp_fd = safe_close(m->llmnr_ipv4_tcp_fd);
38
39 m->llmnr_ipv6_tcp_event_source = sd_event_source_unref(m->llmnr_ipv6_tcp_event_source);
40 m->llmnr_ipv6_tcp_fd = safe_close(m->llmnr_ipv6_tcp_fd);
41 }
42
43 int manager_llmnr_start(Manager *m) {
44 int r;
45
46 assert(m);
47
48 if (m->llmnr_support == RESOLVE_SUPPORT_NO)
49 return 0;
50
51 r = manager_llmnr_ipv4_udp_fd(m);
52 if (r == -EADDRINUSE)
53 goto eaddrinuse;
54 if (r < 0)
55 return r;
56
57 r = manager_llmnr_ipv4_tcp_fd(m);
58 if (r == -EADDRINUSE)
59 goto eaddrinuse;
60 if (r < 0)
61 return r;
62
63 if (socket_ipv6_is_supported()) {
64 r = manager_llmnr_ipv6_udp_fd(m);
65 if (r == -EADDRINUSE)
66 goto eaddrinuse;
67 if (r < 0)
68 return r;
69
70 r = manager_llmnr_ipv6_tcp_fd(m);
71 if (r == -EADDRINUSE)
72 goto eaddrinuse;
73 if (r < 0)
74 return r;
75 }
76
77 return 0;
78
79 eaddrinuse:
80 log_warning("There appears to be another LLMNR responder running. Turning off LLMNR support.");
81 m->llmnr_support = RESOLVE_SUPPORT_NO;
82 manager_llmnr_stop(m);
83
84 return 0;
85 }
86
87 static int on_llmnr_packet(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
88 _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
89 DnsTransaction *t = NULL;
90 Manager *m = userdata;
91 DnsScope *scope;
92 int r;
93
94 assert(s);
95 assert(fd >= 0);
96 assert(m);
97
98 r = manager_recv(m, fd, DNS_PROTOCOL_LLMNR, &p);
99 if (r <= 0)
100 return r;
101
102 scope = manager_find_scope(m, p);
103 if (!scope)
104 log_warning("Got LLMNR UDP packet on unknown scope. Ignoring.");
105 else if (dns_packet_validate_reply(p) > 0) {
106 log_debug("Got LLMNR UDP reply packet for id %u", DNS_PACKET_ID(p));
107
108 dns_scope_check_conflicts(scope, p);
109
110 t = hashmap_get(m->dns_transactions, UINT_TO_PTR(DNS_PACKET_ID(p)));
111 if (t)
112 dns_transaction_process_reply(t, p);
113
114 } else if (dns_packet_validate_query(p) > 0) {
115 log_debug("Got LLMNR UDP query packet for id %u", DNS_PACKET_ID(p));
116
117 dns_scope_process_query(scope, NULL, p);
118 } else
119 log_debug("Invalid LLMNR UDP packet, ignoring.");
120
121 return 0;
122 }
123
124 int manager_llmnr_ipv4_udp_fd(Manager *m) {
125 union sockaddr_union sa = {
126 .in.sin_family = AF_INET,
127 .in.sin_port = htobe16(LLMNR_PORT),
128 };
129 static const int one = 1, pmtu = IP_PMTUDISC_DONT, ttl = 255;
130 int r;
131
132 assert(m);
133
134 if (m->llmnr_ipv4_udp_fd >= 0)
135 return m->llmnr_ipv4_udp_fd;
136
137 m->llmnr_ipv4_udp_fd = socket(AF_INET, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
138 if (m->llmnr_ipv4_udp_fd < 0)
139 return -errno;
140
141 /* RFC 4795, section 2.5 recommends setting the TTL of UDP packets to 255. */
142 r = setsockopt(m->llmnr_ipv4_udp_fd, IPPROTO_IP, IP_TTL, &ttl, sizeof(ttl));
143 if (r < 0) {
144 r = -errno;
145 goto fail;
146 }
147
148 r = setsockopt(m->llmnr_ipv4_udp_fd, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl));
149 if (r < 0) {
150 r = -errno;
151 goto fail;
152 }
153
154 r = setsockopt(m->llmnr_ipv4_udp_fd, IPPROTO_IP, IP_MULTICAST_LOOP, &one, sizeof(one));
155 if (r < 0) {
156 r = -errno;
157 goto fail;
158 }
159
160 r = setsockopt(m->llmnr_ipv4_udp_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
161 if (r < 0) {
162 r = -errno;
163 goto fail;
164 }
165
166 r = setsockopt(m->llmnr_ipv4_udp_fd, IPPROTO_IP, IP_PKTINFO, &one, sizeof(one));
167 if (r < 0) {
168 r = -errno;
169 goto fail;
170 }
171
172 r = setsockopt(m->llmnr_ipv4_udp_fd, IPPROTO_IP, IP_RECVTTL, &one, sizeof(one));
173 if (r < 0) {
174 r = -errno;
175 goto fail;
176 }
177
178 /* Disable Don't-Fragment bit in the IP header */
179 r = setsockopt(m->llmnr_ipv4_udp_fd, IPPROTO_IP, IP_MTU_DISCOVER, &pmtu, sizeof(pmtu));
180 if (r < 0) {
181 r = -errno;
182 goto fail;
183 }
184
185 r = bind(m->llmnr_ipv4_udp_fd, &sa.sa, sizeof(sa.in));
186 if (r < 0) {
187 r = -errno;
188 goto fail;
189 }
190
191 r = sd_event_add_io(m->event, &m->llmnr_ipv4_udp_event_source, m->llmnr_ipv4_udp_fd, EPOLLIN, on_llmnr_packet, m);
192 if (r < 0)
193 goto fail;
194
195 (void) sd_event_source_set_description(m->llmnr_ipv4_udp_event_source, "llmnr-ipv4-udp");
196
197 return m->llmnr_ipv4_udp_fd;
198
199 fail:
200 m->llmnr_ipv4_udp_fd = safe_close(m->llmnr_ipv4_udp_fd);
201 return r;
202 }
203
204 int manager_llmnr_ipv6_udp_fd(Manager *m) {
205 union sockaddr_union sa = {
206 .in6.sin6_family = AF_INET6,
207 .in6.sin6_port = htobe16(LLMNR_PORT),
208 };
209 static const int one = 1, ttl = 255;
210 int r;
211
212 assert(m);
213
214 if (m->llmnr_ipv6_udp_fd >= 0)
215 return m->llmnr_ipv6_udp_fd;
216
217 m->llmnr_ipv6_udp_fd = socket(AF_INET6, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
218 if (m->llmnr_ipv6_udp_fd < 0)
219 return -errno;
220
221 r = setsockopt(m->llmnr_ipv6_udp_fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &ttl, sizeof(ttl));
222 if (r < 0) {
223 r = -errno;
224 goto fail;
225 }
226
227 /* RFC 4795, section 2.5 recommends setting the TTL of UDP packets to 255. */
228 r = setsockopt(m->llmnr_ipv6_udp_fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &ttl, sizeof(ttl));
229 if (r < 0) {
230 r = -errno;
231 goto fail;
232 }
233
234 r = setsockopt(m->llmnr_ipv6_udp_fd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &one, sizeof(one));
235 if (r < 0) {
236 r = -errno;
237 goto fail;
238 }
239
240 r = setsockopt(m->llmnr_ipv6_udp_fd, IPPROTO_IPV6, IPV6_V6ONLY, &one, sizeof(one));
241 if (r < 0) {
242 r = -errno;
243 goto fail;
244 }
245
246 r = setsockopt(m->llmnr_ipv6_udp_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
247 if (r < 0) {
248 r = -errno;
249 goto fail;
250 }
251
252 r = setsockopt(m->llmnr_ipv6_udp_fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &one, sizeof(one));
253 if (r < 0) {
254 r = -errno;
255 goto fail;
256 }
257
258 r = setsockopt(m->llmnr_ipv6_udp_fd, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &one, sizeof(one));
259 if (r < 0) {
260 r = -errno;
261 goto fail;
262 }
263
264 r = bind(m->llmnr_ipv6_udp_fd, &sa.sa, sizeof(sa.in6));
265 if (r < 0) {
266 r = -errno;
267 goto fail;
268 }
269
270 r = sd_event_add_io(m->event, &m->llmnr_ipv6_udp_event_source, m->llmnr_ipv6_udp_fd, EPOLLIN, on_llmnr_packet, m);
271 if (r < 0)
272 goto fail;
273
274 (void) sd_event_source_set_description(m->llmnr_ipv6_udp_event_source, "llmnr-ipv6-udp");
275
276 return m->llmnr_ipv6_udp_fd;
277
278 fail:
279 m->llmnr_ipv6_udp_fd = safe_close(m->llmnr_ipv6_udp_fd);
280 return r;
281 }
282
283 static int on_llmnr_stream_packet(DnsStream *s) {
284 DnsScope *scope;
285
286 assert(s);
287 assert(s->read_packet);
288
289 scope = manager_find_scope(s->manager, s->read_packet);
290 if (!scope)
291 log_warning("Got LLMNR TCP packet on unknown scope. Ignoring.");
292 else if (dns_packet_validate_query(s->read_packet) > 0) {
293 log_debug("Got LLMNR TCP query packet for id %u", DNS_PACKET_ID(s->read_packet));
294
295 dns_scope_process_query(scope, s, s->read_packet);
296 } else
297 log_debug("Invalid LLMNR TCP packet, ignoring.");
298
299 dns_stream_unref(s);
300 return 0;
301 }
302
303 static int on_llmnr_stream(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
304 DnsStream *stream;
305 Manager *m = userdata;
306 int cfd, r;
307
308 cfd = accept4(fd, NULL, NULL, SOCK_NONBLOCK|SOCK_CLOEXEC);
309 if (cfd < 0) {
310 if (errno == EAGAIN || errno == EINTR)
311 return 0;
312
313 return -errno;
314 }
315
316 r = dns_stream_new(m, &stream, DNS_PROTOCOL_LLMNR, cfd);
317 if (r < 0) {
318 safe_close(cfd);
319 return r;
320 }
321
322 stream->on_packet = on_llmnr_stream_packet;
323 return 0;
324 }
325
326 int manager_llmnr_ipv4_tcp_fd(Manager *m) {
327 union sockaddr_union sa = {
328 .in.sin_family = AF_INET,
329 .in.sin_port = htobe16(LLMNR_PORT),
330 };
331 static const int one = 1, pmtu = IP_PMTUDISC_DONT;
332 int r;
333
334 assert(m);
335
336 if (m->llmnr_ipv4_tcp_fd >= 0)
337 return m->llmnr_ipv4_tcp_fd;
338
339 m->llmnr_ipv4_tcp_fd = socket(AF_INET, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
340 if (m->llmnr_ipv4_tcp_fd < 0)
341 return -errno;
342
343 /* RFC 4795, section 2.5. requires setting the TTL of TCP streams to 1 */
344 r = setsockopt(m->llmnr_ipv4_tcp_fd, IPPROTO_IP, IP_TTL, &one, sizeof(one));
345 if (r < 0) {
346 r = -errno;
347 goto fail;
348 }
349
350 r = setsockopt(m->llmnr_ipv4_tcp_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
351 if (r < 0) {
352 r = -errno;
353 goto fail;
354 }
355
356 r = setsockopt(m->llmnr_ipv4_tcp_fd, IPPROTO_IP, IP_PKTINFO, &one, sizeof(one));
357 if (r < 0) {
358 r = -errno;
359 goto fail;
360 }
361
362 r = setsockopt(m->llmnr_ipv4_tcp_fd, IPPROTO_IP, IP_RECVTTL, &one, sizeof(one));
363 if (r < 0) {
364 r = -errno;
365 goto fail;
366 }
367
368 /* Disable Don't-Fragment bit in the IP header */
369 r = setsockopt(m->llmnr_ipv4_tcp_fd, IPPROTO_IP, IP_MTU_DISCOVER, &pmtu, sizeof(pmtu));
370 if (r < 0) {
371 r = -errno;
372 goto fail;
373 }
374
375 r = bind(m->llmnr_ipv4_tcp_fd, &sa.sa, sizeof(sa.in));
376 if (r < 0) {
377 r = -errno;
378 goto fail;
379 }
380
381 r = listen(m->llmnr_ipv4_tcp_fd, SOMAXCONN);
382 if (r < 0) {
383 r = -errno;
384 goto fail;
385 }
386
387 r = sd_event_add_io(m->event, &m->llmnr_ipv4_tcp_event_source, m->llmnr_ipv4_tcp_fd, EPOLLIN, on_llmnr_stream, m);
388 if (r < 0)
389 goto fail;
390
391 (void) sd_event_source_set_description(m->llmnr_ipv4_tcp_event_source, "llmnr-ipv4-tcp");
392
393 return m->llmnr_ipv4_tcp_fd;
394
395 fail:
396 m->llmnr_ipv4_tcp_fd = safe_close(m->llmnr_ipv4_tcp_fd);
397 return r;
398 }
399
400 int manager_llmnr_ipv6_tcp_fd(Manager *m) {
401 union sockaddr_union sa = {
402 .in6.sin6_family = AF_INET6,
403 .in6.sin6_port = htobe16(LLMNR_PORT),
404 };
405 static const int one = 1;
406 int r;
407
408 assert(m);
409
410 if (m->llmnr_ipv6_tcp_fd >= 0)
411 return m->llmnr_ipv6_tcp_fd;
412
413 m->llmnr_ipv6_tcp_fd = socket(AF_INET6, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
414 if (m->llmnr_ipv6_tcp_fd < 0)
415 return -errno;
416
417 /* RFC 4795, section 2.5. requires setting the TTL of TCP streams to 1 */
418 r = setsockopt(m->llmnr_ipv6_tcp_fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &one, sizeof(one));
419 if (r < 0) {
420 r = -errno;
421 goto fail;
422 }
423
424 r = setsockopt(m->llmnr_ipv6_tcp_fd, IPPROTO_IPV6, IPV6_V6ONLY, &one, sizeof(one));
425 if (r < 0) {
426 r = -errno;
427 goto fail;
428 }
429
430 r = setsockopt(m->llmnr_ipv6_tcp_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
431 if (r < 0) {
432 r = -errno;
433 goto fail;
434 }
435
436 r = setsockopt(m->llmnr_ipv6_tcp_fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &one, sizeof(one));
437 if (r < 0) {
438 r = -errno;
439 goto fail;
440 }
441
442 r = setsockopt(m->llmnr_ipv6_tcp_fd, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &one, sizeof(one));
443 if (r < 0) {
444 r = -errno;
445 goto fail;
446 }
447
448 r = bind(m->llmnr_ipv6_tcp_fd, &sa.sa, sizeof(sa.in6));
449 if (r < 0) {
450 r = -errno;
451 goto fail;
452 }
453
454 r = listen(m->llmnr_ipv6_tcp_fd, SOMAXCONN);
455 if (r < 0) {
456 r = -errno;
457 goto fail;
458 }
459
460 r = sd_event_add_io(m->event, &m->llmnr_ipv6_tcp_event_source, m->llmnr_ipv6_tcp_fd, EPOLLIN, on_llmnr_stream, m);
461 if (r < 0)
462 goto fail;
463
464 (void) sd_event_source_set_description(m->llmnr_ipv6_tcp_event_source, "llmnr-ipv6-tcp");
465
466 return m->llmnr_ipv6_tcp_fd;
467
468 fail:
469 m->llmnr_ipv6_tcp_fd = safe_close(m->llmnr_ipv6_tcp_fd);
470 return r;
471 }