Skip to content

Commit b850e51

Browse files
committed
resolved: also use TCP tweaks on LLMNR (plus unify setsockopt() code)
1 parent 8624f12 commit b850e51

File tree

1 file changed

+65
-39
lines changed

1 file changed

+65
-39
lines changed

src/resolve/resolved-llmnr.c

Lines changed: 65 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
/* SPDX-License-Identifier: LGPL-2.1-or-later */
22

33
#include <netinet/in.h>
4+
#include <netinet/tcp.h>
45
#include <resolv.h>
56

67
#include "errno-util.h"
@@ -111,6 +112,31 @@ static int on_llmnr_packet(sd_event_source *s, int fd, uint32_t revents, void *u
111112
return 0;
112113
}
113114

115+
static int set_llmnr_common_socket_options(int fd, int family) {
116+
int r;
117+
118+
r = socket_set_recvpktinfo(fd, family, true);
119+
if (r < 0)
120+
return r;
121+
122+
r = socket_set_recvttl(fd, family, true);
123+
if (r < 0)
124+
return r;
125+
126+
return 0;
127+
}
128+
129+
static int set_llmnr_common_udp_socket_options(int fd, int family) {
130+
int r;
131+
132+
/* RFC 4795, section 2.5 recommends setting the TTL of UDP packets to 255. */
133+
r = socket_set_ttl(fd, family, 255);
134+
if (r < 0)
135+
return r;
136+
137+
return 0;
138+
}
139+
114140
int manager_llmnr_ipv4_udp_fd(Manager *m) {
115141
union sockaddr_union sa = {
116142
.in.sin_family = AF_INET,
@@ -128,10 +154,13 @@ int manager_llmnr_ipv4_udp_fd(Manager *m) {
128154
if (s < 0)
129155
return log_error_errno(errno, "LLMNR-IPv4(UDP): Failed to create socket: %m");
130156

131-
/* RFC 4795, section 2.5 recommends setting the TTL of UDP packets to 255. */
132-
r = setsockopt_int(s, IPPROTO_IP, IP_TTL, 255);
157+
r = set_llmnr_common_socket_options(s, AF_INET);
158+
if (r < 0)
159+
return log_error_errno(r, "LLMNR-IPv4(UDP): Failed to set common socket options: %m");
160+
161+
r = set_llmnr_common_udp_socket_options(s, AF_INET);
133162
if (r < 0)
134-
return log_error_errno(r, "LLMNR-IPv4(UDP): Failed to set IP_TTL: %m");
163+
return log_error_errno(r, "LLMNR-IPv4(UDP): Failed to set common UDP socket options: %m");
135164

136165
r = setsockopt_int(s, IPPROTO_IP, IP_MULTICAST_TTL, 255);
137166
if (r < 0)
@@ -141,14 +170,6 @@ int manager_llmnr_ipv4_udp_fd(Manager *m) {
141170
if (r < 0)
142171
return log_error_errno(r, "LLMNR-IPv4(UDP): Failed to set IP_MULTICAST_LOOP: %m");
143172

144-
r = setsockopt_int(s, IPPROTO_IP, IP_PKTINFO, true);
145-
if (r < 0)
146-
return log_error_errno(r, "LLMNR-IPv4(UDP): Failed to set IP_PKTINFO: %m");
147-
148-
r = setsockopt_int(s, IPPROTO_IP, IP_RECVTTL, true);
149-
if (r < 0)
150-
return log_error_errno(r, "LLMNR-IPv4(UDP): Failed to set IP_RECVTTL: %m");
151-
152173
/* Disable Don't-Fragment bit in the IP header */
153174
r = setsockopt_int(s, IPPROTO_IP, IP_MTU_DISCOVER, IP_PMTUDISC_DONT);
154175
if (r < 0)
@@ -203,9 +224,13 @@ int manager_llmnr_ipv6_udp_fd(Manager *m) {
203224
if (s < 0)
204225
return log_error_errno(errno, "LLMNR-IPv6(UDP): Failed to create socket: %m");
205226

206-
r = setsockopt_int(s, IPPROTO_IPV6, IPV6_UNICAST_HOPS, 255);
227+
r = set_llmnr_common_socket_options(s, AF_INET6);
228+
if (r < 0)
229+
return log_error_errno(r, "LLMNR-IPv6(UDP): Failed to set common socket options: %m");
230+
231+
r = set_llmnr_common_udp_socket_options(s, AF_INET6);
207232
if (r < 0)
208-
return log_error_errno(r, "LLMNR-IPv6(UDP): Failed to set IPV6_UNICAST_HOPS: %m");
233+
return log_error_errno(r, "LLMNR-IPv6(UDP): Failed to set common UDP socket options: %m");
209234

210235
/* RFC 4795, section 2.5 recommends setting the TTL of UDP packets to 255. */
211236
r = setsockopt_int(s, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, 255);
@@ -220,14 +245,6 @@ int manager_llmnr_ipv6_udp_fd(Manager *m) {
220245
if (r < 0)
221246
return log_error_errno(r, "LLMNR-IPv6(UDP): Failed to set IPV6_V6ONLY: %m");
222247

223-
r = setsockopt_int(s, IPPROTO_IPV6, IPV6_RECVPKTINFO, true);
224-
if (r < 0)
225-
return log_error_errno(r, "LLMNR-IPv6(UDP): Failed to set IPV6_RECVPKTINFO: %m");
226-
227-
r = setsockopt_int(s, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, true);
228-
if (r < 0)
229-
return log_error_errno(r, "LLMNR-IPv6(UDP): Failed to set IPV6_RECVHOPLIMIT: %m");
230-
231248
/* first try to bind without SO_REUSEADDR to detect another LLMNR responder */
232249
r = bind(s, &sa.sa, sizeof(sa.in6));
233250
if (r < 0) {
@@ -308,6 +325,25 @@ static int on_llmnr_stream(sd_event_source *s, int fd, uint32_t revents, void *u
308325
return 0;
309326
}
310327

328+
static int set_llmnr_common_tcp_socket_options(int fd, int family) {
329+
int r;
330+
331+
/* RFC 4795, section 2.5. requires setting the TTL of TCP streams to 1 */
332+
r = socket_set_ttl(fd, family, 1);
333+
if (r < 0)
334+
return r;
335+
336+
r = setsockopt_int(fd, IPPROTO_TCP, TCP_FASTOPEN, 5); /* Everybody appears to pick qlen=5, let's do the same here. */
337+
if (r < 0)
338+
log_debug_errno(r, "Failed to enable TCP_FASTOPEN on TCP listening socket, ignoring: %m");
339+
340+
r = setsockopt_int(fd, IPPROTO_TCP, TCP_NODELAY, true);
341+
if (r < 0)
342+
log_debug_errno(r, "Failed to enable TCP_NODELAY mode, ignoring: %m");
343+
344+
return 0;
345+
}
346+
311347
int manager_llmnr_ipv4_tcp_fd(Manager *m) {
312348
union sockaddr_union sa = {
313349
.in.sin_family = AF_INET,
@@ -325,18 +361,13 @@ int manager_llmnr_ipv4_tcp_fd(Manager *m) {
325361
if (s < 0)
326362
return log_error_errno(errno, "LLMNR-IPv4(TCP): Failed to create socket: %m");
327363

328-
/* RFC 4795, section 2.5. requires setting the TTL of TCP streams to 1 */
329-
r = setsockopt_int(s, IPPROTO_IP, IP_TTL, 1);
330-
if (r < 0)
331-
return log_error_errno(r, "LLMNR-IPv4(TCP): Failed to set IP_TTL: %m");
332-
333-
r = setsockopt_int(s, IPPROTO_IP, IP_PKTINFO, true);
364+
r = set_llmnr_common_socket_options(s, AF_INET);
334365
if (r < 0)
335-
return log_error_errno(r, "LLMNR-IPv4(TCP): Failed to set IP_PKTINFO: %m");
366+
return log_error_errno(r, "LLMNR-IPv4(TCP): Failed to set common socket options: %m");
336367

337-
r = setsockopt_int(s, IPPROTO_IP, IP_RECVTTL, true);
368+
r = set_llmnr_common_tcp_socket_options(s, AF_INET);
338369
if (r < 0)
339-
return log_error_errno(r, "LLMNR-IPv4(TCP): Failed to set IP_RECVTTL: %m");
370+
return log_error_errno(r, "LLMNR-IPv4(TCP): Failed to set common TCP socket options: %m");
340371

341372
/* Disable Don't-Fragment bit in the IP header */
342373
r = setsockopt_int(s, IPPROTO_IP, IP_MTU_DISCOVER, IP_PMTUDISC_DONT);
@@ -396,22 +427,17 @@ int manager_llmnr_ipv6_tcp_fd(Manager *m) {
396427
if (s < 0)
397428
return log_error_errno(errno, "LLMNR-IPv6(TCP): Failed to create socket: %m");
398429

399-
/* RFC 4795, section 2.5. requires setting the TTL of TCP streams to 1 */
400-
r = setsockopt_int(s, IPPROTO_IPV6, IPV6_UNICAST_HOPS, 1);
401-
if (r < 0)
402-
return log_error_errno(r, "LLMNR-IPv6(TCP): Failed to set IPV6_UNICAST_HOPS: %m");
403-
404430
r = setsockopt_int(s, IPPROTO_IPV6, IPV6_V6ONLY, true);
405431
if (r < 0)
406432
return log_error_errno(r, "LLMNR-IPv6(TCP): Failed to set IPV6_V6ONLY: %m");
407433

408-
r = setsockopt_int(s, IPPROTO_IPV6, IPV6_RECVPKTINFO, true);
434+
r = set_llmnr_common_socket_options(s, AF_INET6);
409435
if (r < 0)
410-
return log_error_errno(r, "LLMNR-IPv6(TCP): Failed to set IPV6_RECVPKTINFO: %m");
436+
return log_error_errno(r, "LLMNR-IPv6(TCP): Failed to set common socket options: %m");
411437

412-
r = setsockopt_int(s, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, true);
438+
r = set_llmnr_common_tcp_socket_options(s, AF_INET6);
413439
if (r < 0)
414-
return log_error_errno(r, "LLMNR-IPv6(TCP): Failed to set IPV6_RECVHOPLIMIT: %m");
440+
return log_error_errno(r, "LLMNR-IPv6(TCP): Failed to set common TCP socket options: %m");
415441

416442
/* first try to bind without SO_REUSEADDR to detect another LLMNR responder */
417443
r = bind(s, &sa.sa, sizeof(sa.in6));

0 commit comments

Comments
 (0)