1 /* SPDX-License-Identifier: LGPL-2.1+ */
4 #include <netinet/in.h>
8 #include <sys/socket.h>
12 #include "alloc-util.h"
19 #include "selinux-util.h"
20 #include "socket-util.h"
21 #include "umask-util.h"
23 int socket_address_listen(
24 const SocketAddress
*a
,
27 SocketAddressBindIPv6Only only
,
28 const char *bind_to_device
,
32 mode_t directory_mode
,
36 _cleanup_close_
int fd
= -1;
42 r
= socket_address_verify(a
);
46 if (socket_address_family(a
) == AF_INET6
&& !socket_ipv6_is_supported())
50 r
= mac_selinux_create_socket_prepare(label
);
55 fd
= socket(socket_address_family(a
), a
->type
| flags
, a
->protocol
);
56 r
= fd
< 0 ? -errno
: 0;
59 mac_selinux_create_socket_clear();
64 if (socket_address_family(a
) == AF_INET6
&& only
!= SOCKET_ADDRESS_DEFAULT
) {
65 r
= setsockopt_int(fd
, IPPROTO_IPV6
, IPV6_V6ONLY
, only
== SOCKET_ADDRESS_IPV6_ONLY
);
70 if (IN_SET(socket_address_family(a
), AF_INET
, AF_INET6
)) {
72 if (setsockopt(fd
, SOL_SOCKET
, SO_BINDTODEVICE
, bind_to_device
, strlen(bind_to_device
)+1) < 0)
76 r
= setsockopt_int(fd
, SOL_SOCKET
, SO_REUSEPORT
, true);
78 log_warning_errno(r
, "SO_REUSEPORT failed: %m");
82 r
= setsockopt_int(fd
, IPPROTO_IP
, IP_FREEBIND
, true);
84 log_warning_errno(r
, "IP_FREEBIND failed: %m");
88 r
= setsockopt_int(fd
, IPPROTO_IP
, IP_TRANSPARENT
, true);
90 log_warning_errno(r
, "IP_TRANSPARENT failed: %m");
94 r
= setsockopt_int(fd
, SOL_SOCKET
, SO_REUSEADDR
, true);
98 p
= socket_address_get_path(a
);
101 (void) mkdir_parents_label(p
, directory_mode
);
103 /* Enforce the right access mode for the socket */
104 RUN_WITH_UMASK(~socket_mode
) {
105 r
= mac_selinux_bind(fd
, &a
->sockaddr
.sa
, a
->size
);
106 if (r
== -EADDRINUSE
) {
107 /* Unlink and try again */
110 return r
; /* didn't work, return original error */
112 r
= mac_selinux_bind(fd
, &a
->sockaddr
.sa
, a
->size
);
118 if (bind(fd
, &a
->sockaddr
.sa
, a
->size
) < 0)
122 if (socket_address_can_accept(a
))
123 if (listen(fd
, backlog
) < 0)
126 /* Let's trigger an inotify event on the socket node, so that anyone waiting for this socket to be connectable
137 int make_socket_fd(int log_level
, const char* address
, int type
, int flags
) {
141 r
= socket_address_parse(&a
, address
);
143 return log_error_errno(r
, "Failed to parse socket address \"%s\": %m", address
);
147 fd
= socket_address_listen(&a
, type
| flags
, SOMAXCONN
, SOCKET_ADDRESS_DEFAULT
,
148 NULL
, false, false, false, 0755, 0644, NULL
);
149 if (fd
< 0 || log_get_max_level() >= log_level
) {
150 _cleanup_free_
char *p
= NULL
;
152 r
= socket_address_print(&a
, &p
);
154 return log_error_errno(r
, "socket_address_print(): %m");
157 log_error_errno(fd
, "Failed to listen on %s: %m", p
);
159 log_full(log_level
, "Listening on %s", p
);