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