]> git.proxmox.com Git - systemd.git/blame - src/basic/socket-util.h
New upstream version 249~rc1
[systemd.git] / src / basic / socket-util.h
CommitLineData
a032b68d 1/* SPDX-License-Identifier: LGPL-2.1-or-later */
663996b3
MS
2#pragma once
3
6e866b33
MB
4#include <inttypes.h>
5#include <linux/netlink.h>
f2dec872 6#include <linux/if_ether.h>
6e866b33
MB
7#include <linux/if_infiniband.h>
8#include <linux/if_packet.h>
4c89c718
MP
9#include <netinet/in.h>
10#include <stdbool.h>
11#include <stddef.h>
f2dec872 12#include <string.h>
4c89c718
MP
13#include <sys/socket.h>
14#include <sys/types.h>
663996b3 15#include <sys/un.h>
663996b3 16
8b3d4ff0 17#include "errno-util.h"
663996b3 18#include "macro.h"
3a6ce677 19#include "missing_network.h"
6e866b33
MB
20#include "missing_socket.h"
21#include "sparse-endian.h"
663996b3
MS
22
23union sockaddr_union {
1d42b86d 24 /* The minimal, abstract version */
663996b3 25 struct sockaddr sa;
1d42b86d
MB
26
27 /* The libc provided version that allocates "enough room" for every protocol */
28 struct sockaddr_storage storage;
29
30 /* Protoctol-specific implementations */
60f067b4 31 struct sockaddr_in in;
663996b3
MS
32 struct sockaddr_in6 in6;
33 struct sockaddr_un un;
34 struct sockaddr_nl nl;
60f067b4 35 struct sockaddr_ll ll;
2897b343 36 struct sockaddr_vm vm;
1d42b86d 37
f5e65279
MB
38 /* Ensure there is enough space to store Infiniband addresses */
39 uint8_t ll_buffer[offsetof(struct sockaddr_ll, sll_addr) + CONST_MAX(ETH_ALEN, INFINIBAND_ALEN)];
1d42b86d
MB
40
41 /* Ensure there is enough space after the AF_UNIX sun_path for one more NUL byte, just to be sure that the path
42 * component is always followed by at least one NUL byte. */
43 uint8_t un_buffer[sizeof(struct sockaddr_un) + 1];
663996b3
MS
44};
45
46cdbd49
BR
46#define SUN_PATH_LEN (sizeof(((struct sockaddr_un){}).sun_path))
47
663996b3
MS
48typedef struct SocketAddress {
49 union sockaddr_union sockaddr;
50
51 /* We store the size here explicitly due to the weird
52 * sockaddr_un semantics for abstract sockets */
53 socklen_t size;
54
55 /* Socket type, i.e. SOCK_STREAM, SOCK_DGRAM, ... */
56 int type;
57
58 /* Socket protocol, IPPROTO_xxx, usually 0, except for netlink */
59 int protocol;
60} SocketAddress;
61
62typedef enum SocketAddressBindIPv6Only {
63 SOCKET_ADDRESS_DEFAULT,
64 SOCKET_ADDRESS_BOTH,
65 SOCKET_ADDRESS_IPV6_ONLY,
66 _SOCKET_ADDRESS_BIND_IPV6_ONLY_MAX,
3a6ce677 67 _SOCKET_ADDRESS_BIND_IPV6_ONLY_INVALID = -EINVAL,
663996b3
MS
68} SocketAddressBindIPv6Only;
69
70#define socket_address_family(a) ((a)->sockaddr.sa.sa_family)
71
1d42b86d
MB
72const char* socket_address_type_to_string(int t) _const_;
73int socket_address_type_from_string(const char *s) _pure_;
74
6e866b33
MB
75int sockaddr_un_unlink(const struct sockaddr_un *sa);
76
77static inline int socket_address_unlink(const SocketAddress *a) {
78 return socket_address_family(a) == AF_UNIX ? sockaddr_un_unlink(&a->sockaddr.un) : 0;
79}
663996b3
MS
80
81bool socket_address_can_accept(const SocketAddress *a) _pure_;
82
83int socket_address_listen(
84 const SocketAddress *a,
60f067b4 85 int flags,
663996b3
MS
86 int backlog,
87 SocketAddressBindIPv6Only only,
88 const char *bind_to_device,
fb183854 89 bool reuse_port,
663996b3
MS
90 bool free_bind,
91 bool transparent,
92 mode_t directory_mode,
93 mode_t socket_mode,
60f067b4 94 const char *label);
663996b3 95
46cdbd49
BR
96int socket_address_verify(const SocketAddress *a, bool strict) _pure_;
97int socket_address_print(const SocketAddress *a, char **p);
663996b3
MS
98bool socket_address_matches_fd(const SocketAddress *a, int fd);
99
663996b3
MS
100bool socket_address_equal(const SocketAddress *a, const SocketAddress *b) _pure_;
101
14228c0d 102const char* socket_address_get_path(const SocketAddress *a);
663996b3 103
60f067b4 104bool socket_ipv6_is_supported(void);
3a6ce677 105bool socket_ipv6_is_enabled(void);
60f067b4 106
2897b343 107int sockaddr_port(const struct sockaddr *_sa, unsigned *port);
3a6ce677 108const union in_addr_union *sockaddr_in_addr(const struct sockaddr *sa);
e3bff60a
MP
109
110int sockaddr_pretty(const struct sockaddr *_sa, socklen_t salen, bool translate_ipv6, bool include_port, char **ret);
4c89c718 111int getpeername_pretty(int fd, bool include_port, char **ret);
60f067b4
JS
112int getsockname_pretty(int fd, char **ret);
113
5eef597e 114int socknameinfo_pretty(union sockaddr_union *sa, socklen_t salen, char **_ret);
5eef597e 115
663996b3
MS
116const char* socket_address_bind_ipv6_only_to_string(SocketAddressBindIPv6Only b) _const_;
117SocketAddressBindIPv6Only socket_address_bind_ipv6_only_from_string(const char *s) _pure_;
b012e921 118SocketAddressBindIPv6Only socket_address_bind_ipv6_only_or_bool_from_string(const char *s);
663996b3
MS
119
120int netlink_family_to_string_alloc(int b, char **s);
60f067b4 121int netlink_family_from_string(const char *s) _pure_;
e842803a 122
5eef597e
MP
123bool sockaddr_equal(const union sockaddr_union *a, const union sockaddr_union *b);
124
7de6915e
MB
125int fd_set_sndbuf(int fd, size_t n, bool increase);
126static inline int fd_inc_sndbuf(int fd, size_t n) {
127 return fd_set_sndbuf(fd, n, true);
128}
129int fd_set_rcvbuf(int fd, size_t n, bool increase);
130static inline int fd_inc_rcvbuf(int fd, size_t n) {
131 return fd_set_rcvbuf(fd, n, true);
132}
5eef597e 133
db2df898
MP
134int ip_tos_to_string_alloc(int i, char **s);
135int ip_tos_from_string(const char *s);
136
a032b68d 137typedef enum {
3a6ce677
BR
138 IFNAME_VALID_ALTERNATIVE = 1 << 0,
139 IFNAME_VALID_NUMERIC = 1 << 1,
140 _IFNAME_VALID_ALL = IFNAME_VALID_ALTERNATIVE | IFNAME_VALID_NUMERIC,
a032b68d
MB
141} IfnameValidFlags;
142bool ifname_valid_full(const char *p, IfnameValidFlags flags);
46cdbd49 143static inline bool ifname_valid(const char *p) {
a032b68d 144 return ifname_valid_full(p, 0);
46cdbd49 145}
2897b343 146bool address_label_valid(const char *p);
aa27b158 147
db2df898
MP
148int getpeercred(int fd, struct ucred *ucred);
149int getpeersec(int fd, char **ret);
1d42b86d 150int getpeergroups(int fd, gid_t **ret);
db2df898 151
6e866b33
MB
152ssize_t send_one_fd_iov_sa(
153 int transport_fd,
154 int fd,
155 struct iovec *iov, size_t iovlen,
156 const struct sockaddr *sa, socklen_t len,
157 int flags);
4c89c718
MP
158int send_one_fd_sa(int transport_fd,
159 int fd,
160 const struct sockaddr *sa, socklen_t len,
161 int flags);
6e866b33
MB
162#define send_one_fd_iov(transport_fd, fd, iov, iovlen, flags) send_one_fd_iov_sa(transport_fd, fd, iov, iovlen, NULL, 0, flags)
163#define send_one_fd(transport_fd, fd, flags) send_one_fd_iov_sa(transport_fd, fd, NULL, 0, NULL, 0, flags)
164ssize_t receive_one_fd_iov(int transport_fd, struct iovec *iov, size_t iovlen, int flags, int *ret_fd);
db2df898
MP
165int receive_one_fd(int transport_fd, int flags);
166
aa27b158
MP
167ssize_t next_datagram_size_fd(int fd);
168
169int flush_accept(int fd);
170
db2df898
MP
171#define CMSG_FOREACH(cmsg, mh) \
172 for ((cmsg) = CMSG_FIRSTHDR(mh); (cmsg); (cmsg) = CMSG_NXTHDR((mh), (cmsg)))
aa27b158 173
8a584da2
MP
174struct cmsghdr* cmsg_find(struct msghdr *mh, int level, int type, socklen_t length);
175
a10f5d05
MB
176/* Type-safe, dereferencing version of cmsg_find() */
177#define CMSG_FIND_DATA(mh, level, type, ctype) \
178 ({ \
179 struct cmsghdr *_found; \
180 _found = cmsg_find(mh, level, type, CMSG_LEN(sizeof(ctype))); \
181 (ctype*) (_found ? CMSG_DATA(_found) : NULL); \
182 })
183
184/* Resolves to a type that can carry cmsghdr structures. Make sure things are properly aligned, i.e. the type
185 * itself is placed properly in memory and the size is also aligned to what's appropriate for "cmsghdr"
186 * structures. */
187#define CMSG_BUFFER_TYPE(size) \
188 union { \
189 struct cmsghdr cmsghdr; \
190 uint8_t buf[size]; \
191 uint8_t align_check[(size) >= CMSG_SPACE(0) && \
192 (size) == CMSG_ALIGN(size) ? 1 : -1]; \
193 }
194
f5e65279
MB
195/*
196 * Certain hardware address types (e.g Infiniband) do not fit into sll_addr
197 * (8 bytes) and run over the structure. This macro returns the correct size that
198 * must be passed to kernel.
199 */
200#define SOCKADDR_LL_LEN(sa) \
201 ({ \
202 const struct sockaddr_ll *_sa = &(sa); \
203 size_t _mac_len = sizeof(_sa->sll_addr); \
204 assert(_sa->sll_family == AF_PACKET); \
205 if (be16toh(_sa->sll_hatype) == ARPHRD_ETHER) \
206 _mac_len = MAX(_mac_len, (size_t) ETH_ALEN); \
207 if (be16toh(_sa->sll_hatype) == ARPHRD_INFINIBAND) \
208 _mac_len = MAX(_mac_len, (size_t) INFINIBAND_ALEN); \
209 offsetof(struct sockaddr_ll, sll_addr) + _mac_len; \
210 })
211
aa27b158
MP
212/* Covers only file system and abstract AF_UNIX socket addresses, but not unnamed socket addresses. */
213#define SOCKADDR_UN_LEN(sa) \
214 ({ \
215 const struct sockaddr_un *_sa = &(sa); \
216 assert(_sa->sun_family == AF_UNIX); \
217 offsetof(struct sockaddr_un, sun_path) + \
218 (_sa->sun_path[0] == 0 ? \
219 1 + strnlen(_sa->sun_path+1, sizeof(_sa->sun_path)-1) : \
6e866b33 220 strnlen(_sa->sun_path, sizeof(_sa->sun_path))+1); \
aa27b158 221 })
8a584da2 222
a032b68d
MB
223#define SOCKADDR_LEN(sa) \
224 ({ \
225 const union sockaddr_union *__sa = &(sa); \
226 size_t _len; \
227 switch(__sa->sa.sa_family) { \
228 case AF_INET: \
229 _len = sizeof(struct sockaddr_in); \
230 break; \
231 case AF_INET6: \
232 _len = sizeof(struct sockaddr_in6); \
233 break; \
234 case AF_UNIX: \
235 _len = SOCKADDR_UN_LEN(__sa->un); \
236 break; \
237 case AF_PACKET: \
238 _len = SOCKADDR_LL_LEN(__sa->ll); \
239 break; \
240 case AF_NETLINK: \
241 _len = sizeof(struct sockaddr_nl); \
242 break; \
243 case AF_VSOCK: \
244 _len = sizeof(struct sockaddr_vm); \
245 break; \
246 default: \
247 assert_not_reached("invalid socket family"); \
248 } \
249 _len; \
250 })
251
8a584da2 252int socket_ioctl_fd(void);
6e866b33
MB
253
254int sockaddr_un_set_path(struct sockaddr_un *ret, const char *path);
255
256static inline int setsockopt_int(int fd, int level, int optname, int value) {
257 if (setsockopt(fd, level, optname, &value, sizeof(value)) < 0)
258 return -errno;
259
260 return 0;
261}
bb4f798a 262
3a6ce677
BR
263static inline int getsockopt_int(int fd, int level, int optname, int *ret) {
264 int v;
265 socklen_t sl = sizeof(v);
266
267 if (getsockopt(fd, level, optname, &v, &sl) < 0)
8b3d4ff0 268 return negative_errno();
3a6ce677
BR
269 if (sl != sizeof(v))
270 return -EIO;
271
272 *ret = v;
273 return 0;
274}
275
bb4f798a
MB
276int socket_bind_to_ifname(int fd, const char *ifname);
277int socket_bind_to_ifindex(int fd, int ifindex);
20a6e51f
MB
278
279ssize_t recvmsg_safe(int sockfd, struct msghdr *msg, int flags);
a10f5d05 280
a032b68d
MB
281int socket_get_family(int fd, int *ret);
282int socket_set_recvpktinfo(int fd, int af, bool b);
a032b68d 283int socket_set_unicast_if(int fd, int af, int ifi);
3a6ce677
BR
284
285int socket_set_option(int fd, int af, int opt_ipv4, int opt_ipv6, int val);
286static inline int socket_set_recverr(int fd, int af, bool b) {
287 return socket_set_option(fd, af, IP_RECVERR, IPV6_RECVERR, b);
288}
289static inline int socket_set_recvttl(int fd, int af, bool b) {
290 return socket_set_option(fd, af, IP_RECVTTL, IPV6_RECVHOPLIMIT, b);
291}
292static inline int socket_set_ttl(int fd, int af, int ttl) {
293 return socket_set_option(fd, af, IP_TTL, IPV6_UNICAST_HOPS, ttl);
294}
295static inline int socket_set_freebind(int fd, int af, bool b) {
296 return socket_set_option(fd, af, IP_FREEBIND, IPV6_FREEBIND, b);
297}
298static inline int socket_set_transparent(int fd, int af, bool b) {
299 return socket_set_option(fd, af, IP_TRANSPARENT, IPV6_TRANSPARENT, b);
300}
301static inline int socket_set_recvfragsize(int fd, int af, bool b) {
302 return socket_set_option(fd, af, IP_RECVFRAGSIZE, IPV6_RECVFRAGSIZE, b);
303}
304
305int socket_get_mtu(int fd, int af, size_t *ret);