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 int flag
= only
== SOCKET_ADDRESS_IPV6_ONLY
;
67 if (setsockopt(fd
, IPPROTO_IPV6
, IPV6_V6ONLY
, &flag
, sizeof(flag
)) < 0)
71 if (IN_SET(socket_address_family(a
), AF_INET
, AF_INET6
)) {
73 if (setsockopt(fd
, SOL_SOCKET
, SO_BINDTODEVICE
, bind_to_device
, strlen(bind_to_device
)+1) < 0)
78 if (setsockopt(fd
, SOL_SOCKET
, SO_REUSEPORT
, &one
, sizeof(one
)) < 0)
79 log_warning_errno(errno
, "SO_REUSEPORT failed: %m");
84 if (setsockopt(fd
, IPPROTO_IP
, IP_FREEBIND
, &one
, sizeof(one
)) < 0)
85 log_warning_errno(errno
, "IP_FREEBIND failed: %m");
90 if (setsockopt(fd
, IPPROTO_IP
, IP_TRANSPARENT
, &one
, sizeof(one
)) < 0)
91 log_warning_errno(errno
, "IP_TRANSPARENT failed: %m");
96 if (setsockopt(fd
, SOL_SOCKET
, SO_REUSEADDR
, &one
, sizeof(one
)) < 0)
99 p
= socket_address_get_path(a
);
102 (void) mkdir_parents_label(p
, directory_mode
);
104 /* Enforce the right access mode for the socket */
105 RUN_WITH_UMASK(~socket_mode
) {
106 r
= mac_selinux_bind(fd
, &a
->sockaddr
.sa
, a
->size
);
107 if (r
== -EADDRINUSE
) {
108 /* Unlink and try again */
111 return r
; /* didn't work, return original error */
113 r
= mac_selinux_bind(fd
, &a
->sockaddr
.sa
, a
->size
);
119 if (bind(fd
, &a
->sockaddr
.sa
, a
->size
) < 0)
123 if (socket_address_can_accept(a
))
124 if (listen(fd
, backlog
) < 0)
127 /* Let's trigger an inotify event on the socket node, so that anyone waiting for this socket to be connectable
138 int make_socket_fd(int log_level
, const char* address
, int type
, int flags
) {
142 r
= socket_address_parse(&a
, address
);
144 return log_error_errno(r
, "Failed to parse socket address \"%s\": %m", address
);
148 fd
= socket_address_listen(&a
, type
| flags
, SOMAXCONN
, SOCKET_ADDRESS_DEFAULT
,
149 NULL
, false, false, false, 0755, 0644, NULL
);
150 if (fd
< 0 || log_get_max_level() >= log_level
) {
151 _cleanup_free_
char *p
= NULL
;
153 r
= socket_address_print(&a
, &p
);
155 return log_error_errno(r
, "socket_address_print(): %m");
158 log_error_errno(fd
, "Failed to listen on %s: %m", p
);
160 log_full(log_level
, "Listening on %s", p
);