Blame


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