chiark / gitweb /
socket-util: explicitly ensure there's one trailing NUL byte on AF_UNIX socket addresses
[elogind.git] / src / basic / socket-util.h
1 /* SPDX-License-Identifier: LGPL-2.1+ */
2 #pragma once
3
4 /***
5   This file is part of systemd.
6
7   Copyright 2010 Lennart Poettering
8
9   systemd is free software; you can redistribute it and/or modify it
10   under the terms of the GNU Lesser General Public License as published by
11   the Free Software Foundation; either version 2.1 of the License, or
12   (at your option) any later version.
13
14   systemd is distributed in the hope that it will be useful, but
15   WITHOUT ANY WARRANTY; without even the implied warranty of
16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17   Lesser General Public License for more details.
18
19   You should have received a copy of the GNU Lesser General Public License
20   along with systemd; If not, see <http://www.gnu.org/licenses/>.
21 ***/
22
23 #include <netinet/ether.h>
24 #include <netinet/in.h>
25 #include <stdbool.h>
26 #include <stddef.h>
27 #include <sys/socket.h>
28 #include <sys/types.h>
29 #include <sys/un.h>
30 #include <linux/netlink.h>
31 #include <linux/if_infiniband.h>
32 #include <linux/if_packet.h>
33
34 #include "macro.h"
35 #include "missing.h"
36 #include "util.h"
37
38 union sockaddr_union {
39         /* The minimal, abstract version */
40         struct sockaddr sa;
41
42         /* The libc provided version that allocates "enough room" for every protocol */
43         struct sockaddr_storage storage;
44
45         /* Protoctol-specific implementations */
46         struct sockaddr_in in;
47         struct sockaddr_in6 in6;
48         struct sockaddr_un un;
49 #if 0 /// UNNEEDED by elogind, only 'sa', 'in', 'in6' and 'un' are used in all of elogind.
50         struct sockaddr_nl nl;
51         struct sockaddr_ll ll;
52         struct sockaddr_vm vm;
53 #endif // 0
54
55         /* Ensure there is enough space to store Infiniband addresses */
56         uint8_t ll_buffer[offsetof(struct sockaddr_ll, sll_addr) + CONST_MAX(ETH_ALEN, INFINIBAND_ALEN)];
57
58         /* Ensure there is enough space after the AF_UNIX sun_path for one more NUL byte, just to be sure that the path
59          * component is always followed by at least one NUL byte. */
60         uint8_t un_buffer[sizeof(struct sockaddr_un) + 1];
61 };
62
63 #if 0 /// UNNEEDED by elogind
64 typedef struct SocketAddress {
65         union sockaddr_union sockaddr;
66
67         /* We store the size here explicitly due to the weird
68          * sockaddr_un semantics for abstract sockets */
69         socklen_t size;
70
71         /* Socket type, i.e. SOCK_STREAM, SOCK_DGRAM, ... */
72         int type;
73
74         /* Socket protocol, IPPROTO_xxx, usually 0, except for netlink */
75         int protocol;
76 } SocketAddress;
77
78 typedef enum SocketAddressBindIPv6Only {
79         SOCKET_ADDRESS_DEFAULT,
80         SOCKET_ADDRESS_BOTH,
81         SOCKET_ADDRESS_IPV6_ONLY,
82         _SOCKET_ADDRESS_BIND_IPV6_ONLY_MAX,
83         _SOCKET_ADDRESS_BIND_IPV6_ONLY_INVALID = -1
84 } SocketAddressBindIPv6Only;
85
86 #define socket_address_family(a) ((a)->sockaddr.sa.sa_family)
87
88 const char* socket_address_type_to_string(int t) _const_;
89 int socket_address_type_from_string(const char *s) _pure_;
90
91 int socket_address_parse(SocketAddress *a, const char *s);
92 int socket_address_parse_and_warn(SocketAddress *a, const char *s);
93 int socket_address_parse_netlink(SocketAddress *a, const char *s);
94 int socket_address_print(const SocketAddress *a, char **p);
95 int socket_address_verify(const SocketAddress *a) _pure_;
96 int socket_address_unlink(SocketAddress *a);
97
98 bool socket_address_can_accept(const SocketAddress *a) _pure_;
99
100 int socket_address_listen(
101                 const SocketAddress *a,
102                 int flags,
103                 int backlog,
104                 SocketAddressBindIPv6Only only,
105                 const char *bind_to_device,
106                 bool reuse_port,
107                 bool free_bind,
108                 bool transparent,
109                 mode_t directory_mode,
110                 mode_t socket_mode,
111                 const char *label);
112 int make_socket_fd(int log_level, const char* address, int type, int flags);
113
114 bool socket_address_is(const SocketAddress *a, const char *s, int type);
115 bool socket_address_is_netlink(const SocketAddress *a, const char *s);
116
117 bool socket_address_matches_fd(const SocketAddress *a, int fd);
118
119 bool socket_address_equal(const SocketAddress *a, const SocketAddress *b) _pure_;
120
121 const char* socket_address_get_path(const SocketAddress *a);
122
123 bool socket_ipv6_is_supported(void);
124
125 int sockaddr_port(const struct sockaddr *_sa, unsigned *port);
126
127 int sockaddr_pretty(const struct sockaddr *_sa, socklen_t salen, bool translate_ipv6, bool include_port, char **ret);
128 int getpeername_pretty(int fd, bool include_port, char **ret);
129 int getsockname_pretty(int fd, char **ret);
130
131 int socknameinfo_pretty(union sockaddr_union *sa, socklen_t salen, char **_ret);
132 int getnameinfo_pretty(int fd, char **ret);
133
134 const char* socket_address_bind_ipv6_only_to_string(SocketAddressBindIPv6Only b) _const_;
135 SocketAddressBindIPv6Only socket_address_bind_ipv6_only_from_string(const char *s) _pure_;
136 SocketAddressBindIPv6Only parse_socket_address_bind_ipv6_only_or_bool(const char *s);
137
138 int netlink_family_to_string_alloc(int b, char **s);
139 int netlink_family_from_string(const char *s) _pure_;
140
141 bool sockaddr_equal(const union sockaddr_union *a, const union sockaddr_union *b);
142 #endif // 0
143
144 int fd_inc_sndbuf(int fd, size_t n);
145 int fd_inc_rcvbuf(int fd, size_t n);
146 #if 0 /// UNNEEDED by elogind
147
148 int ip_tos_to_string_alloc(int i, char **s);
149 int ip_tos_from_string(const char *s);
150
151 bool ifname_valid(const char *p);
152 bool address_label_valid(const char *p);
153 #endif // 0
154
155 int getpeercred(int fd, struct ucred *ucred);
156 int getpeersec(int fd, char **ret);
157 int getpeergroups(int fd, gid_t **ret);
158
159 int send_one_fd_sa(int transport_fd,
160                    int fd,
161                    const struct sockaddr *sa, socklen_t len,
162                    int flags);
163 #define send_one_fd(transport_fd, fd, flags) send_one_fd_sa(transport_fd, fd, NULL, 0, flags)
164 #if 0 /// UNNEEDED by elogind
165 int receive_one_fd(int transport_fd, int flags);
166
167 ssize_t next_datagram_size_fd(int fd);
168
169 int flush_accept(int fd);
170 #endif // 0
171
172 #define CMSG_FOREACH(cmsg, mh)                                          \
173         for ((cmsg) = CMSG_FIRSTHDR(mh); (cmsg); (cmsg) = CMSG_NXTHDR((mh), (cmsg)))
174
175 #if 0 /// UNNEEDED by elogind
176 struct cmsghdr* cmsg_find(struct msghdr *mh, int level, int type, socklen_t length);
177 #endif // 0
178
179 /*
180  * Certain hardware address types (e.g Infiniband) do not fit into sll_addr
181  * (8 bytes) and run over the structure. This macro returns the correct size that
182  * must be passed to kernel.
183  */
184 #define SOCKADDR_LL_LEN(sa)                                             \
185         ({                                                              \
186                 const struct sockaddr_ll *_sa = &(sa);                  \
187                 size_t _mac_len = sizeof(_sa->sll_addr);                \
188                 assert(_sa->sll_family == AF_PACKET);                   \
189                 if (be16toh(_sa->sll_hatype) == ARPHRD_ETHER)           \
190                         _mac_len = MAX(_mac_len, (size_t) ETH_ALEN);    \
191                 if (be16toh(_sa->sll_hatype) == ARPHRD_INFINIBAND)      \
192                         _mac_len = MAX(_mac_len, (size_t) INFINIBAND_ALEN); \
193                 offsetof(struct sockaddr_ll, sll_addr) + _mac_len;      \
194         })
195
196 /* Covers only file system and abstract AF_UNIX socket addresses, but not unnamed socket addresses. */
197 #define SOCKADDR_UN_LEN(sa)                                             \
198         ({                                                              \
199                 const struct sockaddr_un *_sa = &(sa);                  \
200                 assert(_sa->sun_family == AF_UNIX);                     \
201                 offsetof(struct sockaddr_un, sun_path) +                \
202                         (_sa->sun_path[0] == 0 ?                        \
203                          1 + strnlen(_sa->sun_path+1, sizeof(_sa->sun_path)-1) : \
204                          strnlen(_sa->sun_path, sizeof(_sa->sun_path))); \
205         })
206
207 #if 0 /// UNNEEDED by elogind
208 int socket_ioctl_fd(void);
209 #endif // 0