]>
Commit | Line | Data |
---|---|---|
cc73685d | 1 | /* SPDX-License-Identifier: LGPL-2.1+ */ |
b0a33c1e | 2 | |
f1a4a029 ÇO |
3 | #ifndef __LXC_AF_UNIX_H |
4 | #define __LXC_AF_UNIX_H | |
5 | ||
1160ce89 CB |
6 | #include "config.h" |
7 | ||
ae467c54 | 8 | #include <stdio.h> |
86ce1da1 | 9 | #include <sys/socket.h> |
d17c815d | 10 | #include <stddef.h> |
86ce1da1 | 11 | #include <sys/un.h> |
ae467c54 | 12 | |
674c9692 | 13 | #include "compiler.h" |
d17c815d CB |
14 | #include "macro.h" |
15 | #include "memory_utils.h" | |
16 | ||
780215cf CB |
17 | #define KERNEL_SCM_MAX_FD 253 |
18 | ||
19 | /* Allow the caller to set expectations. */ | |
20 | ||
d17c815d | 21 | /* |
780215cf CB |
22 | * UNIX_FDS_ACCEPT_EXACT will only succeed if the exact amount of fds has been |
23 | * received (unless combined with UNIX_FDS_ACCEPT_NONE). | |
d17c815d | 24 | */ |
780215cf CB |
25 | #define UNIX_FDS_ACCEPT_EXACT ((__u32)(1 << 0)) /* default */ |
26 | ||
27 | /* | |
28 | * UNIX_FDS_ACCEPT_LESS will also succeed if less than the requested number of | |
29 | * fd has been received. If the UNIX_FDS_ACCEPT_NONE flag is not raised than at | |
30 | * least one fd must be received. | |
31 | * */ | |
32 | #define UNIX_FDS_ACCEPT_LESS ((__u32)(1 << 1)) | |
33 | ||
34 | /* | |
35 | * UNIX_FDS_ACCEPT_MORE will also succeed if more than the requested number of | |
36 | * fds have been received. Any additional fds will be silently closed. If the | |
37 | * UNIX_FDS_ACCEPT_NONE flag is not raised than at least one fd must be | |
38 | * received. | |
39 | */ | |
40 | #define UNIX_FDS_ACCEPT_MORE ((__u32)(1 << 2)) /* wipe any extra fds */ | |
41 | ||
42 | /* | |
43 | * UNIX_FDS_ACCEPT_NONE can be specified with any of the above flags and | |
44 | * indicates that the caller will accept no file descriptors to be received. | |
45 | */ | |
46 | #define UNIX_FDS_ACCEPT_NONE ((__u32)(1 << 3)) | |
47 | ||
48 | /* UNIX_FDS_ACCEPT_MASK is the value of all the above flags or-ed together. */ | |
49 | #define UNIX_FDS_ACCEPT_MASK (UNIX_FDS_ACCEPT_EXACT | UNIX_FDS_ACCEPT_LESS | UNIX_FDS_ACCEPT_MORE | UNIX_FDS_ACCEPT_NONE) | |
d17c815d | 50 | |
780215cf CB |
51 | /* Allow the callee to communicate reality. */ |
52 | ||
53 | /* UNIX_FDS_RECEIVED_EXACT indicates that the exact number of fds was received. */ | |
54 | #define UNIX_FDS_RECEIVED_EXACT ((__u32)(1 << 16)) | |
55 | ||
56 | /* | |
57 | * UNIX_FDS_RECEIVED_LESS indicates that less than the requested number of fd | |
58 | * has been received. | |
59 | */ | |
60 | #define UNIX_FDS_RECEIVED_LESS ((__u32)(1 << 17)) | |
61 | ||
62 | /* | |
63 | * UNIX_FDS_RECEIVED_MORE indicates that more than the requested number of fd | |
64 | * has been received. | |
65 | */ | |
66 | #define UNIX_FDS_RECEIVED_MORE ((__u32)(1 << 18)) | |
67 | ||
68 | /* UNIX_FDS_RECEIVED_NONE indicates that no fds have been received. */ | |
69 | #define UNIX_FDS_RECEIVED_NONE ((__u32)(1 << 19)) | |
70 | ||
71 | /** | |
72 | * Defines a generic struct to receive file descriptors from unix sockets. | |
73 | * @fd_count_max : Either the exact or maximum number of file descriptors the | |
74 | * caller is willing to accept. Must be smaller than | |
75 | * KERNEL_SCM_MAX_FDs; larger values will be rejected. | |
76 | * Filled in by the caller. | |
77 | * @fd_count_ret : The actually received number of file descriptors. | |
78 | * Filled in by the callee. | |
79 | * @flags : Flags to negotiate expectations about the number of file | |
80 | * descriptors to receive. | |
81 | * Filled in by the caller and callee. The caller's flag space | |
82 | * is UNIX_FDS_ACCEPT_* other values will be rejected. The | |
83 | * caller may only set one of {EXACT, LESS, MORE}. In addition | |
84 | * they can raise the NONE flag. Any combination of {EXACT, | |
85 | * LESS, MORE} will be rejected. | |
86 | * The callee's flag space is UNIX_FDS_RECEIVED_*. Only ever | |
87 | * one of those values will be set. | |
88 | * @fd : Array to store received file descriptors into. Filled by the | |
89 | * callee on success. If less file descriptors are received | |
90 | * than requested in @fd_count_max the callee will ensure that | |
91 | * all additional slots will be set to -EBADF. Nonetheless, the | |
92 | * caller should only ever use @fd_count_ret to iterate through | |
93 | * @fd after a successful receive. | |
94 | */ | |
d17c815d CB |
95 | struct unix_fds { |
96 | __u32 fd_count_max; | |
97 | __u32 fd_count_ret; | |
780215cf | 98 | __u32 flags; |
d17c815d CB |
99 | __s32 fd[KERNEL_SCM_MAX_FD]; |
100 | } __attribute__((aligned(8))); | |
674c9692 | 101 | |
caf3beb0 | 102 | /* does not enforce \0-termination */ |
035db741 CB |
103 | __hidden extern int lxc_abstract_unix_open(const char *path, int type, int flags); |
104 | __hidden extern void lxc_abstract_unix_close(int fd); | |
caf3beb0 | 105 | /* does not enforce \0-termination */ |
035db741 | 106 | __hidden extern int lxc_abstract_unix_connect(const char *path); |
674c9692 | 107 | |
d17c815d CB |
108 | __hidden extern int lxc_abstract_unix_send_fds(int fd, const int *sendfds, |
109 | int num_sendfds, void *data, | |
110 | size_t size) __access_r(2, 3) | |
111 | __access_r(4, 5); | |
112 | ||
113 | __hidden extern int lxc_abstract_unix_send_fds_iov(int fd, const int *sendfds, | |
114 | int num_sendfds, | |
115 | struct iovec *iov, | |
116 | size_t iovlen) | |
117 | __access_r(2, 3); | |
118 | ||
119 | __hidden extern ssize_t lxc_abstract_unix_recv_fds(int fd, | |
120 | struct unix_fds *ret_fds, | |
121 | void *ret_data, | |
122 | size_t size_ret_data) | |
123 | __access_r(3, 4); | |
674c9692 | 124 | |
d17c815d CB |
125 | __hidden extern ssize_t lxc_abstract_unix_recv_one_fd(int fd, int *ret_fd, |
126 | void *ret_data, | |
127 | size_t size_ret_data) | |
128 | __access_r(3, 4); | |
674c9692 | 129 | |
1b82d721 CB |
130 | __hidden extern int __lxc_abstract_unix_send_two_fds(int fd, int fd_first, |
131 | int fd_second, void *data, | |
132 | size_t size); | |
133 | ||
134 | static inline int lxc_abstract_unix_send_two_fds(int fd, int fd_first, | |
135 | int fd_second) | |
136 | { | |
137 | return __lxc_abstract_unix_send_two_fds(fd, fd_first, fd_second, NULL, 0); | |
138 | } | |
139 | ||
140 | __hidden extern ssize_t __lxc_abstract_unix_recv_two_fds(int fd, int *fd_first, | |
141 | int *fd_second, | |
142 | void *data, size_t size); | |
143 | ||
144 | static inline ssize_t lxc_abstract_unix_recv_two_fds(int fd, int *fd_first, int *fd_second) | |
145 | { | |
146 | return __lxc_abstract_unix_recv_two_fds(fd, fd_first, fd_second, NULL, 0); | |
147 | } | |
674c9692 | 148 | |
035db741 | 149 | __hidden extern int lxc_unix_send_fds(int fd, int *sendfds, int num_sendfds, void *data, size_t size); |
674c9692 | 150 | |
035db741 CB |
151 | __hidden extern int lxc_abstract_unix_send_credential(int fd, void *data, size_t size) |
152 | __access_r(2, 3); | |
674c9692 | 153 | |
035db741 CB |
154 | __hidden extern int lxc_abstract_unix_rcv_credential(int fd, void *data, size_t size) |
155 | __access_w(2, 3); | |
674c9692 | 156 | |
035db741 CB |
157 | __hidden extern int lxc_unix_sockaddr(struct sockaddr_un *ret, const char *path); |
158 | __hidden extern int lxc_unix_connect(struct sockaddr_un *addr); | |
159 | __hidden extern int lxc_unix_connect_type(struct sockaddr_un *addr, int type); | |
160 | __hidden extern int lxc_socket_set_timeout(int fd, int rcv_timeout, int snd_timeout); | |
b0a33c1e | 161 | |
d17c815d CB |
162 | static inline void put_unix_fds(struct unix_fds *fds) |
163 | { | |
164 | if (!IS_ERR_OR_NULL(fds)) { | |
165 | for (size_t idx = 0; idx < fds->fd_count_ret; idx++) | |
166 | close_prot_errno_disarm(fds->fd[idx]); | |
167 | } | |
168 | } | |
169 | define_cleanup_function(struct unix_fds *, put_unix_fds); | |
170 | ||
77b0073a | 171 | #endif /* __LXC_AF_UNIX_H */ |