]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/resolve/resolved-llmnr.c
resolved: explicitly refuse zone transfers using the bus API
[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 r = manager_recv(m, fd, DNS_PROTOCOL_LLMNR, &p);
95 if (r <= 0)
96 return r;
97
98 scope = manager_find_scope(m, p);
99 if (!scope) {
100 log_warning("Got LLMNR UDP packet on unknown scope. Ignoring.");
101 return 0;
102 }
103
104 if (dns_packet_validate_reply(p) > 0) {
105 log_debug("Got LLMNR reply packet for id %u", DNS_PACKET_ID(p));
106
107 dns_scope_check_conflicts(scope, p);
108
109 t = hashmap_get(m->dns_transactions, UINT_TO_PTR(DNS_PACKET_ID(p)));
110 if (t)
111 dns_transaction_process_reply(t, p);
112
113 } else if (dns_packet_validate_query(p) > 0) {
114 log_debug("Got LLMNR query packet for id %u", DNS_PACKET_ID(p));
115
116 dns_scope_process_query(scope, NULL, p);
117 } else
118 log_debug("Invalid LLMNR UDP packet, ignoring.");
119
120 return 0;
121 }
122
123 int manager_llmnr_ipv4_udp_fd(Manager *m) {
124 union sockaddr_union sa = {
125 .in.sin_family = AF_INET,
126 .in.sin_port = htobe16(LLMNR_PORT),
127 };
128 static const int one = 1, pmtu = IP_PMTUDISC_DONT, ttl = 255;
129 int r;
130
131 assert(m);
132
133 if (m->llmnr_ipv4_udp_fd >= 0)
134 return m->llmnr_ipv4_udp_fd;
135
136 m->llmnr_ipv4_udp_fd = socket(AF_INET, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
137 if (m->llmnr_ipv4_udp_fd < 0)
138 return -errno;
139
140 /* RFC 4795, section 2.5 recommends setting the TTL of UDP packets to 255. */
141 r = setsockopt(m->llmnr_ipv4_udp_fd, IPPROTO_IP, IP_TTL, &ttl, sizeof(ttl));
142 if (r < 0) {
143 r = -errno;
144 goto fail;
145 }
146
147 r = setsockopt(m->llmnr_ipv4_udp_fd, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl));
148 if (r < 0) {
149 r = -errno;
150 goto fail;
151 }
152
153 r = setsockopt(m->llmnr_ipv4_udp_fd, IPPROTO_IP, IP_MULTICAST_LOOP, &one, sizeof(one));
154 if (r < 0) {
155 r = -errno;
156 goto fail;
157 }
158
159 r = setsockopt(m->llmnr_ipv4_udp_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
160 if (r < 0) {
161 r = -errno;
162 goto fail;
163 }
164
165 r = setsockopt(m->llmnr_ipv4_udp_fd, IPPROTO_IP, IP_PKTINFO, &one, sizeof(one));
166 if (r < 0) {
167 r = -errno;
168 goto fail;
169 }
170
171 r = setsockopt(m->llmnr_ipv4_udp_fd, IPPROTO_IP, IP_RECVTTL, &one, sizeof(one));
172 if (r < 0) {
173 r = -errno;
174 goto fail;
175 }
176
177 /* Disable Don't-Fragment bit in the IP header */
178 r = setsockopt(m->llmnr_ipv4_udp_fd, IPPROTO_IP, IP_MTU_DISCOVER, &pmtu, sizeof(pmtu));
179 if (r < 0) {
180 r = -errno;
181 goto fail;
182 }
183
184 r = bind(m->llmnr_ipv4_udp_fd, &sa.sa, sizeof(sa.in));
185 if (r < 0) {
186 r = -errno;
187 goto fail;
188 }
189
190 r = sd_event_add_io(m->event, &m->llmnr_ipv4_udp_event_source, m->llmnr_ipv4_udp_fd, EPOLLIN, on_llmnr_packet, m);
191 if (r < 0)
192 goto fail;
193
194 (void) sd_event_source_set_description(m->llmnr_ipv4_udp_event_source, "llmnr-ipv4-udp");
195
196 return m->llmnr_ipv4_udp_fd;
197
198 fail:
199 m->llmnr_ipv4_udp_fd = safe_close(m->llmnr_ipv4_udp_fd);
200 return r;
201 }
202
203 int manager_llmnr_ipv6_udp_fd(Manager *m) {
204 union sockaddr_union sa = {
205 .in6.sin6_family = AF_INET6,
206 .in6.sin6_port = htobe16(LLMNR_PORT),
207 };
208 static const int one = 1, ttl = 255;
209 int r;
210
211 assert(m);
212
213 if (m->llmnr_ipv6_udp_fd >= 0)
214 return m->llmnr_ipv6_udp_fd;
215
216 m->llmnr_ipv6_udp_fd = socket(AF_INET6, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
217 if (m->llmnr_ipv6_udp_fd < 0)
218 return -errno;
219
220 r = setsockopt(m->llmnr_ipv6_udp_fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &ttl, sizeof(ttl));
221 if (r < 0) {
222 r = -errno;
223 goto fail;
224 }
225
226 /* RFC 4795, section 2.5 recommends setting the TTL of UDP packets to 255. */
227 r = setsockopt(m->llmnr_ipv6_udp_fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &ttl, sizeof(ttl));
228 if (r < 0) {
229 r = -errno;
230 goto fail;
231 }
232
233 r = setsockopt(m->llmnr_ipv6_udp_fd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &one, sizeof(one));
234 if (r < 0) {
235 r = -errno;
236 goto fail;
237 }
238
239 r = setsockopt(m->llmnr_ipv6_udp_fd, IPPROTO_IPV6, IPV6_V6ONLY, &one, sizeof(one));
240 if (r < 0) {
241 r = -errno;
242 goto fail;
243 }
244
245 r = setsockopt(m->llmnr_ipv6_udp_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
246 if (r < 0) {
247 r = -errno;
248 goto fail;
249 }
250
251 r = setsockopt(m->llmnr_ipv6_udp_fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &one, sizeof(one));
252 if (r < 0) {
253 r = -errno;
254 goto fail;
255 }
256
257 r = setsockopt(m->llmnr_ipv6_udp_fd, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &one, sizeof(one));
258 if (r < 0) {
259 r = -errno;
260 goto fail;
261 }
262
263 r = bind(m->llmnr_ipv6_udp_fd, &sa.sa, sizeof(sa.in6));
264 if (r < 0) {
265 r = -errno;
266 goto fail;
267 }
268
269 r = sd_event_add_io(m->event, &m->llmnr_ipv6_udp_event_source, m->llmnr_ipv6_udp_fd, EPOLLIN, on_llmnr_packet, m);
270 if (r < 0)
271 goto fail;
272
273 (void) sd_event_source_set_description(m->llmnr_ipv6_udp_event_source, "llmnr-ipv6-udp");
274
275 return m->llmnr_ipv6_udp_fd;
276
277 fail:
278 m->llmnr_ipv6_udp_fd = safe_close(m->llmnr_ipv6_udp_fd);
279 return r;
280 }
281
282 static int on_llmnr_stream_packet(DnsStream *s) {
283 DnsScope *scope;
284
285 assert(s);
286
287 scope = manager_find_scope(s->manager, s->read_packet);
288 if (!scope) {
289 log_warning("Got LLMNR TCP packet on unknown scope. Ignoring.");
290 return 0;
291 }
292
293 if (dns_packet_validate_query(s->read_packet) > 0) {
294 log_debug("Got query packet for id %u", DNS_PACKET_ID(s->read_packet));
295
296 dns_scope_process_query(scope, s, s->read_packet);
297
298 /* If no reply packet was set, we free the stream */
299 if (s->write_packet)
300 return 0;
301 } else
302 log_debug("Invalid LLMNR TCP packet.");
303
304 dns_stream_free(s);
305 return 0;
306 }
307
308 static int on_llmnr_stream(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
309 DnsStream *stream;
310 Manager *m = userdata;
311 int cfd, r;
312
313 cfd = accept4(fd, NULL, NULL, SOCK_NONBLOCK|SOCK_CLOEXEC);
314 if (cfd < 0) {
315 if (errno == EAGAIN || errno == EINTR)
316 return 0;
317
318 return -errno;
319 }
320
321 r = dns_stream_new(m, &stream, DNS_PROTOCOL_LLMNR, cfd);
322 if (r < 0) {
323 safe_close(cfd);
324 return r;
325 }
326
327 stream->on_packet = on_llmnr_stream_packet;
328 return 0;
329 }
330
331 int manager_llmnr_ipv4_tcp_fd(Manager *m) {
332 union sockaddr_union sa = {
333 .in.sin_family = AF_INET,
334 .in.sin_port = htobe16(LLMNR_PORT),
335 };
336 static const int one = 1, pmtu = IP_PMTUDISC_DONT;
337 int r;
338
339 assert(m);
340
341 if (m->llmnr_ipv4_tcp_fd >= 0)
342 return m->llmnr_ipv4_tcp_fd;
343
344 m->llmnr_ipv4_tcp_fd = socket(AF_INET, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
345 if (m->llmnr_ipv4_tcp_fd < 0)
346 return -errno;
347
348 /* RFC 4795, section 2.5. requires setting the TTL of TCP streams to 1 */
349 r = setsockopt(m->llmnr_ipv4_tcp_fd, IPPROTO_IP, IP_TTL, &one, sizeof(one));
350 if (r < 0) {
351 r = -errno;
352 goto fail;
353 }
354
355 r = setsockopt(m->llmnr_ipv4_tcp_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
356 if (r < 0) {
357 r = -errno;
358 goto fail;
359 }
360
361 r = setsockopt(m->llmnr_ipv4_tcp_fd, IPPROTO_IP, IP_PKTINFO, &one, sizeof(one));
362 if (r < 0) {
363 r = -errno;
364 goto fail;
365 }
366
367 r = setsockopt(m->llmnr_ipv4_tcp_fd, IPPROTO_IP, IP_RECVTTL, &one, sizeof(one));
368 if (r < 0) {
369 r = -errno;
370 goto fail;
371 }
372
373 /* Disable Don't-Fragment bit in the IP header */
374 r = setsockopt(m->llmnr_ipv4_tcp_fd, IPPROTO_IP, IP_MTU_DISCOVER, &pmtu, sizeof(pmtu));
375 if (r < 0) {
376 r = -errno;
377 goto fail;
378 }
379
380 r = bind(m->llmnr_ipv4_tcp_fd, &sa.sa, sizeof(sa.in));
381 if (r < 0) {
382 r = -errno;
383 goto fail;
384 }
385
386 r = listen(m->llmnr_ipv4_tcp_fd, SOMAXCONN);
387 if (r < 0) {
388 r = -errno;
389 goto fail;
390 }
391
392 r = sd_event_add_io(m->event, &m->llmnr_ipv4_tcp_event_source, m->llmnr_ipv4_tcp_fd, EPOLLIN, on_llmnr_stream, m);
393 if (r < 0)
394 goto fail;
395
396 (void) sd_event_source_set_description(m->llmnr_ipv4_tcp_event_source, "llmnr-ipv4-tcp");
397
398 return m->llmnr_ipv4_tcp_fd;
399
400 fail:
401 m->llmnr_ipv4_tcp_fd = safe_close(m->llmnr_ipv4_tcp_fd);
402 return r;
403 }
404
405 int manager_llmnr_ipv6_tcp_fd(Manager *m) {
406 union sockaddr_union sa = {
407 .in6.sin6_family = AF_INET6,
408 .in6.sin6_port = htobe16(LLMNR_PORT),
409 };
410 static const int one = 1;
411 int r;
412
413 assert(m);
414
415 if (m->llmnr_ipv6_tcp_fd >= 0)
416 return m->llmnr_ipv6_tcp_fd;
417
418 m->llmnr_ipv6_tcp_fd = socket(AF_INET6, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
419 if (m->llmnr_ipv6_tcp_fd < 0)
420 return -errno;
421
422 /* RFC 4795, section 2.5. requires setting the TTL of TCP streams to 1 */
423 r = setsockopt(m->llmnr_ipv6_tcp_fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &one, sizeof(one));
424 if (r < 0) {
425 r = -errno;
426 goto fail;
427 }
428
429 r = setsockopt(m->llmnr_ipv6_tcp_fd, IPPROTO_IPV6, IPV6_V6ONLY, &one, sizeof(one));
430 if (r < 0) {
431 r = -errno;
432 goto fail;
433 }
434
435 r = setsockopt(m->llmnr_ipv6_tcp_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
436 if (r < 0) {
437 r = -errno;
438 goto fail;
439 }
440
441 r = setsockopt(m->llmnr_ipv6_tcp_fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &one, sizeof(one));
442 if (r < 0) {
443 r = -errno;
444 goto fail;
445 }
446
447 r = setsockopt(m->llmnr_ipv6_tcp_fd, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &one, sizeof(one));
448 if (r < 0) {
449 r = -errno;
450 goto fail;
451 }
452
453 r = bind(m->llmnr_ipv6_tcp_fd, &sa.sa, sizeof(sa.in6));
454 if (r < 0) {
455 r = -errno;
456 goto fail;
457 }
458
459 r = listen(m->llmnr_ipv6_tcp_fd, SOMAXCONN);
460 if (r < 0) {
461 r = -errno;
462 goto fail;
463 }
464
465 r = sd_event_add_io(m->event, &m->llmnr_ipv6_tcp_event_source, m->llmnr_ipv6_tcp_fd, EPOLLIN, on_llmnr_stream, m);
466 if (r < 0)
467 goto fail;
468
469 (void) sd_event_source_set_description(m->llmnr_ipv6_tcp_event_source, "llmnr-ipv6-tcp");
470
471 return m->llmnr_ipv6_tcp_fd;
472
473 fail:
474 m->llmnr_ipv6_tcp_fd = safe_close(m->llmnr_ipv6_tcp_fd);
475 return r;
476 }