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+
114140int 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+
311347int 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