Blame


1 b69b73ef 2023-11-25 thomas /* $OpenBSD: imsg-buffer.c,v 1.17 2023/10/24 14:05:23 claudio Exp $ */
2 dd038bc6 2021-09-21 thomas.ad
3 dd038bc6 2021-09-21 thomas.ad /*
4 dd038bc6 2021-09-21 thomas.ad * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
5 dd038bc6 2021-09-21 thomas.ad *
6 dd038bc6 2021-09-21 thomas.ad * Permission to use, copy, modify, and distribute this software for any
7 dd038bc6 2021-09-21 thomas.ad * purpose with or without fee is hereby granted, provided that the above
8 dd038bc6 2021-09-21 thomas.ad * copyright notice and this permission notice appear in all copies.
9 dd038bc6 2021-09-21 thomas.ad *
10 dd038bc6 2021-09-21 thomas.ad * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 dd038bc6 2021-09-21 thomas.ad * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 dd038bc6 2021-09-21 thomas.ad * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 dd038bc6 2021-09-21 thomas.ad * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 dd038bc6 2021-09-21 thomas.ad * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 dd038bc6 2021-09-21 thomas.ad * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 dd038bc6 2021-09-21 thomas.ad * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 dd038bc6 2021-09-21 thomas.ad */
18 dd038bc6 2021-09-21 thomas.ad
19 dd038bc6 2021-09-21 thomas.ad #include <sys/types.h>
20 dd038bc6 2021-09-21 thomas.ad #include <sys/socket.h>
21 dd038bc6 2021-09-21 thomas.ad #include <sys/uio.h>
22 dd038bc6 2021-09-21 thomas.ad
23 dd038bc6 2021-09-21 thomas.ad #include <limits.h>
24 dd038bc6 2021-09-21 thomas.ad #include <errno.h>
25 dd038bc6 2021-09-21 thomas.ad #include <stdlib.h>
26 dd038bc6 2021-09-21 thomas.ad #include <string.h>
27 dd038bc6 2021-09-21 thomas.ad #include <unistd.h>
28 dd038bc6 2021-09-21 thomas.ad
29 dd038bc6 2021-09-21 thomas.ad #include "got_compat.h"
30 4fccd2fe 2023-03-08 thomas #include "imsg.h"
31 dd038bc6 2021-09-21 thomas.ad
32 dd038bc6 2021-09-21 thomas.ad static int ibuf_realloc(struct ibuf *, size_t);
33 dd038bc6 2021-09-21 thomas.ad static void ibuf_enqueue(struct msgbuf *, struct ibuf *);
34 dd038bc6 2021-09-21 thomas.ad static void ibuf_dequeue(struct msgbuf *, struct ibuf *);
35 3ef3f36a 2023-07-05 op static void msgbuf_drain(struct msgbuf *, size_t);
36 dd038bc6 2021-09-21 thomas.ad
37 dd038bc6 2021-09-21 thomas.ad struct ibuf *
38 dd038bc6 2021-09-21 thomas.ad ibuf_open(size_t len)
39 dd038bc6 2021-09-21 thomas.ad {
40 dd038bc6 2021-09-21 thomas.ad struct ibuf *buf;
41 dd038bc6 2021-09-21 thomas.ad
42 3ef3f36a 2023-07-05 op if (len == 0) {
43 3ef3f36a 2023-07-05 op errno = EINVAL;
44 3ef3f36a 2023-07-05 op return (NULL);
45 3ef3f36a 2023-07-05 op }
46 dd038bc6 2021-09-21 thomas.ad if ((buf = calloc(1, sizeof(struct ibuf))) == NULL)
47 dd038bc6 2021-09-21 thomas.ad return (NULL);
48 3ef3f36a 2023-07-05 op if ((buf->buf = calloc(len, 1)) == NULL) {
49 dd038bc6 2021-09-21 thomas.ad free(buf);
50 dd038bc6 2021-09-21 thomas.ad return (NULL);
51 dd038bc6 2021-09-21 thomas.ad }
52 dd038bc6 2021-09-21 thomas.ad buf->size = buf->max = len;
53 dd038bc6 2021-09-21 thomas.ad buf->fd = -1;
54 dd038bc6 2021-09-21 thomas.ad
55 dd038bc6 2021-09-21 thomas.ad return (buf);
56 dd038bc6 2021-09-21 thomas.ad }
57 dd038bc6 2021-09-21 thomas.ad
58 dd038bc6 2021-09-21 thomas.ad struct ibuf *
59 dd038bc6 2021-09-21 thomas.ad ibuf_dynamic(size_t len, size_t max)
60 dd038bc6 2021-09-21 thomas.ad {
61 dd038bc6 2021-09-21 thomas.ad struct ibuf *buf;
62 dd038bc6 2021-09-21 thomas.ad
63 3ef3f36a 2023-07-05 op if (max < len) {
64 3ef3f36a 2023-07-05 op errno = EINVAL;
65 dd038bc6 2021-09-21 thomas.ad return (NULL);
66 3ef3f36a 2023-07-05 op }
67 dd038bc6 2021-09-21 thomas.ad
68 3ef3f36a 2023-07-05 op if ((buf = calloc(1, sizeof(struct ibuf))) == NULL)
69 dd038bc6 2021-09-21 thomas.ad return (NULL);
70 3ef3f36a 2023-07-05 op if (len > 0) {
71 3ef3f36a 2023-07-05 op if ((buf->buf = calloc(len, 1)) == NULL) {
72 3ef3f36a 2023-07-05 op free(buf);
73 3ef3f36a 2023-07-05 op return (NULL);
74 3ef3f36a 2023-07-05 op }
75 3ef3f36a 2023-07-05 op }
76 3ef3f36a 2023-07-05 op buf->size = len;
77 3ef3f36a 2023-07-05 op buf->max = max;
78 3ef3f36a 2023-07-05 op buf->fd = -1;
79 dd038bc6 2021-09-21 thomas.ad
80 dd038bc6 2021-09-21 thomas.ad return (buf);
81 dd038bc6 2021-09-21 thomas.ad }
82 dd038bc6 2021-09-21 thomas.ad
83 dd038bc6 2021-09-21 thomas.ad static int
84 dd038bc6 2021-09-21 thomas.ad ibuf_realloc(struct ibuf *buf, size_t len)
85 dd038bc6 2021-09-21 thomas.ad {
86 3ef3f36a 2023-07-05 op unsigned char *b;
87 dd038bc6 2021-09-21 thomas.ad
88 dd038bc6 2021-09-21 thomas.ad /* on static buffers max is eq size and so the following fails */
89 3ef3f36a 2023-07-05 op if (len > SIZE_MAX - buf->wpos || buf->wpos + len > buf->max) {
90 dd038bc6 2021-09-21 thomas.ad errno = ERANGE;
91 dd038bc6 2021-09-21 thomas.ad return (-1);
92 dd038bc6 2021-09-21 thomas.ad }
93 dd038bc6 2021-09-21 thomas.ad
94 c0faa645 2021-09-21 thomas.ad b = recallocarray(buf->buf, buf->size, buf->wpos + len, 1);
95 dd038bc6 2021-09-21 thomas.ad if (b == NULL)
96 dd038bc6 2021-09-21 thomas.ad return (-1);
97 dd038bc6 2021-09-21 thomas.ad buf->buf = b;
98 dd038bc6 2021-09-21 thomas.ad buf->size = buf->wpos + len;
99 dd038bc6 2021-09-21 thomas.ad
100 dd038bc6 2021-09-21 thomas.ad return (0);
101 dd038bc6 2021-09-21 thomas.ad }
102 dd038bc6 2021-09-21 thomas.ad
103 dd038bc6 2021-09-21 thomas.ad void *
104 dd038bc6 2021-09-21 thomas.ad ibuf_reserve(struct ibuf *buf, size_t len)
105 dd038bc6 2021-09-21 thomas.ad {
106 dd038bc6 2021-09-21 thomas.ad void *b;
107 dd038bc6 2021-09-21 thomas.ad
108 3ef3f36a 2023-07-05 op if (len > SIZE_MAX - buf->wpos) {
109 3ef3f36a 2023-07-05 op errno = ERANGE;
110 3ef3f36a 2023-07-05 op return (NULL);
111 3ef3f36a 2023-07-05 op }
112 3ef3f36a 2023-07-05 op
113 dd038bc6 2021-09-21 thomas.ad if (buf->wpos + len > buf->size)
114 dd038bc6 2021-09-21 thomas.ad if (ibuf_realloc(buf, len) == -1)
115 dd038bc6 2021-09-21 thomas.ad return (NULL);
116 dd038bc6 2021-09-21 thomas.ad
117 dd038bc6 2021-09-21 thomas.ad b = buf->buf + buf->wpos;
118 dd038bc6 2021-09-21 thomas.ad buf->wpos += len;
119 3ef3f36a 2023-07-05 op memset(b, 0, len);
120 dd038bc6 2021-09-21 thomas.ad return (b);
121 dd038bc6 2021-09-21 thomas.ad }
122 dd038bc6 2021-09-21 thomas.ad
123 3ef3f36a 2023-07-05 op int
124 3ef3f36a 2023-07-05 op ibuf_add(struct ibuf *buf, const void *data, size_t len)
125 3ef3f36a 2023-07-05 op {
126 3ef3f36a 2023-07-05 op void *b;
127 3ef3f36a 2023-07-05 op
128 3ef3f36a 2023-07-05 op if ((b = ibuf_reserve(buf, len)) == NULL)
129 3ef3f36a 2023-07-05 op return (-1);
130 3ef3f36a 2023-07-05 op
131 3ef3f36a 2023-07-05 op memcpy(b, data, len);
132 3ef3f36a 2023-07-05 op return (0);
133 3ef3f36a 2023-07-05 op }
134 3ef3f36a 2023-07-05 op
135 3ef3f36a 2023-07-05 op int
136 3ef3f36a 2023-07-05 op ibuf_add_buf(struct ibuf *buf, const struct ibuf *from)
137 3ef3f36a 2023-07-05 op {
138 3ef3f36a 2023-07-05 op return ibuf_add(buf, from->buf, from->wpos);
139 3ef3f36a 2023-07-05 op }
140 3ef3f36a 2023-07-05 op
141 3ef3f36a 2023-07-05 op int
142 3ef3f36a 2023-07-05 op ibuf_add_n8(struct ibuf *buf, uint64_t value)
143 3ef3f36a 2023-07-05 op {
144 3ef3f36a 2023-07-05 op uint8_t v;
145 3ef3f36a 2023-07-05 op
146 3ef3f36a 2023-07-05 op if (value > UINT8_MAX) {
147 3ef3f36a 2023-07-05 op errno = EINVAL;
148 3ef3f36a 2023-07-05 op return (-1);
149 3ef3f36a 2023-07-05 op }
150 3ef3f36a 2023-07-05 op v = value;
151 3ef3f36a 2023-07-05 op return ibuf_add(buf, &v, sizeof(v));
152 3ef3f36a 2023-07-05 op }
153 3ef3f36a 2023-07-05 op
154 3ef3f36a 2023-07-05 op int
155 3ef3f36a 2023-07-05 op ibuf_add_n16(struct ibuf *buf, uint64_t value)
156 3ef3f36a 2023-07-05 op {
157 3ef3f36a 2023-07-05 op uint16_t v;
158 3ef3f36a 2023-07-05 op
159 3ef3f36a 2023-07-05 op if (value > UINT16_MAX) {
160 3ef3f36a 2023-07-05 op errno = EINVAL;
161 3ef3f36a 2023-07-05 op return (-1);
162 3ef3f36a 2023-07-05 op }
163 3ef3f36a 2023-07-05 op v = htobe16(value);
164 3ef3f36a 2023-07-05 op return ibuf_add(buf, &v, sizeof(v));
165 3ef3f36a 2023-07-05 op }
166 3ef3f36a 2023-07-05 op
167 3ef3f36a 2023-07-05 op int
168 3ef3f36a 2023-07-05 op ibuf_add_n32(struct ibuf *buf, uint64_t value)
169 3ef3f36a 2023-07-05 op {
170 3ef3f36a 2023-07-05 op uint32_t v;
171 3ef3f36a 2023-07-05 op
172 3ef3f36a 2023-07-05 op if (value > UINT32_MAX) {
173 3ef3f36a 2023-07-05 op errno = EINVAL;
174 3ef3f36a 2023-07-05 op return (-1);
175 3ef3f36a 2023-07-05 op }
176 3ef3f36a 2023-07-05 op v = htobe32(value);
177 3ef3f36a 2023-07-05 op return ibuf_add(buf, &v, sizeof(v));
178 3ef3f36a 2023-07-05 op }
179 3ef3f36a 2023-07-05 op
180 3ef3f36a 2023-07-05 op int
181 3ef3f36a 2023-07-05 op ibuf_add_n64(struct ibuf *buf, uint64_t value)
182 3ef3f36a 2023-07-05 op {
183 3ef3f36a 2023-07-05 op value = htobe64(value);
184 3ef3f36a 2023-07-05 op return ibuf_add(buf, &value, sizeof(value));
185 3ef3f36a 2023-07-05 op }
186 3ef3f36a 2023-07-05 op
187 3ef3f36a 2023-07-05 op int
188 3ef3f36a 2023-07-05 op ibuf_add_zero(struct ibuf *buf, size_t len)
189 3ef3f36a 2023-07-05 op {
190 3ef3f36a 2023-07-05 op void *b;
191 3ef3f36a 2023-07-05 op
192 3ef3f36a 2023-07-05 op if ((b = ibuf_reserve(buf, len)) == NULL)
193 3ef3f36a 2023-07-05 op return (-1);
194 3ef3f36a 2023-07-05 op return (0);
195 3ef3f36a 2023-07-05 op }
196 3ef3f36a 2023-07-05 op
197 dd038bc6 2021-09-21 thomas.ad void *
198 dd038bc6 2021-09-21 thomas.ad ibuf_seek(struct ibuf *buf, size_t pos, size_t len)
199 dd038bc6 2021-09-21 thomas.ad {
200 dd038bc6 2021-09-21 thomas.ad /* only allowed to seek in already written parts */
201 3ef3f36a 2023-07-05 op if (len > SIZE_MAX - pos || pos + len > buf->wpos) {
202 3ef3f36a 2023-07-05 op errno = ERANGE;
203 dd038bc6 2021-09-21 thomas.ad return (NULL);
204 3ef3f36a 2023-07-05 op }
205 dd038bc6 2021-09-21 thomas.ad
206 dd038bc6 2021-09-21 thomas.ad return (buf->buf + pos);
207 dd038bc6 2021-09-21 thomas.ad }
208 dd038bc6 2021-09-21 thomas.ad
209 3ef3f36a 2023-07-05 op int
210 3ef3f36a 2023-07-05 op ibuf_set(struct ibuf *buf, size_t pos, const void *data, size_t len)
211 3ef3f36a 2023-07-05 op {
212 3ef3f36a 2023-07-05 op void *b;
213 3ef3f36a 2023-07-05 op
214 3ef3f36a 2023-07-05 op if ((b = ibuf_seek(buf, pos, len)) == NULL)
215 3ef3f36a 2023-07-05 op return (-1);
216 3ef3f36a 2023-07-05 op
217 3ef3f36a 2023-07-05 op memcpy(b, data, len);
218 3ef3f36a 2023-07-05 op return (0);
219 3ef3f36a 2023-07-05 op }
220 3ef3f36a 2023-07-05 op
221 3ef3f36a 2023-07-05 op int
222 3ef3f36a 2023-07-05 op ibuf_set_n8(struct ibuf *buf, size_t pos, uint64_t value)
223 3ef3f36a 2023-07-05 op {
224 3ef3f36a 2023-07-05 op uint8_t v;
225 3ef3f36a 2023-07-05 op
226 3ef3f36a 2023-07-05 op if (value > UINT8_MAX) {
227 3ef3f36a 2023-07-05 op errno = EINVAL;
228 3ef3f36a 2023-07-05 op return (-1);
229 3ef3f36a 2023-07-05 op }
230 3ef3f36a 2023-07-05 op v = value;
231 3ef3f36a 2023-07-05 op return (ibuf_set(buf, pos, &v, sizeof(v)));
232 3ef3f36a 2023-07-05 op }
233 3ef3f36a 2023-07-05 op
234 3ef3f36a 2023-07-05 op int
235 3ef3f36a 2023-07-05 op ibuf_set_n16(struct ibuf *buf, size_t pos, uint64_t value)
236 3ef3f36a 2023-07-05 op {
237 3ef3f36a 2023-07-05 op uint16_t v;
238 3ef3f36a 2023-07-05 op
239 3ef3f36a 2023-07-05 op if (value > UINT16_MAX) {
240 3ef3f36a 2023-07-05 op errno = EINVAL;
241 3ef3f36a 2023-07-05 op return (-1);
242 3ef3f36a 2023-07-05 op }
243 3ef3f36a 2023-07-05 op v = htobe16(value);
244 3ef3f36a 2023-07-05 op return (ibuf_set(buf, pos, &v, sizeof(v)));
245 3ef3f36a 2023-07-05 op }
246 3ef3f36a 2023-07-05 op
247 3ef3f36a 2023-07-05 op int
248 3ef3f36a 2023-07-05 op ibuf_set_n32(struct ibuf *buf, size_t pos, uint64_t value)
249 3ef3f36a 2023-07-05 op {
250 3ef3f36a 2023-07-05 op uint32_t v;
251 3ef3f36a 2023-07-05 op
252 3ef3f36a 2023-07-05 op if (value > UINT32_MAX) {
253 3ef3f36a 2023-07-05 op errno = EINVAL;
254 3ef3f36a 2023-07-05 op return (-1);
255 3ef3f36a 2023-07-05 op }
256 3ef3f36a 2023-07-05 op v = htobe32(value);
257 3ef3f36a 2023-07-05 op return (ibuf_set(buf, pos, &v, sizeof(v)));
258 3ef3f36a 2023-07-05 op }
259 3ef3f36a 2023-07-05 op
260 3ef3f36a 2023-07-05 op int
261 3ef3f36a 2023-07-05 op ibuf_set_n64(struct ibuf *buf, size_t pos, uint64_t value)
262 3ef3f36a 2023-07-05 op {
263 3ef3f36a 2023-07-05 op value = htobe64(value);
264 3ef3f36a 2023-07-05 op return (ibuf_set(buf, pos, &value, sizeof(value)));
265 3ef3f36a 2023-07-05 op }
266 3ef3f36a 2023-07-05 op
267 3ef3f36a 2023-07-05 op void *
268 3ef3f36a 2023-07-05 op ibuf_data(struct ibuf *buf)
269 3ef3f36a 2023-07-05 op {
270 3ef3f36a 2023-07-05 op return (buf->buf);
271 3ef3f36a 2023-07-05 op }
272 3ef3f36a 2023-07-05 op
273 dd038bc6 2021-09-21 thomas.ad size_t
274 dd038bc6 2021-09-21 thomas.ad ibuf_size(struct ibuf *buf)
275 dd038bc6 2021-09-21 thomas.ad {
276 dd038bc6 2021-09-21 thomas.ad return (buf->wpos);
277 dd038bc6 2021-09-21 thomas.ad }
278 dd038bc6 2021-09-21 thomas.ad
279 dd038bc6 2021-09-21 thomas.ad size_t
280 dd038bc6 2021-09-21 thomas.ad ibuf_left(struct ibuf *buf)
281 dd038bc6 2021-09-21 thomas.ad {
282 dd038bc6 2021-09-21 thomas.ad return (buf->max - buf->wpos);
283 dd038bc6 2021-09-21 thomas.ad }
284 dd038bc6 2021-09-21 thomas.ad
285 dd038bc6 2021-09-21 thomas.ad void
286 dd038bc6 2021-09-21 thomas.ad ibuf_close(struct msgbuf *msgbuf, struct ibuf *buf)
287 dd038bc6 2021-09-21 thomas.ad {
288 dd038bc6 2021-09-21 thomas.ad ibuf_enqueue(msgbuf, buf);
289 dd038bc6 2021-09-21 thomas.ad }
290 dd038bc6 2021-09-21 thomas.ad
291 3ef3f36a 2023-07-05 op void
292 3ef3f36a 2023-07-05 op ibuf_free(struct ibuf *buf)
293 3ef3f36a 2023-07-05 op {
294 3ef3f36a 2023-07-05 op if (buf == NULL)
295 3ef3f36a 2023-07-05 op return;
296 3ef3f36a 2023-07-05 op if (buf->fd != -1)
297 3ef3f36a 2023-07-05 op close(buf->fd);
298 3ef3f36a 2023-07-05 op freezero(buf->buf, buf->size);
299 3ef3f36a 2023-07-05 op free(buf);
300 3ef3f36a 2023-07-05 op }
301 3ef3f36a 2023-07-05 op
302 dd038bc6 2021-09-21 thomas.ad int
303 3ef3f36a 2023-07-05 op ibuf_fd_avail(struct ibuf *buf)
304 3ef3f36a 2023-07-05 op {
305 3ef3f36a 2023-07-05 op return (buf->fd != -1);
306 3ef3f36a 2023-07-05 op }
307 3ef3f36a 2023-07-05 op
308 3ef3f36a 2023-07-05 op int
309 3ef3f36a 2023-07-05 op ibuf_fd_get(struct ibuf *buf)
310 3ef3f36a 2023-07-05 op {
311 3ef3f36a 2023-07-05 op int fd;
312 3ef3f36a 2023-07-05 op
313 3ef3f36a 2023-07-05 op fd = buf->fd;
314 3ef3f36a 2023-07-05 op buf->fd = -1;
315 3ef3f36a 2023-07-05 op return (fd);
316 3ef3f36a 2023-07-05 op }
317 3ef3f36a 2023-07-05 op
318 3ef3f36a 2023-07-05 op void
319 3ef3f36a 2023-07-05 op ibuf_fd_set(struct ibuf *buf, int fd)
320 3ef3f36a 2023-07-05 op {
321 3ef3f36a 2023-07-05 op if (buf->fd != -1)
322 3ef3f36a 2023-07-05 op close(buf->fd);
323 3ef3f36a 2023-07-05 op buf->fd = fd;
324 3ef3f36a 2023-07-05 op }
325 3ef3f36a 2023-07-05 op
326 3ef3f36a 2023-07-05 op int
327 dd038bc6 2021-09-21 thomas.ad ibuf_write(struct msgbuf *msgbuf)
328 dd038bc6 2021-09-21 thomas.ad {
329 dd038bc6 2021-09-21 thomas.ad struct iovec iov[IOV_MAX];
330 dd038bc6 2021-09-21 thomas.ad struct ibuf *buf;
331 dd038bc6 2021-09-21 thomas.ad unsigned int i = 0;
332 dd038bc6 2021-09-21 thomas.ad ssize_t n;
333 dd038bc6 2021-09-21 thomas.ad
334 dd038bc6 2021-09-21 thomas.ad memset(&iov, 0, sizeof(iov));
335 dd038bc6 2021-09-21 thomas.ad TAILQ_FOREACH(buf, &msgbuf->bufs, entry) {
336 dd038bc6 2021-09-21 thomas.ad if (i >= IOV_MAX)
337 dd038bc6 2021-09-21 thomas.ad break;
338 dd038bc6 2021-09-21 thomas.ad iov[i].iov_base = buf->buf + buf->rpos;
339 dd038bc6 2021-09-21 thomas.ad iov[i].iov_len = buf->wpos - buf->rpos;
340 dd038bc6 2021-09-21 thomas.ad i++;
341 dd038bc6 2021-09-21 thomas.ad }
342 dd038bc6 2021-09-21 thomas.ad
343 dd038bc6 2021-09-21 thomas.ad again:
344 dd038bc6 2021-09-21 thomas.ad if ((n = writev(msgbuf->fd, iov, i)) == -1) {
345 dd038bc6 2021-09-21 thomas.ad if (errno == EINTR)
346 dd038bc6 2021-09-21 thomas.ad goto again;
347 dd038bc6 2021-09-21 thomas.ad if (errno == ENOBUFS)
348 dd038bc6 2021-09-21 thomas.ad errno = EAGAIN;
349 dd038bc6 2021-09-21 thomas.ad return (-1);
350 dd038bc6 2021-09-21 thomas.ad }
351 dd038bc6 2021-09-21 thomas.ad
352 dd038bc6 2021-09-21 thomas.ad if (n == 0) { /* connection closed */
353 dd038bc6 2021-09-21 thomas.ad errno = 0;
354 dd038bc6 2021-09-21 thomas.ad return (0);
355 dd038bc6 2021-09-21 thomas.ad }
356 dd038bc6 2021-09-21 thomas.ad
357 dd038bc6 2021-09-21 thomas.ad msgbuf_drain(msgbuf, n);
358 dd038bc6 2021-09-21 thomas.ad
359 dd038bc6 2021-09-21 thomas.ad return (1);
360 dd038bc6 2021-09-21 thomas.ad }
361 dd038bc6 2021-09-21 thomas.ad
362 dd038bc6 2021-09-21 thomas.ad void
363 dd038bc6 2021-09-21 thomas.ad msgbuf_init(struct msgbuf *msgbuf)
364 dd038bc6 2021-09-21 thomas.ad {
365 dd038bc6 2021-09-21 thomas.ad msgbuf->queued = 0;
366 dd038bc6 2021-09-21 thomas.ad msgbuf->fd = -1;
367 dd038bc6 2021-09-21 thomas.ad TAILQ_INIT(&msgbuf->bufs);
368 dd038bc6 2021-09-21 thomas.ad }
369 dd038bc6 2021-09-21 thomas.ad
370 3ef3f36a 2023-07-05 op static void
371 dd038bc6 2021-09-21 thomas.ad msgbuf_drain(struct msgbuf *msgbuf, size_t n)
372 dd038bc6 2021-09-21 thomas.ad {
373 dd038bc6 2021-09-21 thomas.ad struct ibuf *buf, *next;
374 dd038bc6 2021-09-21 thomas.ad
375 dd038bc6 2021-09-21 thomas.ad for (buf = TAILQ_FIRST(&msgbuf->bufs); buf != NULL && n > 0;
376 dd038bc6 2021-09-21 thomas.ad buf = next) {
377 dd038bc6 2021-09-21 thomas.ad next = TAILQ_NEXT(buf, entry);
378 3ef3f36a 2023-07-05 op if (n >= buf->wpos - buf->rpos) {
379 dd038bc6 2021-09-21 thomas.ad n -= buf->wpos - buf->rpos;
380 dd038bc6 2021-09-21 thomas.ad ibuf_dequeue(msgbuf, buf);
381 dd038bc6 2021-09-21 thomas.ad } else {
382 dd038bc6 2021-09-21 thomas.ad buf->rpos += n;
383 dd038bc6 2021-09-21 thomas.ad n = 0;
384 dd038bc6 2021-09-21 thomas.ad }
385 dd038bc6 2021-09-21 thomas.ad }
386 dd038bc6 2021-09-21 thomas.ad }
387 dd038bc6 2021-09-21 thomas.ad
388 dd038bc6 2021-09-21 thomas.ad void
389 dd038bc6 2021-09-21 thomas.ad msgbuf_clear(struct msgbuf *msgbuf)
390 dd038bc6 2021-09-21 thomas.ad {
391 dd038bc6 2021-09-21 thomas.ad struct ibuf *buf;
392 dd038bc6 2021-09-21 thomas.ad
393 dd038bc6 2021-09-21 thomas.ad while ((buf = TAILQ_FIRST(&msgbuf->bufs)) != NULL)
394 dd038bc6 2021-09-21 thomas.ad ibuf_dequeue(msgbuf, buf);
395 dd038bc6 2021-09-21 thomas.ad }
396 dd038bc6 2021-09-21 thomas.ad
397 dd038bc6 2021-09-21 thomas.ad int
398 dd038bc6 2021-09-21 thomas.ad msgbuf_write(struct msgbuf *msgbuf)
399 dd038bc6 2021-09-21 thomas.ad {
400 dd038bc6 2021-09-21 thomas.ad struct iovec iov[IOV_MAX];
401 3ef3f36a 2023-07-05 op struct ibuf *buf, *buf0 = NULL;
402 dd038bc6 2021-09-21 thomas.ad unsigned int i = 0;
403 dd038bc6 2021-09-21 thomas.ad ssize_t n;
404 dd038bc6 2021-09-21 thomas.ad struct msghdr msg;
405 dd038bc6 2021-09-21 thomas.ad struct cmsghdr *cmsg;
406 dd038bc6 2021-09-21 thomas.ad union {
407 dd038bc6 2021-09-21 thomas.ad struct cmsghdr hdr;
408 dd038bc6 2021-09-21 thomas.ad char buf[CMSG_SPACE(sizeof(int))];
409 dd038bc6 2021-09-21 thomas.ad } cmsgbuf;
410 dd038bc6 2021-09-21 thomas.ad
411 dd038bc6 2021-09-21 thomas.ad memset(&iov, 0, sizeof(iov));
412 dd038bc6 2021-09-21 thomas.ad memset(&msg, 0, sizeof(msg));
413 dd038bc6 2021-09-21 thomas.ad memset(&cmsgbuf, 0, sizeof(cmsgbuf));
414 dd038bc6 2021-09-21 thomas.ad TAILQ_FOREACH(buf, &msgbuf->bufs, entry) {
415 dd038bc6 2021-09-21 thomas.ad if (i >= IOV_MAX)
416 dd038bc6 2021-09-21 thomas.ad break;
417 3ef3f36a 2023-07-05 op if (i > 0 && buf->fd != -1)
418 3ef3f36a 2023-07-05 op break;
419 dd038bc6 2021-09-21 thomas.ad iov[i].iov_base = buf->buf + buf->rpos;
420 dd038bc6 2021-09-21 thomas.ad iov[i].iov_len = buf->wpos - buf->rpos;
421 dd038bc6 2021-09-21 thomas.ad i++;
422 dd038bc6 2021-09-21 thomas.ad if (buf->fd != -1)
423 3ef3f36a 2023-07-05 op buf0 = buf;
424 dd038bc6 2021-09-21 thomas.ad }
425 dd038bc6 2021-09-21 thomas.ad
426 dd038bc6 2021-09-21 thomas.ad msg.msg_iov = iov;
427 dd038bc6 2021-09-21 thomas.ad msg.msg_iovlen = i;
428 dd038bc6 2021-09-21 thomas.ad
429 3ef3f36a 2023-07-05 op if (buf0 != NULL) {
430 dd038bc6 2021-09-21 thomas.ad msg.msg_control = (caddr_t)&cmsgbuf.buf;
431 dd038bc6 2021-09-21 thomas.ad msg.msg_controllen = sizeof(cmsgbuf.buf);
432 dd038bc6 2021-09-21 thomas.ad cmsg = CMSG_FIRSTHDR(&msg);
433 dd038bc6 2021-09-21 thomas.ad cmsg->cmsg_len = CMSG_LEN(sizeof(int));
434 dd038bc6 2021-09-21 thomas.ad cmsg->cmsg_level = SOL_SOCKET;
435 dd038bc6 2021-09-21 thomas.ad cmsg->cmsg_type = SCM_RIGHTS;
436 3ef3f36a 2023-07-05 op *(int *)CMSG_DATA(cmsg) = buf0->fd;
437 dd038bc6 2021-09-21 thomas.ad }
438 dd038bc6 2021-09-21 thomas.ad
439 dd038bc6 2021-09-21 thomas.ad again:
440 dd038bc6 2021-09-21 thomas.ad if ((n = sendmsg(msgbuf->fd, &msg, 0)) == -1) {
441 dd038bc6 2021-09-21 thomas.ad if (errno == EINTR)
442 dd038bc6 2021-09-21 thomas.ad goto again;
443 dd038bc6 2021-09-21 thomas.ad if (errno == ENOBUFS)
444 dd038bc6 2021-09-21 thomas.ad errno = EAGAIN;
445 dd038bc6 2021-09-21 thomas.ad return (-1);
446 dd038bc6 2021-09-21 thomas.ad }
447 dd038bc6 2021-09-21 thomas.ad
448 dd038bc6 2021-09-21 thomas.ad if (n == 0) { /* connection closed */
449 dd038bc6 2021-09-21 thomas.ad errno = 0;
450 dd038bc6 2021-09-21 thomas.ad return (0);
451 dd038bc6 2021-09-21 thomas.ad }
452 dd038bc6 2021-09-21 thomas.ad
453 dd038bc6 2021-09-21 thomas.ad /*
454 dd038bc6 2021-09-21 thomas.ad * assumption: fd got sent if sendmsg sent anything
455 dd038bc6 2021-09-21 thomas.ad * this works because fds are passed one at a time
456 dd038bc6 2021-09-21 thomas.ad */
457 3ef3f36a 2023-07-05 op if (buf0 != NULL) {
458 3ef3f36a 2023-07-05 op close(buf0->fd);
459 3ef3f36a 2023-07-05 op buf0->fd = -1;
460 dd038bc6 2021-09-21 thomas.ad }
461 dd038bc6 2021-09-21 thomas.ad
462 dd038bc6 2021-09-21 thomas.ad msgbuf_drain(msgbuf, n);
463 dd038bc6 2021-09-21 thomas.ad
464 dd038bc6 2021-09-21 thomas.ad return (1);
465 dd038bc6 2021-09-21 thomas.ad }
466 dd038bc6 2021-09-21 thomas.ad
467 dd038bc6 2021-09-21 thomas.ad static void
468 dd038bc6 2021-09-21 thomas.ad ibuf_enqueue(struct msgbuf *msgbuf, struct ibuf *buf)
469 dd038bc6 2021-09-21 thomas.ad {
470 dd038bc6 2021-09-21 thomas.ad TAILQ_INSERT_TAIL(&msgbuf->bufs, buf, entry);
471 dd038bc6 2021-09-21 thomas.ad msgbuf->queued++;
472 dd038bc6 2021-09-21 thomas.ad }
473 dd038bc6 2021-09-21 thomas.ad
474 dd038bc6 2021-09-21 thomas.ad static void
475 dd038bc6 2021-09-21 thomas.ad ibuf_dequeue(struct msgbuf *msgbuf, struct ibuf *buf)
476 dd038bc6 2021-09-21 thomas.ad {
477 dd038bc6 2021-09-21 thomas.ad TAILQ_REMOVE(&msgbuf->bufs, buf, entry);
478 dd038bc6 2021-09-21 thomas.ad
479 dd038bc6 2021-09-21 thomas.ad msgbuf->queued--;
480 dd038bc6 2021-09-21 thomas.ad ibuf_free(buf);
481 dd038bc6 2021-09-21 thomas.ad }