]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/basic/socket-util.h
logind: Don't match non-leader processes for utmp TTY determination (#38027)
[thirdparty/systemd.git] / src / basic / socket-util.h
CommitLineData
db9ecf05 1/* SPDX-License-Identifier: LGPL-2.1-or-later */
c2f1db8f 2#pragma once
42f4e3c4 3
8f815e8b 4#include <linux/if_ether.h>
ef118d00
YW
5#include <linux/if_infiniband.h>
6#include <linux/if_packet.h>
85fd8df0 7#include <linux/netlink.h>
85fd8df0 8#include <linux/vm_sockets.h>
71d35b6b 9#include <netinet/in.h>
0dc09ccb 10#include <sys/socket.h>
42f4e3c4
LP
11#include <sys/un.h>
12
0c15577a
DDM
13#include "forward.h"
14#include "memory-util.h"
402506ce 15#include "missing_network.h"
ef118d00 16#include "missing_socket.h"
42f4e3c4 17
f6144808 18union sockaddr_union {
8b7f989a 19 /* The minimal, abstract version */
f6144808 20 struct sockaddr sa;
8b7f989a
LP
21
22 /* The libc provided version that allocates "enough room" for every protocol */
23 struct sockaddr_storage storage;
24
2053182b 25 /* Protocol-specific implementations */
4d49b48c 26 struct sockaddr_in in;
f6144808
LP
27 struct sockaddr_in6 in6;
28 struct sockaddr_un un;
7a22745a 29 struct sockaddr_nl nl;
e88bc795 30 struct sockaddr_ll ll;
0fc0f14b 31 struct sockaddr_vm vm;
8b7f989a 32
b1f24b75
BG
33 /* Ensure there is enough space to store Infiniband addresses */
34 uint8_t ll_buffer[offsetof(struct sockaddr_ll, sll_addr) + CONST_MAX(ETH_ALEN, INFINIBAND_ALEN)];
8b7f989a
LP
35
36 /* Ensure there is enough space after the AF_UNIX sun_path for one more NUL byte, just to be sure that the path
37 * component is always followed by at least one NUL byte. */
38 uint8_t un_buffer[sizeof(struct sockaddr_un) + 1];
f6144808
LP
39};
40
5c3fa98d
ZJS
41#define SUN_PATH_LEN (sizeof(((struct sockaddr_un){}).sun_path))
42
542563ba 43typedef struct SocketAddress {
f6144808 44 union sockaddr_union sockaddr;
42f4e3c4
LP
45
46 /* We store the size here explicitly due to the weird
47 * sockaddr_un semantics for abstract sockets */
48 socklen_t size;
49
50 /* Socket type, i.e. SOCK_STREAM, SOCK_DGRAM, ... */
51 int type;
7a22745a
LP
52
53 /* Socket protocol, IPPROTO_xxx, usually 0, except for netlink */
54 int protocol;
542563ba 55} SocketAddress;
42f4e3c4 56
542563ba
LP
57typedef enum SocketAddressBindIPv6Only {
58 SOCKET_ADDRESS_DEFAULT,
59 SOCKET_ADDRESS_BOTH,
c0120d99
LP
60 SOCKET_ADDRESS_IPV6_ONLY,
61 _SOCKET_ADDRESS_BIND_IPV6_ONLY_MAX,
2d93c20e 62 _SOCKET_ADDRESS_BIND_IPV6_ONLY_INVALID = -EINVAL,
542563ba 63} SocketAddressBindIPv6Only;
42f4e3c4 64
542563ba 65#define socket_address_family(a) ((a)->sockaddr.sa.sa_family)
42f4e3c4 66
398ce0bc
YW
67const char* socket_address_type_to_string(int t) _const_;
68int socket_address_type_from_string(const char *s) _pure_;
69
9f20fc28
LP
70int sockaddr_un_unlink(const struct sockaddr_un *sa);
71
72static inline int socket_address_unlink(const SocketAddress *a) {
73 return socket_address_family(a) == AF_UNIX ? sockaddr_un_unlink(&a->sockaddr.un) : 0;
74}
b5a0699f 75
44a6b1b6 76bool socket_address_can_accept(const SocketAddress *a) _pure_;
4f2d528d 77
b5a0699f
LP
78int socket_address_listen(
79 const SocketAddress *a,
175a3d25 80 int flags,
b5a0699f
LP
81 int backlog,
82 SocketAddressBindIPv6Only only,
83 const char *bind_to_device,
54255c64 84 bool reuse_port,
4fd5948e 85 bool free_bind,
6b6d2dee 86 bool transparent,
b5a0699f
LP
87 mode_t directory_mode,
88 mode_t socket_mode,
175a3d25 89 const char *label);
a16e1123 90
5c3fa98d
ZJS
91int socket_address_verify(const SocketAddress *a, bool strict) _pure_;
92int socket_address_print(const SocketAddress *a, char **p);
01e10de3
LP
93bool socket_address_matches_fd(const SocketAddress *a, int fd);
94
44a6b1b6 95bool socket_address_equal(const SocketAddress *a, const SocketAddress *b) _pure_;
a16e1123 96
a57f7e2c 97const char* socket_address_get_path(const SocketAddress *a);
6e2ef85b 98
4d49b48c 99bool socket_ipv6_is_supported(void);
83e03c4f 100bool socket_ipv6_is_enabled(void);
4d49b48c 101
69dc6922 102int sockaddr_port(const struct sockaddr *_sa, unsigned *port);
31325971 103const union in_addr_union *sockaddr_in_addr(const struct sockaddr *sa);
c1b91f06 104int sockaddr_set_in_addr(union sockaddr_union *u, int family, const union in_addr_union *a, uint16_t port);
3b1c5241
SL
105
106int sockaddr_pretty(const struct sockaddr *_sa, socklen_t salen, bool translate_ipv6, bool include_port, char **ret);
366b7db4 107int getpeername_pretty(int fd, bool include_port, char **ret);
4d49b48c
LP
108int getsockname_pretty(int fd, char **ret);
109
fc1f05eb 110int socknameinfo_pretty(const struct sockaddr *sa, socklen_t salen, char **_ret);
b31f535c 111
44a6b1b6
ZJS
112const char* socket_address_bind_ipv6_only_to_string(SocketAddressBindIPv6Only b) _const_;
113SocketAddressBindIPv6Only socket_address_bind_ipv6_only_from_string(const char *s) _pure_;
b54e98ef 114SocketAddressBindIPv6Only socket_address_bind_ipv6_only_or_bool_from_string(const char *s);
c0120d99 115
f8b69d1d 116int netlink_family_to_string_alloc(int b, char **s);
4d49b48c 117int netlink_family_from_string(const char *s) _pure_;
f01e5736
LP
118
119bool sockaddr_equal(const union sockaddr_union *a, const union sockaddr_union *b);
2583fbea 120
d9d9b2a0
YW
121int fd_set_sndbuf(int fd, size_t n, bool increase);
122static inline int fd_inc_sndbuf(int fd, size_t n) {
123 return fd_set_sndbuf(fd, n, true);
124}
125int fd_set_rcvbuf(int fd, size_t n, bool increase);
28e7e934 126static inline int fd_increase_rxbuf(int fd, size_t n) {
d9d9b2a0
YW
127 return fd_set_rcvbuf(fd, n, true);
128}
2583fbea
LP
129
130int ip_tos_to_string_alloc(int i, char **s);
131int ip_tos_from_string(const char *s);
132
2313524a 133typedef enum {
6aebfec3
LP
134 IFNAME_VALID_ALTERNATIVE = 1 << 0, /* Allow "altnames" too */
135 IFNAME_VALID_NUMERIC = 1 << 1, /* Allow decimal formatted ifindexes too */
136 IFNAME_VALID_SPECIAL = 1 << 2, /* Allow the special names "all" and "default" */
137 _IFNAME_VALID_ALL = IFNAME_VALID_ALTERNATIVE | IFNAME_VALID_NUMERIC | IFNAME_VALID_SPECIAL,
2313524a 138} IfnameValidFlags;
180341e7
MY
139bool ifname_valid_char(char a) _const_;
140bool ifname_valid_full(const char *p, IfnameValidFlags flags) _pure_;
4252696a 141static inline bool ifname_valid(const char *p) {
2313524a 142 return ifname_valid_full(p, 0);
4252696a 143}
180341e7 144bool address_label_valid(const char *p) _pure_;
ef76dff2 145
2583fbea
LP
146int getpeercred(int fd, struct ucred *ucred);
147int getpeersec(int fd, char **ret);
43f2c88d 148int getpeergroups(int fd, gid_t **ret);
da5e0c44 149int getpeerpidfd(int fd);
b2206fe5 150int getpeerpidref(int fd, PidRef *ret);
2583fbea 151
598d2428
LB
152ssize_t send_many_fds_iov_sa(
153 int transport_fd,
154 int *fds_array, size_t n_fds_array,
155 const struct iovec *iov, size_t iovlen,
156 const struct sockaddr *sa, socklen_t len,
157 int flags);
158static inline ssize_t send_many_fds_iov(
159 int transport_fd,
160 int *fds_array, size_t n_fds_array,
161 const struct iovec *iov, size_t iovlen,
162 int flags) {
163
164 return send_many_fds_iov_sa(transport_fd, fds_array, n_fds_array, iov, iovlen, NULL, 0, flags);
165}
166static inline int send_many_fds(
167 int transport_fd,
168 int *fds_array,
169 size_t n_fds_array,
170 int flags) {
171
172 return send_many_fds_iov_sa(transport_fd, fds_array, n_fds_array, NULL, 0, NULL, 0, flags);
173}
d34673ec
FB
174ssize_t send_one_fd_iov_sa(
175 int transport_fd,
176 int fd,
f621b8d7 177 const struct iovec *iov, size_t iovlen,
d34673ec
FB
178 const struct sockaddr *sa, socklen_t len,
179 int flags);
726f4c47
ZJS
180int send_one_fd_sa(int transport_fd,
181 int fd,
182 const struct sockaddr *sa, socklen_t len,
183 int flags);
d34673ec
FB
184#define send_one_fd_iov(transport_fd, fd, iov, iovlen, flags) send_one_fd_iov_sa(transport_fd, fd, iov, iovlen, NULL, 0, flags)
185#define send_one_fd(transport_fd, fd, flags) send_one_fd_iov_sa(transport_fd, fd, NULL, 0, NULL, 0, flags)
186ssize_t receive_one_fd_iov(int transport_fd, struct iovec *iov, size_t iovlen, int flags, int *ret_fd);
2583fbea 187int receive_one_fd(int transport_fd, int flags);
598d2428
LB
188ssize_t receive_many_fds_iov(int transport_fd, struct iovec *iov, size_t iovlen, int **ret_fds_array, size_t *ret_n_fds_array, int flags);
189int receive_many_fds(int transport_fd, int **ret_fds_array, size_t *ret_n_fds_array, int flags);
8f328d36 190
4edc2c9b
LP
191ssize_t next_datagram_size_fd(int fd);
192
60d9771c 193int flush_accept(int fd);
ffb6adb7 194ssize_t flush_mqueue(int fd);
60d9771c 195
8f328d36
LP
196#define CMSG_FOREACH(cmsg, mh) \
197 for ((cmsg) = CMSG_FIRSTHDR(mh); (cmsg); (cmsg) = CMSG_NXTHDR((mh), (cmsg)))
fc2fffe7 198
79dec6f5
LP
199/* Returns the cmsghdr's data pointer, but safely cast to the specified type. Does two alignment checks: one
200 * at compile time, that the requested type has a smaller or same alignment as 'struct cmsghdr', and one
201 * during runtime, that the actual pointer matches the alignment too. This is supposed to catch cases such as
202 * 'struct timeval' is embedded into 'struct cmsghdr' on architectures where the alignment of the former is 8
da890466 203 * bytes (because of a 64-bit time_t), but of the latter is 4 bytes (because size_t is 32 bits), such as
79dec6f5 204 * riscv32. */
b6256af7
LP
205#define CMSG_TYPED_DATA(cmsg, type) \
206 ({ \
4db752e4 207 struct cmsghdr *_cmsg = (cmsg); \
1113e507 208 assert_cc(alignof(type) <= alignof(struct cmsghdr)); \
b6256af7
LP
209 _cmsg ? CAST_ALIGN_PTR(type, CMSG_DATA(_cmsg)) : (type*) NULL; \
210 })
211
29206d46 212struct cmsghdr* cmsg_find(struct msghdr *mh, int level, int type, socklen_t length);
4836f4c6 213void* cmsg_find_and_copy_data(struct msghdr *mh, int level, int type, void *buf, size_t buf_len);
29206d46 214
371d72e0 215/* Type-safe, dereferencing version of cmsg_find() */
b6256af7
LP
216#define CMSG_FIND_DATA(mh, level, type, ctype) \
217 CMSG_TYPED_DATA(cmsg_find(mh, level, type, CMSG_LEN(sizeof(ctype))), ctype)
371d72e0 218
4836f4c6
YW
219/* Type-safe version of cmsg_find_and_copy_data() */
220#define CMSG_FIND_AND_COPY_DATA(mh, level, type, ctype) \
221 (ctype*) cmsg_find_and_copy_data(mh, level, type, &(ctype){}, sizeof(ctype))
222
fb29cdbe
LP
223/* Resolves to a type that can carry cmsghdr structures. Make sure things are properly aligned, i.e. the type
224 * itself is placed properly in memory and the size is also aligned to what's appropriate for "cmsghdr"
225 * structures. */
226#define CMSG_BUFFER_TYPE(size) \
227 union { \
228 struct cmsghdr cmsghdr; \
229 uint8_t buf[size]; \
230 uint8_t align_check[(size) >= CMSG_SPACE(0) && \
231 (size) == CMSG_ALIGN(size) ? 1 : -1]; \
232 }
233
a0233fcd 234size_t sockaddr_ll_len(const struct sockaddr_ll *sa);
b1f24b75 235
a0233fcd 236size_t sockaddr_un_len(const struct sockaddr_un *sa);
429b4350 237
a0233fcd 238size_t sockaddr_len(const union sockaddr_union *sa);
4e0a46f6 239
429b4350 240int socket_ioctl_fd(void);
5cf91ea9
LP
241
242int sockaddr_un_set_path(struct sockaddr_un *ret, const char *path);
2ff48e98
LP
243
244static inline int setsockopt_int(int fd, int level, int optname, int value) {
245 if (setsockopt(fd, level, optname, &value, sizeof(value)) < 0)
246 return -errno;
247
248 return 0;
249}
5d594d01 250
8cf13c87 251int getsockopt_int(int fd, int level, int optname, int *ret);
4e25d4cf 252
5d594d01
LP
253int socket_bind_to_ifname(int fd, const char *ifname);
254int socket_bind_to_ifindex(int fd, int ifindex);
47eae6ce 255
1eeb4f9f
MY
256int socket_autobind(int fd, char **ret_name);
257
da890466 258/* Define a 64-bit version of timeval/timespec in any case, even on 32-bit userspace. */
9365e296
YW
259struct timeval_large {
260 uint64_t tvl_sec, tvl_usec;
261};
262struct timespec_large {
263 uint64_t tvl_sec, tvl_nsec;
264};
265
da890466 266/* glibc duplicates timespec/timeval on certain 32-bit arches, once in 32-bit and once in 64-bit.
05403363 267 * See __convert_scm_timestamps() in glibc source code. Hence, we need additional buffer space for them
ad501930 268 * to prevent truncating control msg (recvmsg() MSG_CTRUNC). */
9365e296
YW
269#define CMSG_SPACE_TIMEVAL \
270 ((sizeof(struct timeval) == sizeof(struct timeval_large)) ? \
271 CMSG_SPACE(sizeof(struct timeval)) : \
272 CMSG_SPACE(sizeof(struct timeval)) + \
273 CMSG_SPACE(sizeof(struct timeval_large)))
274#define CMSG_SPACE_TIMESPEC \
275 ((sizeof(struct timespec) == sizeof(struct timespec_large)) ? \
276 CMSG_SPACE(sizeof(struct timespec)) : \
277 CMSG_SPACE(sizeof(struct timespec)) + \
278 CMSG_SPACE(sizeof(struct timespec_large)))
279
47eae6ce 280ssize_t recvmsg_safe(int sockfd, struct msghdr *msg, int flags);
35a3eb9b 281
5f64d2bf 282int socket_get_family(int fd);
5d0fe423 283int socket_set_recvpktinfo(int fd, int af, bool b);
5d0fe423 284int socket_set_unicast_if(int fd, int af, int ifi);
00ed2fff 285
402506ce
YW
286int socket_set_option(int fd, int af, int opt_ipv4, int opt_ipv6, int val);
287static inline int socket_set_recverr(int fd, int af, bool b) {
288 return socket_set_option(fd, af, IP_RECVERR, IPV6_RECVERR, b);
289}
290static inline int socket_set_recvttl(int fd, int af, bool b) {
291 return socket_set_option(fd, af, IP_RECVTTL, IPV6_RECVHOPLIMIT, b);
292}
293static inline int socket_set_ttl(int fd, int af, int ttl) {
294 return socket_set_option(fd, af, IP_TTL, IPV6_UNICAST_HOPS, ttl);
295}
296static inline int socket_set_freebind(int fd, int af, bool b) {
297 return socket_set_option(fd, af, IP_FREEBIND, IPV6_FREEBIND, b);
298}
299static inline int socket_set_transparent(int fd, int af, bool b) {
300 return socket_set_option(fd, af, IP_TRANSPARENT, IPV6_TRANSPARENT, b);
301}
00ed2fff
LP
302static inline int socket_set_recvfragsize(int fd, int af, bool b) {
303 return socket_set_option(fd, af, IP_RECVFRAGSIZE, IPV6_RECVFRAGSIZE, b);
304}
52975f86
LP
305
306int socket_get_mtu(int fd, int af, size_t *ret);
a995ce47
LP
307
308/* an initializer for struct ucred that initialized all fields to the invalid value appropriate for each */
309#define UCRED_INVALID { .pid = 0, .uid = UID_INVALID, .gid = GID_INVALID }
2679aee4
LP
310
311int connect_unix_path(int fd, int dir_fd, const char *path);
747b5d96 312
06d4fe57
LP
313static inline bool VSOCK_CID_IS_REGULAR(unsigned cid) {
314 /* 0, 1, 2, UINT32_MAX are special, refuse those */
315 return cid > 2 && cid < UINT32_MAX;
316}
317
8e471c6a
LP
318int vsock_parse_port(const char *s, unsigned *ret);
319int vsock_parse_cid(const char *s, unsigned *ret);
320
747b5d96
LB
321/* Parses AF_UNIX and AF_VSOCK addresses. AF_INET[6] require some netlink calls, so it cannot be in
322 * src/basic/ and is done from 'socket_local_address from src/shared/. Return -EPROTO in case of
323 * protocol mismatch. */
324int socket_address_parse_unix(SocketAddress *ret_address, const char *s);
325int socket_address_parse_vsock(SocketAddress *ret_address, const char *s);
e739395f 326int socket_address_equal_unix(const char *a, const char *b);
768fcd77
LP
327
328/* libc's SOMAXCONN is defined to 128 or 4096 (at least on glibc). But actually, the value can be much
2053182b 329 * larger. In our codebase we want to set it to the max usually, since nowadays socket memory is properly
768fcd77
LP
330 * tracked by memcg, and hence we don't need to enforce extra limits here. Moreover, the kernel caps it to
331 * /proc/sys/net/core/somaxconn anyway, thus by setting this to unbounded we just make that sysctl file
332 * authoritative. */
333#define SOMAXCONN_DELUXE INT_MAX
d3109d8d
LP
334
335int vsock_get_local_cid(unsigned *ret);
029709f9
YW
336
337int netlink_socket_get_multicast_groups(int fd, size_t *ret_len, uint32_t **ret_groups);
272017d3
LP
338
339int socket_get_cookie(int fd, uint64_t *ret);
ea71d347
LP
340
341void cmsg_close_all(struct msghdr *mh);