1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
5 #include <linux/netlink.h>
6 #include <linux/if_ether.h>
7 #include <linux/if_infiniband.h>
8 #include <linux/if_packet.h>
9 #include <netinet/in.h>
13 #include <sys/socket.h>
14 #include <sys/types.h>
17 #include "errno-util.h"
18 #include "in-addr-util.h"
20 #include "missing_network.h"
21 #include "missing_socket.h"
22 #include "sparse-endian.h"
24 union sockaddr_union
{
25 /* The minimal, abstract version */
28 /* The libc provided version that allocates "enough room" for every protocol */
29 struct sockaddr_storage storage
;
31 /* Protoctol-specific implementations */
32 struct sockaddr_in in
;
33 struct sockaddr_in6 in6
;
34 struct sockaddr_un un
;
35 struct sockaddr_nl nl
;
36 struct sockaddr_ll ll
;
37 struct sockaddr_vm vm
;
39 /* Ensure there is enough space to store Infiniband addresses */
40 uint8_t ll_buffer
[offsetof(struct sockaddr_ll
, sll_addr
) + CONST_MAX(ETH_ALEN
, INFINIBAND_ALEN
)];
42 /* Ensure there is enough space after the AF_UNIX sun_path for one more NUL byte, just to be sure that the path
43 * component is always followed by at least one NUL byte. */
44 uint8_t un_buffer
[sizeof(struct sockaddr_un
) + 1];
47 #define SUN_PATH_LEN (sizeof(((struct sockaddr_un){}).sun_path))
49 typedef struct SocketAddress
{
50 union sockaddr_union sockaddr
;
52 /* We store the size here explicitly due to the weird
53 * sockaddr_un semantics for abstract sockets */
56 /* Socket type, i.e. SOCK_STREAM, SOCK_DGRAM, ... */
59 /* Socket protocol, IPPROTO_xxx, usually 0, except for netlink */
63 typedef enum SocketAddressBindIPv6Only
{
64 SOCKET_ADDRESS_DEFAULT
,
66 SOCKET_ADDRESS_IPV6_ONLY
,
67 _SOCKET_ADDRESS_BIND_IPV6_ONLY_MAX
,
68 _SOCKET_ADDRESS_BIND_IPV6_ONLY_INVALID
= -EINVAL
,
69 } SocketAddressBindIPv6Only
;
71 #define socket_address_family(a) ((a)->sockaddr.sa.sa_family)
73 const char* socket_address_type_to_string(int t
) _const_
;
74 int socket_address_type_from_string(const char *s
) _pure_
;
76 int sockaddr_un_unlink(const struct sockaddr_un
*sa
);
78 static inline int socket_address_unlink(const SocketAddress
*a
) {
79 return socket_address_family(a
) == AF_UNIX
? sockaddr_un_unlink(&a
->sockaddr
.un
) : 0;
82 bool socket_address_can_accept(const SocketAddress
*a
) _pure_
;
84 int socket_address_listen(
85 const SocketAddress
*a
,
88 SocketAddressBindIPv6Only only
,
89 const char *bind_to_device
,
93 mode_t directory_mode
,
97 int socket_address_verify(const SocketAddress
*a
, bool strict
) _pure_
;
98 int socket_address_print(const SocketAddress
*a
, char **p
);
99 bool socket_address_matches_fd(const SocketAddress
*a
, int fd
);
101 bool socket_address_equal(const SocketAddress
*a
, const SocketAddress
*b
) _pure_
;
103 const char* socket_address_get_path(const SocketAddress
*a
);
105 bool socket_ipv6_is_supported(void);
106 bool socket_ipv6_is_enabled(void);
108 int sockaddr_port(const struct sockaddr
*_sa
, unsigned *port
);
109 const union in_addr_union
*sockaddr_in_addr(const struct sockaddr
*sa
);
110 int sockaddr_set_in_addr(union sockaddr_union
*u
, int family
, const union in_addr_union
*a
, uint16_t port
);
112 int sockaddr_pretty(const struct sockaddr
*_sa
, socklen_t salen
, bool translate_ipv6
, bool include_port
, char **ret
);
113 int getpeername_pretty(int fd
, bool include_port
, char **ret
);
114 int getsockname_pretty(int fd
, char **ret
);
116 int socknameinfo_pretty(union sockaddr_union
*sa
, socklen_t salen
, char **_ret
);
118 const char* socket_address_bind_ipv6_only_to_string(SocketAddressBindIPv6Only b
) _const_
;
119 SocketAddressBindIPv6Only
socket_address_bind_ipv6_only_from_string(const char *s
) _pure_
;
120 SocketAddressBindIPv6Only
socket_address_bind_ipv6_only_or_bool_from_string(const char *s
);
122 int netlink_family_to_string_alloc(int b
, char **s
);
123 int netlink_family_from_string(const char *s
) _pure_
;
125 bool sockaddr_equal(const union sockaddr_union
*a
, const union sockaddr_union
*b
);
127 int fd_set_sndbuf(int fd
, size_t n
, bool increase
);
128 static inline int fd_inc_sndbuf(int fd
, size_t n
) {
129 return fd_set_sndbuf(fd
, n
, true);
131 int fd_set_rcvbuf(int fd
, size_t n
, bool increase
);
132 static inline int fd_increase_rxbuf(int fd
, size_t n
) {
133 return fd_set_rcvbuf(fd
, n
, true);
136 int ip_tos_to_string_alloc(int i
, char **s
);
137 int ip_tos_from_string(const char *s
);
140 IFNAME_VALID_ALTERNATIVE
= 1 << 0, /* Allow "altnames" too */
141 IFNAME_VALID_NUMERIC
= 1 << 1, /* Allow decimal formatted ifindexes too */
142 IFNAME_VALID_SPECIAL
= 1 << 2, /* Allow the special names "all" and "default" */
143 _IFNAME_VALID_ALL
= IFNAME_VALID_ALTERNATIVE
| IFNAME_VALID_NUMERIC
| IFNAME_VALID_SPECIAL
,
145 bool ifname_valid_char(char a
);
146 bool ifname_valid_full(const char *p
, IfnameValidFlags flags
);
147 static inline bool ifname_valid(const char *p
) {
148 return ifname_valid_full(p
, 0);
150 bool address_label_valid(const char *p
);
152 int getpeercred(int fd
, struct ucred
*ucred
);
153 int getpeersec(int fd
, char **ret
);
154 int getpeergroups(int fd
, gid_t
**ret
);
156 ssize_t
send_one_fd_iov_sa(
159 const struct iovec
*iov
, size_t iovlen
,
160 const struct sockaddr
*sa
, socklen_t len
,
162 int send_one_fd_sa(int transport_fd
,
164 const struct sockaddr
*sa
, socklen_t len
,
166 #define send_one_fd_iov(transport_fd, fd, iov, iovlen, flags) send_one_fd_iov_sa(transport_fd, fd, iov, iovlen, NULL, 0, flags)
167 #define send_one_fd(transport_fd, fd, flags) send_one_fd_iov_sa(transport_fd, fd, NULL, 0, NULL, 0, flags)
168 ssize_t
receive_one_fd_iov(int transport_fd
, struct iovec
*iov
, size_t iovlen
, int flags
, int *ret_fd
);
169 int receive_one_fd(int transport_fd
, int flags
);
171 ssize_t
next_datagram_size_fd(int fd
);
173 int flush_accept(int fd
);
175 #define CMSG_FOREACH(cmsg, mh) \
176 for ((cmsg) = CMSG_FIRSTHDR(mh); (cmsg); (cmsg) = CMSG_NXTHDR((mh), (cmsg)))
178 struct cmsghdr
* cmsg_find(struct msghdr
*mh
, int level
, int type
, socklen_t length
);
180 /* Type-safe, dereferencing version of cmsg_find() */
181 #define CMSG_FIND_DATA(mh, level, type, ctype) \
183 struct cmsghdr *_found; \
184 _found = cmsg_find(mh, level, type, CMSG_LEN(sizeof(ctype))); \
185 (ctype*) (_found ? CMSG_DATA(_found) : NULL); \
188 /* Resolves to a type that can carry cmsghdr structures. Make sure things are properly aligned, i.e. the type
189 * itself is placed properly in memory and the size is also aligned to what's appropriate for "cmsghdr"
191 #define CMSG_BUFFER_TYPE(size) \
193 struct cmsghdr cmsghdr; \
195 uint8_t align_check[(size) >= CMSG_SPACE(0) && \
196 (size) == CMSG_ALIGN(size) ? 1 : -1]; \
200 * Certain hardware address types (e.g Infiniband) do not fit into sll_addr
201 * (8 bytes) and run over the structure. This macro returns the correct size that
202 * must be passed to kernel.
204 #define SOCKADDR_LL_LEN(sa) \
206 const struct sockaddr_ll *_sa = &(sa); \
207 size_t _mac_len = sizeof(_sa->sll_addr); \
208 assert(_sa->sll_family == AF_PACKET); \
209 if (be16toh(_sa->sll_hatype) == ARPHRD_ETHER) \
210 _mac_len = MAX(_mac_len, (size_t) ETH_ALEN); \
211 if (be16toh(_sa->sll_hatype) == ARPHRD_INFINIBAND) \
212 _mac_len = MAX(_mac_len, (size_t) INFINIBAND_ALEN); \
213 offsetof(struct sockaddr_ll, sll_addr) + _mac_len; \
216 /* Covers only file system and abstract AF_UNIX socket addresses, but not unnamed socket addresses. */
217 #define SOCKADDR_UN_LEN(sa) \
219 const struct sockaddr_un *_sa = &(sa); \
220 assert(_sa->sun_family == AF_UNIX); \
221 offsetof(struct sockaddr_un, sun_path) + \
222 (_sa->sun_path[0] == 0 ? \
223 1 + strnlen(_sa->sun_path+1, sizeof(_sa->sun_path)-1) : \
224 strnlen(_sa->sun_path, sizeof(_sa->sun_path))+1); \
227 #define SOCKADDR_LEN(saddr) \
229 const union sockaddr_union *__sa = &(saddr); \
231 switch (__sa->sa.sa_family) { \
233 _len = sizeof(struct sockaddr_in); \
236 _len = sizeof(struct sockaddr_in6); \
239 _len = SOCKADDR_UN_LEN(__sa->un); \
242 _len = SOCKADDR_LL_LEN(__sa->ll); \
245 _len = sizeof(struct sockaddr_nl); \
248 _len = sizeof(struct sockaddr_vm); \
251 assert_not_reached(); \
256 int socket_ioctl_fd(void);
258 int sockaddr_un_set_path(struct sockaddr_un
*ret
, const char *path
);
260 static inline int setsockopt_int(int fd
, int level
, int optname
, int value
) {
261 if (setsockopt(fd
, level
, optname
, &value
, sizeof(value
)) < 0)
267 static inline int getsockopt_int(int fd
, int level
, int optname
, int *ret
) {
269 socklen_t sl
= sizeof(v
);
271 if (getsockopt(fd
, level
, optname
, &v
, &sl
) < 0)
272 return negative_errno();
280 int socket_bind_to_ifname(int fd
, const char *ifname
);
281 int socket_bind_to_ifindex(int fd
, int ifindex
);
283 /* Define a 64bit version of timeval/timespec in any case, even on 32bit userspace. */
284 struct timeval_large
{
285 uint64_t tvl_sec
, tvl_usec
;
287 struct timespec_large
{
288 uint64_t tvl_sec
, tvl_nsec
;
291 /* glibc duplicates timespec/timeval on certain 32bit archs, once in 32bit and once in 64bit.
292 * See __convert_scm_timestamps() in glibc source code. Hence, we need additional buffer space for them
293 * to prevent from recvmsg_safe() returning -EXFULL. */
294 #define CMSG_SPACE_TIMEVAL \
295 ((sizeof(struct timeval) == sizeof(struct timeval_large)) ? \
296 CMSG_SPACE(sizeof(struct timeval)) : \
297 CMSG_SPACE(sizeof(struct timeval)) + \
298 CMSG_SPACE(sizeof(struct timeval_large)))
299 #define CMSG_SPACE_TIMESPEC \
300 ((sizeof(struct timespec) == sizeof(struct timespec_large)) ? \
301 CMSG_SPACE(sizeof(struct timespec)) : \
302 CMSG_SPACE(sizeof(struct timespec)) + \
303 CMSG_SPACE(sizeof(struct timespec_large)))
305 ssize_t
recvmsg_safe(int sockfd
, struct msghdr
*msg
, int flags
);
307 int socket_get_family(int fd
, int *ret
);
308 int socket_set_recvpktinfo(int fd
, int af
, bool b
);
309 int socket_set_unicast_if(int fd
, int af
, int ifi
);
311 int socket_set_option(int fd
, int af
, int opt_ipv4
, int opt_ipv6
, int val
);
312 static inline int socket_set_recverr(int fd
, int af
, bool b
) {
313 return socket_set_option(fd
, af
, IP_RECVERR
, IPV6_RECVERR
, b
);
315 static inline int socket_set_recvttl(int fd
, int af
, bool b
) {
316 return socket_set_option(fd
, af
, IP_RECVTTL
, IPV6_RECVHOPLIMIT
, b
);
318 static inline int socket_set_ttl(int fd
, int af
, int ttl
) {
319 return socket_set_option(fd
, af
, IP_TTL
, IPV6_UNICAST_HOPS
, ttl
);
321 static inline int socket_set_freebind(int fd
, int af
, bool b
) {
322 return socket_set_option(fd
, af
, IP_FREEBIND
, IPV6_FREEBIND
, b
);
324 static inline int socket_set_transparent(int fd
, int af
, bool b
) {
325 return socket_set_option(fd
, af
, IP_TRANSPARENT
, IPV6_TRANSPARENT
, b
);
327 static inline int socket_set_recvfragsize(int fd
, int af
, bool b
) {
328 return socket_set_option(fd
, af
, IP_RECVFRAGSIZE
, IPV6_RECVFRAGSIZE
, b
);
331 int socket_get_mtu(int fd
, int af
, size_t *ret
);
333 /* an initializer for struct ucred that initialized all fields to the invalid value appropriate for each */
334 #define UCRED_INVALID { .pid = 0, .uid = UID_INVALID, .gid = GID_INVALID }
336 int connect_unix_path(int fd
, int dir_fd
, const char *path
);