xref: /openbsd/usr.sbin/smtpd/scheduler_proc.c (revision d89ec533)
1 /*	$OpenBSD: scheduler_proc.c,v 1.9 2021/06/14 17:58:16 eric Exp $	*/
2 
3 /*
4  * Copyright (c) 2013 Eric Faurot <eric@openbsd.org>
5  *
6  * Permission to use, copy, modify, and distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 #include <errno.h>
20 #include <string.h>
21 
22 #include "smtpd.h"
23 #include "log.h"
24 
25 static struct imsgbuf	 ibuf;
26 static struct imsg	 imsg;
27 static size_t		 rlen;
28 static char		*rdata;
29 
30 static void
31 scheduler_proc_call(void)
32 {
33 	ssize_t	n;
34 
35 	if (imsg_flush(&ibuf) == -1) {
36 		log_warn("warn: scheduler-proc: imsg_flush");
37 		fatalx("scheduler-proc: exiting");
38 	}
39 
40 	while (1) {
41 		if ((n = imsg_get(&ibuf, &imsg)) == -1) {
42 			log_warn("warn: scheduler-proc: imsg_get");
43 			break;
44 		}
45 		if (n) {
46 			rlen = imsg.hdr.len - IMSG_HEADER_SIZE;
47 			rdata = imsg.data;
48 
49 			if (imsg.hdr.type != PROC_SCHEDULER_OK) {
50 				log_warnx("warn: scheduler-proc: bad response");
51 				break;
52 			}
53 			return;
54 		}
55 
56 		if ((n = imsg_read(&ibuf)) == -1 && errno != EAGAIN) {
57 			log_warn("warn: scheduler-proc: imsg_read");
58 			break;
59 		}
60 
61 		if (n == 0) {
62 			log_warnx("warn: scheduler-proc: pipe closed");
63 			break;
64 		}
65 	}
66 
67 	fatalx("scheduler-proc: exiting");
68 }
69 
70 static void
71 scheduler_proc_read(void *dst, size_t len)
72 {
73 	if (len > rlen) {
74 		log_warnx("warn: scheduler-proc: bad msg len");
75 		fatalx("scheduler-proc: exiting");
76 	}
77 
78 	memmove(dst, rdata, len);
79 	rlen -= len;
80 	rdata += len;
81 }
82 
83 static void
84 scheduler_proc_end(void)
85 {
86 	if (rlen) {
87 		log_warnx("warn: scheduler-proc: bogus data");
88 		fatalx("scheduler-proc: exiting");
89 	}
90 	imsg_free(&imsg);
91 }
92 
93 /*
94  * API
95  */
96 
97 static int
98 scheduler_proc_init(const char *conf)
99 {
100 	int		fd, r;
101 	uint32_t	version;
102 
103 	fd = fork_proc_backend("scheduler", conf, "scheduler-proc");
104 	if (fd == -1)
105 		fatalx("scheduler-proc: exiting");
106 
107 	imsg_init(&ibuf, fd);
108 
109 	version = PROC_SCHEDULER_API_VERSION;
110 	imsg_compose(&ibuf, PROC_SCHEDULER_INIT, 0, 0, -1,
111 	    &version, sizeof(version));
112 	scheduler_proc_call();
113 	scheduler_proc_read(&r, sizeof(r));
114 	scheduler_proc_end();
115 
116 	return (1);
117 }
118 
119 static int
120 scheduler_proc_insert(struct scheduler_info *si)
121 {
122 	int	r;
123 
124 	log_debug("debug: scheduler-proc: PROC_SCHEDULER_INSERT");
125 
126 	imsg_compose(&ibuf, PROC_SCHEDULER_INSERT, 0, 0, -1, si, sizeof(*si));
127 
128 	scheduler_proc_call();
129 	scheduler_proc_read(&r, sizeof(r));
130 	scheduler_proc_end();
131 
132 	return (r);
133 }
134 
135 static size_t
136 scheduler_proc_commit(uint32_t msgid)
137 {
138 	size_t	s;
139 
140 	log_debug("debug: scheduler-proc: PROC_SCHEDULER_COMMIT");
141 
142 	imsg_compose(&ibuf, PROC_SCHEDULER_COMMIT, 0, 0, -1,
143 	    &msgid, sizeof(msgid));
144 
145 	scheduler_proc_call();
146 	scheduler_proc_read(&s, sizeof(s));
147 	scheduler_proc_end();
148 
149 	return (s);
150 }
151 
152 static size_t
153 scheduler_proc_rollback(uint32_t msgid)
154 {
155 	size_t	s;
156 
157 	log_debug("debug: scheduler-proc: PROC_SCHEDULER_ROLLBACK");
158 
159 	imsg_compose(&ibuf, PROC_SCHEDULER_ROLLBACK, 0, 0, -1,
160 	    &msgid, sizeof(msgid));
161 
162 	scheduler_proc_call();
163 	scheduler_proc_read(&s, sizeof(s));
164 	scheduler_proc_end();
165 
166 	return (s);
167 }
168 
169 static int
170 scheduler_proc_update(struct scheduler_info *si)
171 {
172 	int	r;
173 
174 	log_debug("debug: scheduler-proc: PROC_SCHEDULER_UPDATE");
175 
176 	imsg_compose(&ibuf, PROC_SCHEDULER_UPDATE, 0, 0, -1, si, sizeof(*si));
177 
178 	scheduler_proc_call();
179 	scheduler_proc_read(&r, sizeof(r));
180 	if (r == 1)
181 		scheduler_proc_read(si, sizeof(*si));
182 	scheduler_proc_end();
183 
184 	return (r);
185 }
186 
187 static int
188 scheduler_proc_delete(uint64_t evpid)
189 {
190 	int	r;
191 
192 	log_debug("debug: scheduler-proc: PROC_SCHEDULER_DELETE");
193 
194 	imsg_compose(&ibuf, PROC_SCHEDULER_DELETE, 0, 0, -1,
195 	    &evpid, sizeof(evpid));
196 
197 	scheduler_proc_call();
198 	scheduler_proc_read(&r, sizeof(r));
199 	scheduler_proc_end();
200 
201 	return (r);
202 }
203 
204 static int
205 scheduler_proc_hold(uint64_t evpid, uint64_t holdq)
206 {
207 	struct ibuf	*buf;
208 	int		 r;
209 
210 	log_debug("debug: scheduler-proc: PROC_SCHEDULER_HOLD");
211 
212 	buf = imsg_create(&ibuf, PROC_SCHEDULER_HOLD, 0, 0,
213 	    sizeof(evpid) + sizeof(holdq));
214 	if (buf == NULL)
215 		return (-1);
216 	if (imsg_add(buf, &evpid, sizeof(evpid)) == -1)
217 		return (-1);
218 	if (imsg_add(buf, &holdq, sizeof(holdq)) == -1)
219 		return (-1);
220 	imsg_close(&ibuf, buf);
221 
222 	scheduler_proc_call();
223 
224 	scheduler_proc_read(&r, sizeof(r));
225 	scheduler_proc_end();
226 
227 	return (r);
228 }
229 
230 static int
231 scheduler_proc_release(int type, uint64_t holdq, int n)
232 {
233 	struct ibuf	*buf;
234 	int		 r;
235 
236 	log_debug("debug: scheduler-proc: PROC_SCHEDULER_RELEASE");
237 
238 	buf = imsg_create(&ibuf, PROC_SCHEDULER_RELEASE, 0, 0,
239 	    sizeof(holdq) + sizeof(n));
240 	if (buf == NULL)
241 		return (-1);
242 	if (imsg_add(buf, &type, sizeof(type)) == -1)
243 		return (-1);
244 	if (imsg_add(buf, &holdq, sizeof(holdq)) == -1)
245 		return (-1);
246 	if (imsg_add(buf, &n, sizeof(n)) == -1)
247 		return (-1);
248 	imsg_close(&ibuf, buf);
249 
250 	scheduler_proc_call();
251 
252 	scheduler_proc_read(&r, sizeof(r));
253 	scheduler_proc_end();
254 
255 	return (r);
256 }
257 
258 static int
259 scheduler_proc_batch(int typemask, int *delay, size_t *count, uint64_t *evpids, int *types)
260 {
261 	struct ibuf	*buf;
262 	int		 r;
263 
264 	log_debug("debug: scheduler-proc: PROC_SCHEDULER_BATCH");
265 
266 	buf = imsg_create(&ibuf, PROC_SCHEDULER_BATCH, 0, 0,
267 	    sizeof(typemask) + sizeof(*count));
268 	if (buf == NULL)
269 		return (-1);
270 	if (imsg_add(buf, &typemask, sizeof(typemask)) == -1)
271 		return (-1);
272 	if (imsg_add(buf, count, sizeof(*count)) == -1)
273 		return (-1);
274 	imsg_close(&ibuf, buf);
275 
276 	scheduler_proc_call();
277 	scheduler_proc_read(&r, sizeof(r));
278 	scheduler_proc_read(delay, sizeof(*delay));
279 	scheduler_proc_read(count, sizeof(*count));
280 	if (r > 0) {
281 		scheduler_proc_read(evpids, sizeof(*evpids) * (*count));
282 		scheduler_proc_read(types, sizeof(*types) * (*count));
283 	}
284 	scheduler_proc_end();
285 
286 	return (r);
287 }
288 
289 static size_t
290 scheduler_proc_messages(uint32_t from, uint32_t *dst, size_t size)
291 {
292 	struct ibuf	*buf;
293 	size_t		 s;
294 
295 	log_debug("debug: scheduler-proc: PROC_SCHEDULER_MESSAGES");
296 
297 	buf = imsg_create(&ibuf, PROC_SCHEDULER_MESSAGES, 0, 0,
298 	    sizeof(from) + sizeof(size));
299 	if (buf == NULL)
300 		return (-1);
301 	if (imsg_add(buf, &from, sizeof(from)) == -1)
302 		return (-1);
303 	if (imsg_add(buf, &size, sizeof(size)) == -1)
304 		return (-1);
305 	imsg_close(&ibuf, buf);
306 
307 	scheduler_proc_call();
308 
309 	s = rlen / sizeof(*dst);
310 	scheduler_proc_read(dst, s * sizeof(*dst));
311 	scheduler_proc_end();
312 
313 	return (s);
314 }
315 
316 static size_t
317 scheduler_proc_envelopes(uint64_t from, struct evpstate *dst, size_t size)
318 {
319 	struct ibuf	*buf;
320 	size_t		 s;
321 
322 	log_debug("debug: scheduler-proc: PROC_SCHEDULER_ENVELOPES");
323 
324 	buf = imsg_create(&ibuf, PROC_SCHEDULER_ENVELOPES, 0, 0,
325 	    sizeof(from) + sizeof(size));
326 	if (buf == NULL)
327 		return (-1);
328 	if (imsg_add(buf, &from, sizeof(from)) == -1)
329 		return (-1);
330 	if (imsg_add(buf, &size, sizeof(size)) == -1)
331 		return (-1);
332 	imsg_close(&ibuf, buf);
333 
334 	scheduler_proc_call();
335 
336 	s = rlen / sizeof(*dst);
337 	scheduler_proc_read(dst, s * sizeof(*dst));
338 	scheduler_proc_end();
339 
340 	return (s);
341 }
342 
343 static int
344 scheduler_proc_schedule(uint64_t evpid)
345 {
346 	int	r;
347 
348 	log_debug("debug: scheduler-proc: PROC_SCHEDULER_SCHEDULE");
349 
350 	imsg_compose(&ibuf, PROC_SCHEDULER_SCHEDULE, 0, 0, -1,
351 	    &evpid, sizeof(evpid));
352 
353 	scheduler_proc_call();
354 
355 	scheduler_proc_read(&r, sizeof(r));
356 	scheduler_proc_end();
357 
358 	return (r);
359 }
360 
361 static int
362 scheduler_proc_remove(uint64_t evpid)
363 {
364 	int	r;
365 
366 	log_debug("debug: scheduler-proc: PROC_SCHEDULER_REMOVE");
367 
368 	imsg_compose(&ibuf, PROC_SCHEDULER_REMOVE, 0, 0, -1,
369 	    &evpid, sizeof(evpid));
370 
371 	scheduler_proc_call();
372 
373 	scheduler_proc_read(&r, sizeof(r));
374 	scheduler_proc_end();
375 
376 	return (r);
377 }
378 
379 static int
380 scheduler_proc_suspend(uint64_t evpid)
381 {
382 	int	r;
383 
384 	log_debug("debug: scheduler-proc: PROC_SCHEDULER_SUSPEND");
385 
386 	imsg_compose(&ibuf, PROC_SCHEDULER_SUSPEND, 0, 0, -1,
387 	    &evpid, sizeof(evpid));
388 
389 	scheduler_proc_call();
390 
391 	scheduler_proc_read(&r, sizeof(r));
392 	scheduler_proc_end();
393 
394 	return (r);
395 }
396 
397 static int
398 scheduler_proc_resume(uint64_t evpid)
399 {
400 	int	r;
401 
402 	log_debug("debug: scheduler-proc: PROC_SCHEDULER_RESUME");
403 
404 	imsg_compose(&ibuf, PROC_SCHEDULER_RESUME, 0, 0, -1,
405 	    &evpid, sizeof(evpid));
406 
407 	scheduler_proc_call();
408 
409 	scheduler_proc_read(&r, sizeof(r));
410 	scheduler_proc_end();
411 
412 	return (r);
413 }
414 
415 struct scheduler_backend scheduler_backend_proc = {
416 	scheduler_proc_init,
417 	scheduler_proc_insert,
418 	scheduler_proc_commit,
419 	scheduler_proc_rollback,
420 	scheduler_proc_update,
421 	scheduler_proc_delete,
422 	scheduler_proc_hold,
423 	scheduler_proc_release,
424 	scheduler_proc_batch,
425 	scheduler_proc_messages,
426 	scheduler_proc_envelopes,
427 	scheduler_proc_schedule,
428 	scheduler_proc_remove,
429 	scheduler_proc_suspend,
430 	scheduler_proc_resume,
431 };
432