]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/resolve/resolved-dns-stub.c
resolved: add missing error code check when initializing DNS-over-TLS
[thirdparty/systemd.git] / src / resolve / resolved-dns-stub.c
CommitLineData
53e1b683 1/* SPDX-License-Identifier: LGPL-2.1+ */
b30bf55d 2
4ff9bc2e 3#include "errno-util.h"
b30bf55d 4#include "fd-util.h"
ef118d00 5#include "missing_network.h"
b30bf55d
LP
6#include "resolved-dns-stub.h"
7#include "socket-util.h"
8
9/* The MTU of the loopback device is 64K on Linux, advertise that as maximum datagram size, but subtract the Ethernet,
10 * IP and UDP header sizes */
11#define ADVERTISE_DATAGRAM_SIZE_MAX (65536U-14U-20U-8U)
12
424e490b
ZJS
13static int manager_dns_stub_udp_fd(Manager *m);
14static int manager_dns_stub_tcp_fd(Manager *m);
15
b30bf55d 16static int dns_stub_make_reply_packet(
e8d23f92 17 DnsPacket **p,
51027656 18 size_t max_size,
b30bf55d 19 DnsQuestion *q,
51027656
LP
20 DnsAnswer *answer,
21 bool *ret_truncated) {
b30bf55d 22
51027656 23 bool truncated = false;
b30bf55d
LP
24 DnsResourceRecord *rr;
25 unsigned c = 0;
26 int r;
27
e8d23f92
LP
28 assert(p);
29
b30bf55d
LP
30 /* Note that we don't bother with any additional RRs, as this is stub is for local lookups only, and hence
31 * roundtrips aren't expensive. */
32
e8d23f92 33 if (!*p) {
51027656 34 r = dns_packet_new(p, DNS_PROTOCOL_DNS, 0, max_size);
e8d23f92
LP
35 if (r < 0)
36 return r;
b30bf55d 37
e8d23f92
LP
38 r = dns_packet_append_question(*p, q);
39 if (r < 0)
40 return r;
b30bf55d 41
e8d23f92
LP
42 DNS_PACKET_HEADER(*p)->qdcount = htobe16(dns_question_size(q));
43 }
b30bf55d
LP
44
45 DNS_ANSWER_FOREACH(rr, answer) {
e8d23f92 46
b30bf55d
LP
47 r = dns_question_matches_rr(q, rr, NULL);
48 if (r < 0)
49 return r;
50 if (r > 0)
51 goto add;
52
53 r = dns_question_matches_cname_or_dname(q, rr, NULL);
54 if (r < 0)
55 return r;
56 if (r > 0)
57 goto add;
58
59 continue;
60 add:
01c901e2 61 r = dns_packet_append_rr(*p, rr, 0, NULL, NULL);
51027656
LP
62 if (r == -EMSGSIZE) {
63 truncated = true;
64 break;
65 }
b30bf55d
LP
66 if (r < 0)
67 return r;
68
69 c++;
70 }
e8d23f92 71
51027656
LP
72 if (ret_truncated)
73 *ret_truncated = truncated;
74 else if (truncated)
75 return -EMSGSIZE;
76
e8d23f92
LP
77 DNS_PACKET_HEADER(*p)->ancount = htobe16(be16toh(DNS_PACKET_HEADER(*p)->ancount) + c);
78
79 return 0;
80}
81
82static int dns_stub_finish_reply_packet(
83 DnsPacket *p,
84 uint16_t id,
85 int rcode,
51027656 86 bool tc, /* set the Truncated bit? */
e8d23f92
LP
87 bool add_opt, /* add an OPT RR to this packet? */
88 bool edns0_do, /* set the EDNS0 DNSSEC OK bit? */
89 bool ad) { /* set the DNSSEC authenticated data bit? */
90
91 int r;
92
93 assert(p);
94
ff4caaae
LP
95 if (add_opt) {
96 r = dns_packet_append_opt(p, ADVERTISE_DATAGRAM_SIZE_MAX, edns0_do, rcode, NULL);
97 if (r == -EMSGSIZE) /* Hit the size limit? then indicate truncation */
98 tc = true;
99 else if (r < 0)
100 return r;
101
102 } else {
941dd294
LP
103 /* If the client can't to EDNS0, don't do DO either */
104 edns0_do = false;
105
106 /* If the client didn't do EDNS, clamp the rcode to 4 bit */
107 if (rcode > 0xF)
108 rcode = DNS_RCODE_SERVFAIL;
109 }
110
111 /* Don't set the AD bit unless DO is on, too */
112 if (!edns0_do)
113 ad = false;
e8d23f92
LP
114
115 DNS_PACKET_HEADER(p)->id = id;
116
117 DNS_PACKET_HEADER(p)->flags = htobe16(DNS_PACKET_MAKE_FLAGS(
51027656
LP
118 1 /* qr */,
119 0 /* opcode */,
120 0 /* aa */,
121 tc /* tc */,
122 1 /* rd */,
123 1 /* ra */,
e8d23f92 124 ad /* ad */,
51027656 125 0 /* cd */,
e8d23f92 126 rcode));
b30bf55d 127
b30bf55d
LP
128 return 0;
129}
130
b30bf55d
LP
131static int dns_stub_send(Manager *m, DnsStream *s, DnsPacket *p, DnsPacket *reply) {
132 int r;
133
134 assert(m);
135 assert(p);
136 assert(reply);
137
138 if (s)
139 r = dns_stream_write_packet(s, reply);
140 else {
141 int fd;
142
b30bf55d
LP
143 fd = manager_dns_stub_udp_fd(m);
144 if (fd < 0)
145 return log_debug_errno(fd, "Failed to get reply socket: %m");
146
147 /* Note that it is essential here that we explicitly choose the source IP address for this packet. This
148 * is because otherwise the kernel will choose it automatically based on the routing table and will
149 * thus pick 127.0.0.1 rather than 127.0.0.53. */
150
151 r = manager_send(m, fd, LOOPBACK_IFINDEX, p->family, &p->sender, p->sender_port, &p->destination, reply);
152 }
153 if (r < 0)
154 return log_debug_errno(r, "Failed to send reply packet: %m");
155
156 return 0;
157}
158
2b2d98c1 159static int dns_stub_send_failure(Manager *m, DnsStream *s, DnsPacket *p, int rcode, bool authenticated) {
b30bf55d
LP
160 _cleanup_(dns_packet_unrefp) DnsPacket *reply = NULL;
161 int r;
162
163 assert(m);
164 assert(p);
165
51027656 166 r = dns_stub_make_reply_packet(&reply, DNS_PACKET_PAYLOAD_SIZE_MAX(p), p->question, NULL, NULL);
e8d23f92
LP
167 if (r < 0)
168 return log_debug_errno(r, "Failed to make failure packet: %m");
169
51027656 170 r = dns_stub_finish_reply_packet(reply, DNS_PACKET_ID(p), rcode, false, !!p->opt, DNS_PACKET_DO(p), authenticated);
b30bf55d
LP
171 if (r < 0)
172 return log_debug_errno(r, "Failed to build failure packet: %m");
173
174 return dns_stub_send(m, s, p, reply);
175}
176
177static void dns_stub_query_complete(DnsQuery *q) {
178 int r;
179
180 assert(q);
181 assert(q->request_dns_packet);
182
183 switch (q->state) {
184
51027656
LP
185 case DNS_TRANSACTION_SUCCESS: {
186 bool truncated;
e8d23f92 187
51027656 188 r = dns_stub_make_reply_packet(&q->reply_dns_packet, DNS_PACKET_PAYLOAD_SIZE_MAX(q->request_dns_packet), q->question_idna, q->answer, &truncated);
e8d23f92
LP
189 if (r < 0) {
190 log_debug_errno(r, "Failed to build reply packet: %m");
191 break;
192 }
b30bf55d 193
aa11cab9
LP
194 if (!truncated) {
195 r = dns_query_process_cname(q);
196 if (r == -ELOOP) {
197 (void) dns_stub_send_failure(q->manager, q->request_dns_stream, q->request_dns_packet, DNS_RCODE_SERVFAIL, false);
198 break;
199 }
200 if (r < 0) {
201 log_debug_errno(r, "Failed to process CNAME: %m");
202 break;
203 }
204 if (r == DNS_QUERY_RESTARTED)
205 return;
e8d23f92 206 }
e8d23f92
LP
207
208 r = dns_stub_finish_reply_packet(
209 q->reply_dns_packet,
b30bf55d
LP
210 DNS_PACKET_ID(q->request_dns_packet),
211 q->answer_rcode,
51027656 212 truncated,
b30bf55d
LP
213 !!q->request_dns_packet->opt,
214 DNS_PACKET_DO(q->request_dns_packet),
941dd294 215 dns_query_fully_authenticated(q));
b30bf55d 216 if (r < 0) {
e8d23f92 217 log_debug_errno(r, "Failed to finish reply packet: %m");
b30bf55d
LP
218 break;
219 }
220
e8d23f92 221 (void) dns_stub_send(q->manager, q->request_dns_stream, q->request_dns_packet, q->reply_dns_packet);
b30bf55d 222 break;
51027656 223 }
b30bf55d
LP
224
225 case DNS_TRANSACTION_RCODE_FAILURE:
2b2d98c1 226 (void) dns_stub_send_failure(q->manager, q->request_dns_stream, q->request_dns_packet, q->answer_rcode, dns_query_fully_authenticated(q));
b30bf55d
LP
227 break;
228
229 case DNS_TRANSACTION_NOT_FOUND:
2b2d98c1 230 (void) dns_stub_send_failure(q->manager, q->request_dns_stream, q->request_dns_packet, DNS_RCODE_NXDOMAIN, dns_query_fully_authenticated(q));
b30bf55d
LP
231 break;
232
233 case DNS_TRANSACTION_TIMEOUT:
234 case DNS_TRANSACTION_ATTEMPTS_MAX_REACHED:
235 /* Propagate a timeout as a no packet, i.e. that the client also gets a timeout */
236 break;
237
238 case DNS_TRANSACTION_NO_SERVERS:
239 case DNS_TRANSACTION_INVALID_REPLY:
240 case DNS_TRANSACTION_ERRNO:
241 case DNS_TRANSACTION_ABORTED:
242 case DNS_TRANSACTION_DNSSEC_FAILED:
243 case DNS_TRANSACTION_NO_TRUST_ANCHOR:
244 case DNS_TRANSACTION_RR_TYPE_UNSUPPORTED:
245 case DNS_TRANSACTION_NETWORK_DOWN:
2b2d98c1 246 (void) dns_stub_send_failure(q->manager, q->request_dns_stream, q->request_dns_packet, DNS_RCODE_SERVFAIL, false);
b30bf55d
LP
247 break;
248
249 case DNS_TRANSACTION_NULL:
250 case DNS_TRANSACTION_PENDING:
251 case DNS_TRANSACTION_VALIDATING:
252 default:
253 assert_not_reached("Impossible state");
254 }
255
b30bf55d
LP
256 dns_query_free(q);
257}
258
259static int dns_stub_stream_complete(DnsStream *s, int error) {
260 assert(s);
261
b412af57
LP
262 log_debug_errno(error, "DNS TCP connection terminated, destroying queries: %m");
263
264 for (;;) {
265 DnsQuery *q;
266
267 q = set_first(s->queries);
268 if (!q)
269 break;
b30bf55d 270
b412af57
LP
271 dns_query_free(q);
272 }
b30bf55d 273
b412af57
LP
274 /* This drops the implicit ref we keep around since it was allocated, as incoming stub connections
275 * should be kept as long as the client wants to. */
276 dns_stream_unref(s);
b30bf55d
LP
277 return 0;
278}
279
280static void dns_stub_process_query(Manager *m, DnsStream *s, DnsPacket *p) {
281 DnsQuery *q = NULL;
282 int r;
283
284 assert(m);
285 assert(p);
286 assert(p->protocol == DNS_PROTOCOL_DNS);
287
b30bf55d
LP
288 if (in_addr_is_localhost(p->family, &p->sender) <= 0 ||
289 in_addr_is_localhost(p->family, &p->destination) <= 0) {
290 log_error("Got packet on unexpected IP range, refusing.");
2b2d98c1 291 dns_stub_send_failure(m, s, p, DNS_RCODE_SERVFAIL, false);
b30bf55d
LP
292 goto fail;
293 }
294
295 r = dns_packet_extract(p);
296 if (r < 0) {
297 log_debug_errno(r, "Failed to extract resources from incoming packet, ignoring packet: %m");
2b2d98c1 298 dns_stub_send_failure(m, s, p, DNS_RCODE_FORMERR, false);
b30bf55d
LP
299 goto fail;
300 }
301
302 if (!DNS_PACKET_VERSION_SUPPORTED(p)) {
303 log_debug("Got EDNS OPT field with unsupported version number.");
2b2d98c1 304 dns_stub_send_failure(m, s, p, DNS_RCODE_BADVERS, false);
b30bf55d
LP
305 goto fail;
306 }
307
308 if (dns_type_is_obsolete(p->question->keys[0]->type)) {
309 log_debug("Got message with obsolete key type, refusing.");
2b2d98c1 310 dns_stub_send_failure(m, s, p, DNS_RCODE_NOTIMP, false);
b30bf55d
LP
311 goto fail;
312 }
313
314 if (dns_type_is_zone_transer(p->question->keys[0]->type)) {
315 log_debug("Got request for zone transfer, refusing.");
2b2d98c1 316 dns_stub_send_failure(m, s, p, DNS_RCODE_NOTIMP, false);
b30bf55d
LP
317 goto fail;
318 }
319
320 if (!DNS_PACKET_RD(p)) {
321 /* If the "rd" bit is off (i.e. recursion was not requested), then refuse operation */
322 log_debug("Got request with recursion disabled, refusing.");
2b2d98c1 323 dns_stub_send_failure(m, s, p, DNS_RCODE_REFUSED, false);
b30bf55d
LP
324 goto fail;
325 }
326
327 if (DNS_PACKET_DO(p) && DNS_PACKET_CD(p)) {
328 log_debug("Got request with DNSSEC CD bit set, refusing.");
2b2d98c1 329 dns_stub_send_failure(m, s, p, DNS_RCODE_NOTIMP, false);
b30bf55d
LP
330 goto fail;
331 }
332
e8d23f92 333 r = dns_query_new(m, &q, p->question, p->question, 0, SD_RESOLVED_PROTOCOLS_ALL|SD_RESOLVED_NO_SEARCH);
b30bf55d
LP
334 if (r < 0) {
335 log_error_errno(r, "Failed to generate query object: %m");
2b2d98c1 336 dns_stub_send_failure(m, s, p, DNS_RCODE_SERVFAIL, false);
b30bf55d
LP
337 goto fail;
338 }
339
340 /* Request that the TTL is corrected by the cached time for this lookup, so that we return vaguely useful TTLs */
341 q->clamp_ttl = true;
342
343 q->request_dns_packet = dns_packet_ref(p);
344 q->request_dns_stream = dns_stream_ref(s); /* make sure the stream stays around until we can send a reply through it */
345 q->complete = dns_stub_query_complete;
346
347 if (s) {
b412af57
LP
348 /* Remember which queries belong to this stream, so that we can cancel them when the stream
349 * is disconnected early */
350
351 r = set_ensure_allocated(&s->queries, &trivial_hash_ops);
352 if (r < 0) {
353 log_oom();
354 goto fail;
355 }
356
357 if (set_put(s->queries, q) < 0) {
358 log_oom();
359 goto fail;
360 }
b30bf55d
LP
361 }
362
363 r = dns_query_go(q);
364 if (r < 0) {
365 log_error_errno(r, "Failed to start query: %m");
2b2d98c1 366 dns_stub_send_failure(m, s, p, DNS_RCODE_SERVFAIL, false);
b30bf55d
LP
367 goto fail;
368 }
369
52e63427 370 log_debug("Processing query...");
b30bf55d
LP
371 return;
372
373fail:
b30bf55d
LP
374 dns_query_free(q);
375}
376
377static int on_dns_stub_packet(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
378 _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
379 Manager *m = userdata;
380 int r;
381
382 r = manager_recv(m, fd, DNS_PROTOCOL_DNS, &p);
383 if (r <= 0)
384 return r;
385
386 if (dns_packet_validate_query(p) > 0) {
387 log_debug("Got DNS stub UDP query packet for id %u", DNS_PACKET_ID(p));
388
389 dns_stub_process_query(m, NULL, p);
390 } else
391 log_debug("Invalid DNS stub UDP packet, ignoring.");
392
393 return 0;
394}
395
424e490b 396static int manager_dns_stub_udp_fd(Manager *m) {
b30bf55d
LP
397 union sockaddr_union sa = {
398 .in.sin_family = AF_INET,
399 .in.sin_port = htobe16(53),
400 .in.sin_addr.s_addr = htobe32(INADDR_DNS_STUB),
401 };
424e490b 402 _cleanup_close_ int fd = -1;
b30bf55d
LP
403 int r;
404
405 if (m->dns_stub_udp_fd >= 0)
406 return m->dns_stub_udp_fd;
407
424e490b
ZJS
408 fd = socket(AF_INET, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
409 if (fd < 0)
b30bf55d
LP
410 return -errno;
411
2ff48e98
LP
412 r = setsockopt_int(fd, SOL_SOCKET, SO_REUSEADDR, true);
413 if (r < 0)
414 return r;
b30bf55d 415
2ff48e98
LP
416 r = setsockopt_int(fd, IPPROTO_IP, IP_PKTINFO, true);
417 if (r < 0)
418 return r;
b30bf55d 419
2ff48e98
LP
420 r = setsockopt_int(fd, IPPROTO_IP, IP_RECVTTL, true);
421 if (r < 0)
422 return r;
b30bf55d
LP
423
424 /* Make sure no traffic from outside the local host can leak to onto this socket */
953a02d1
LP
425 r = socket_bind_to_ifindex(fd, LOOPBACK_IFINDEX);
426 if (r < 0)
427 return r;
b30bf55d 428
424e490b
ZJS
429 if (bind(fd, &sa.sa, sizeof(sa.in)) < 0)
430 return -errno;
b30bf55d 431
424e490b 432 r = sd_event_add_io(m->event, &m->dns_stub_udp_event_source, fd, EPOLLIN, on_dns_stub_packet, m);
b30bf55d 433 if (r < 0)
424e490b 434 return r;
b30bf55d
LP
435
436 (void) sd_event_source_set_description(m->dns_stub_udp_event_source, "dns-stub-udp");
437
c10d6bdb 438 return m->dns_stub_udp_fd = TAKE_FD(fd);
b30bf55d
LP
439}
440
441static int on_dns_stub_stream_packet(DnsStream *s) {
aa337a5e
LP
442 _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
443
b30bf55d 444 assert(s);
b30bf55d 445
aa337a5e
LP
446 p = dns_stream_take_read_packet(s);
447 assert(p);
448
449 if (dns_packet_validate_query(p) > 0) {
450 log_debug("Got DNS stub TCP query packet for id %u", DNS_PACKET_ID(p));
b30bf55d 451
aa337a5e 452 dns_stub_process_query(s->manager, s, p);
b30bf55d
LP
453 } else
454 log_debug("Invalid DNS stub TCP packet, ignoring.");
455
b30bf55d
LP
456 return 0;
457}
458
459static int on_dns_stub_stream(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
460 DnsStream *stream;
461 Manager *m = userdata;
462 int cfd, r;
463
464 cfd = accept4(fd, NULL, NULL, SOCK_NONBLOCK|SOCK_CLOEXEC);
465 if (cfd < 0) {
4ff9bc2e 466 if (ERRNO_IS_ACCEPT_AGAIN(errno))
b30bf55d
LP
467 return 0;
468
469 return -errno;
470 }
471
652ba568 472 r = dns_stream_new(m, &stream, DNS_STREAM_STUB, DNS_PROTOCOL_DNS, cfd, NULL);
b30bf55d
LP
473 if (r < 0) {
474 safe_close(cfd);
475 return r;
476 }
477
478 stream->on_packet = on_dns_stub_stream_packet;
b412af57 479 stream->complete = dns_stub_stream_complete;
b30bf55d 480
b412af57 481 /* We let the reference to the stream dangle here, it will be dropped later by the complete callback. */
b30bf55d
LP
482
483 return 0;
484}
485
424e490b 486static int manager_dns_stub_tcp_fd(Manager *m) {
b30bf55d
LP
487 union sockaddr_union sa = {
488 .in.sin_family = AF_INET,
489 .in.sin_addr.s_addr = htobe32(INADDR_DNS_STUB),
490 .in.sin_port = htobe16(53),
491 };
424e490b 492 _cleanup_close_ int fd = -1;
b30bf55d
LP
493 int r;
494
495 if (m->dns_stub_tcp_fd >= 0)
496 return m->dns_stub_tcp_fd;
497
424e490b
ZJS
498 fd = socket(AF_INET, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
499 if (fd < 0)
b30bf55d
LP
500 return -errno;
501
2ff48e98
LP
502 r = setsockopt_int(fd, IPPROTO_IP, IP_TTL, true);
503 if (r < 0)
504 return r;
b30bf55d 505
2ff48e98
LP
506 r = setsockopt_int(fd, SOL_SOCKET, SO_REUSEADDR, true);
507 if (r < 0)
508 return r;
b30bf55d 509
2ff48e98
LP
510 r = setsockopt_int(fd, IPPROTO_IP, IP_PKTINFO, true);
511 if (r < 0)
512 return r;
b30bf55d 513
2ff48e98
LP
514 r = setsockopt_int(fd, IPPROTO_IP, IP_RECVTTL, true);
515 if (r < 0)
516 return r;
b30bf55d
LP
517
518 /* Make sure no traffic from outside the local host can leak to onto this socket */
953a02d1
LP
519 r = socket_bind_to_ifindex(fd, LOOPBACK_IFINDEX);
520 if (r < 0)
521 return r;
b30bf55d 522
424e490b
ZJS
523 if (bind(fd, &sa.sa, sizeof(sa.in)) < 0)
524 return -errno;
b30bf55d 525
424e490b
ZJS
526 if (listen(fd, SOMAXCONN) < 0)
527 return -errno;
b30bf55d 528
424e490b 529 r = sd_event_add_io(m->event, &m->dns_stub_tcp_event_source, fd, EPOLLIN, on_dns_stub_stream, m);
b30bf55d 530 if (r < 0)
424e490b 531 return r;
b30bf55d
LP
532
533 (void) sd_event_source_set_description(m->dns_stub_tcp_event_source, "dns-stub-tcp");
534
c10d6bdb 535 return m->dns_stub_tcp_fd = TAKE_FD(fd);
b30bf55d
LP
536}
537
538int manager_dns_stub_start(Manager *m) {
424e490b 539 const char *t = "UDP";
01b0669e 540 int r = 0;
b30bf55d
LP
541
542 assert(m);
543
d5da7707
ZJS
544 if (m->dns_stub_listener_mode == DNS_STUB_LISTENER_NO)
545 log_debug("Not creating stub listener.");
546 else
547 log_debug("Creating stub listener using %s.",
548 m->dns_stub_listener_mode == DNS_STUB_LISTENER_UDP ? "UDP" :
549 m->dns_stub_listener_mode == DNS_STUB_LISTENER_TCP ? "TCP" :
550 "UDP/TCP");
551
424e490b 552 if (IN_SET(m->dns_stub_listener_mode, DNS_STUB_LISTENER_YES, DNS_STUB_LISTENER_UDP))
1ae43295 553 r = manager_dns_stub_udp_fd(m);
b30bf55d 554
424e490b
ZJS
555 if (r >= 0 &&
556 IN_SET(m->dns_stub_listener_mode, DNS_STUB_LISTENER_YES, DNS_STUB_LISTENER_TCP)) {
557 t = "TCP";
1ae43295 558 r = manager_dns_stub_tcp_fd(m);
1ae43295 559 }
b30bf55d 560
0f4db364
ZJS
561 if (IN_SET(r, -EADDRINUSE, -EPERM)) {
562 if (r == -EADDRINUSE)
563 log_warning_errno(r,
564 "Another process is already listening on %s socket 127.0.0.53:53.\n"
565 "Turning off local DNS stub support.", t);
566 else
567 log_warning_errno(r,
568 "Failed to listen on %s socket 127.0.0.53:53: %m.\n"
569 "Turning off local DNS stub support.", t);
424e490b
ZJS
570 manager_dns_stub_stop(m);
571 } else if (r < 0)
572 return log_error_errno(r, "Failed to listen on %s socket 127.0.0.53:53: %m", t);
b30bf55d
LP
573
574 return 0;
575}
576
577void manager_dns_stub_stop(Manager *m) {
578 assert(m);
579
580 m->dns_stub_udp_event_source = sd_event_source_unref(m->dns_stub_udp_event_source);
581 m->dns_stub_tcp_event_source = sd_event_source_unref(m->dns_stub_tcp_event_source);
582
583 m->dns_stub_udp_fd = safe_close(m->dns_stub_udp_fd);
584 m->dns_stub_tcp_fd = safe_close(m->dns_stub_tcp_fd);
585}