xref: /openbsd/usr.sbin/smtpd/scheduler_proc.c (revision bf921b2a)
1 /*	$OpenBSD: scheduler_proc.c,v 1.13 2024/11/21 13:42:22 claudio 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
scheduler_proc_call(void)31 scheduler_proc_call(void)
32 {
33 	ssize_t	n;
34 
35 	if (imsgbuf_flush(&ibuf) == -1) {
36 		log_warn("warn: scheduler-proc: imsgbuf_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 = imsgbuf_read(&ibuf)) == -1) {
57 			log_warn("warn: scheduler-proc: imsgbuf_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
scheduler_proc_read(void * dst,size_t len)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
scheduler_proc_end(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
scheduler_proc_init(const char * conf)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", 0);
104 	if (fd == -1)
105 		fatalx("scheduler-proc: exiting");
106 
107 	if (imsgbuf_init(&ibuf, fd) == -1)
108 		fatal("scheduler-proc: exiting");
109 	imsgbuf_allow_fdpass(&ibuf);
110 
111 	version = PROC_SCHEDULER_API_VERSION;
112 	imsg_compose(&ibuf, PROC_SCHEDULER_INIT, 0, 0, -1,
113 	    &version, sizeof(version));
114 	scheduler_proc_call();
115 	scheduler_proc_read(&r, sizeof(r));
116 	scheduler_proc_end();
117 
118 	return (1);
119 }
120 
121 static int
scheduler_proc_insert(struct scheduler_info * si)122 scheduler_proc_insert(struct scheduler_info *si)
123 {
124 	int	r;
125 
126 	log_debug("debug: scheduler-proc: PROC_SCHEDULER_INSERT");
127 
128 	imsg_compose(&ibuf, PROC_SCHEDULER_INSERT, 0, 0, -1, si, sizeof(*si));
129 
130 	scheduler_proc_call();
131 	scheduler_proc_read(&r, sizeof(r));
132 	scheduler_proc_end();
133 
134 	return (r);
135 }
136 
137 static size_t
scheduler_proc_commit(uint32_t msgid)138 scheduler_proc_commit(uint32_t msgid)
139 {
140 	size_t	s;
141 
142 	log_debug("debug: scheduler-proc: PROC_SCHEDULER_COMMIT");
143 
144 	imsg_compose(&ibuf, PROC_SCHEDULER_COMMIT, 0, 0, -1,
145 	    &msgid, sizeof(msgid));
146 
147 	scheduler_proc_call();
148 	scheduler_proc_read(&s, sizeof(s));
149 	scheduler_proc_end();
150 
151 	return (s);
152 }
153 
154 static size_t
scheduler_proc_rollback(uint32_t msgid)155 scheduler_proc_rollback(uint32_t msgid)
156 {
157 	size_t	s;
158 
159 	log_debug("debug: scheduler-proc: PROC_SCHEDULER_ROLLBACK");
160 
161 	imsg_compose(&ibuf, PROC_SCHEDULER_ROLLBACK, 0, 0, -1,
162 	    &msgid, sizeof(msgid));
163 
164 	scheduler_proc_call();
165 	scheduler_proc_read(&s, sizeof(s));
166 	scheduler_proc_end();
167 
168 	return (s);
169 }
170 
171 static int
scheduler_proc_update(struct scheduler_info * si)172 scheduler_proc_update(struct scheduler_info *si)
173 {
174 	int	r;
175 
176 	log_debug("debug: scheduler-proc: PROC_SCHEDULER_UPDATE");
177 
178 	imsg_compose(&ibuf, PROC_SCHEDULER_UPDATE, 0, 0, -1, si, sizeof(*si));
179 
180 	scheduler_proc_call();
181 	scheduler_proc_read(&r, sizeof(r));
182 	if (r == 1)
183 		scheduler_proc_read(si, sizeof(*si));
184 	scheduler_proc_end();
185 
186 	return (r);
187 }
188 
189 static int
scheduler_proc_delete(uint64_t evpid)190 scheduler_proc_delete(uint64_t evpid)
191 {
192 	int	r;
193 
194 	log_debug("debug: scheduler-proc: PROC_SCHEDULER_DELETE");
195 
196 	imsg_compose(&ibuf, PROC_SCHEDULER_DELETE, 0, 0, -1,
197 	    &evpid, sizeof(evpid));
198 
199 	scheduler_proc_call();
200 	scheduler_proc_read(&r, sizeof(r));
201 	scheduler_proc_end();
202 
203 	return (r);
204 }
205 
206 static int
scheduler_proc_hold(uint64_t evpid,uint64_t holdq)207 scheduler_proc_hold(uint64_t evpid, uint64_t holdq)
208 {
209 	struct ibuf	*buf;
210 	int		 r;
211 
212 	log_debug("debug: scheduler-proc: PROC_SCHEDULER_HOLD");
213 
214 	buf = imsg_create(&ibuf, PROC_SCHEDULER_HOLD, 0, 0,
215 	    sizeof(evpid) + sizeof(holdq));
216 	if (buf == NULL)
217 		return (-1);
218 	if (imsg_add(buf, &evpid, sizeof(evpid)) == -1)
219 		return (-1);
220 	if (imsg_add(buf, &holdq, sizeof(holdq)) == -1)
221 		return (-1);
222 	imsg_close(&ibuf, buf);
223 
224 	scheduler_proc_call();
225 
226 	scheduler_proc_read(&r, sizeof(r));
227 	scheduler_proc_end();
228 
229 	return (r);
230 }
231 
232 static int
scheduler_proc_release(int type,uint64_t holdq,int n)233 scheduler_proc_release(int type, uint64_t holdq, int n)
234 {
235 	struct ibuf	*buf;
236 	int		 r;
237 
238 	log_debug("debug: scheduler-proc: PROC_SCHEDULER_RELEASE");
239 
240 	buf = imsg_create(&ibuf, PROC_SCHEDULER_RELEASE, 0, 0,
241 	    sizeof(holdq) + sizeof(n));
242 	if (buf == NULL)
243 		return (-1);
244 	if (imsg_add(buf, &type, sizeof(type)) == -1)
245 		return (-1);
246 	if (imsg_add(buf, &holdq, sizeof(holdq)) == -1)
247 		return (-1);
248 	if (imsg_add(buf, &n, sizeof(n)) == -1)
249 		return (-1);
250 	imsg_close(&ibuf, buf);
251 
252 	scheduler_proc_call();
253 
254 	scheduler_proc_read(&r, sizeof(r));
255 	scheduler_proc_end();
256 
257 	return (r);
258 }
259 
260 static int
scheduler_proc_batch(int typemask,int * delay,size_t * count,uint64_t * evpids,int * types)261 scheduler_proc_batch(int typemask, int *delay, size_t *count, uint64_t *evpids, int *types)
262 {
263 	struct ibuf	*buf;
264 	int		 r;
265 
266 	log_debug("debug: scheduler-proc: PROC_SCHEDULER_BATCH");
267 
268 	buf = imsg_create(&ibuf, PROC_SCHEDULER_BATCH, 0, 0,
269 	    sizeof(typemask) + sizeof(*count));
270 	if (buf == NULL)
271 		return (-1);
272 	if (imsg_add(buf, &typemask, sizeof(typemask)) == -1)
273 		return (-1);
274 	if (imsg_add(buf, count, sizeof(*count)) == -1)
275 		return (-1);
276 	imsg_close(&ibuf, buf);
277 
278 	scheduler_proc_call();
279 	scheduler_proc_read(&r, sizeof(r));
280 	scheduler_proc_read(delay, sizeof(*delay));
281 	scheduler_proc_read(count, sizeof(*count));
282 	if (r > 0) {
283 		scheduler_proc_read(evpids, sizeof(*evpids) * (*count));
284 		scheduler_proc_read(types, sizeof(*types) * (*count));
285 	}
286 	scheduler_proc_end();
287 
288 	return (r);
289 }
290 
291 static size_t
scheduler_proc_messages(uint32_t from,uint32_t * dst,size_t size)292 scheduler_proc_messages(uint32_t from, uint32_t *dst, size_t size)
293 {
294 	struct ibuf	*buf;
295 	size_t		 s;
296 
297 	log_debug("debug: scheduler-proc: PROC_SCHEDULER_MESSAGES");
298 
299 	buf = imsg_create(&ibuf, PROC_SCHEDULER_MESSAGES, 0, 0,
300 	    sizeof(from) + sizeof(size));
301 	if (buf == NULL)
302 		return (-1);
303 	if (imsg_add(buf, &from, sizeof(from)) == -1)
304 		return (-1);
305 	if (imsg_add(buf, &size, sizeof(size)) == -1)
306 		return (-1);
307 	imsg_close(&ibuf, buf);
308 
309 	scheduler_proc_call();
310 
311 	s = rlen / sizeof(*dst);
312 	scheduler_proc_read(dst, s * sizeof(*dst));
313 	scheduler_proc_end();
314 
315 	return (s);
316 }
317 
318 static size_t
scheduler_proc_envelopes(uint64_t from,struct evpstate * dst,size_t size)319 scheduler_proc_envelopes(uint64_t from, struct evpstate *dst, size_t size)
320 {
321 	struct ibuf	*buf;
322 	size_t		 s;
323 
324 	log_debug("debug: scheduler-proc: PROC_SCHEDULER_ENVELOPES");
325 
326 	buf = imsg_create(&ibuf, PROC_SCHEDULER_ENVELOPES, 0, 0,
327 	    sizeof(from) + sizeof(size));
328 	if (buf == NULL)
329 		return (-1);
330 	if (imsg_add(buf, &from, sizeof(from)) == -1)
331 		return (-1);
332 	if (imsg_add(buf, &size, sizeof(size)) == -1)
333 		return (-1);
334 	imsg_close(&ibuf, buf);
335 
336 	scheduler_proc_call();
337 
338 	s = rlen / sizeof(*dst);
339 	scheduler_proc_read(dst, s * sizeof(*dst));
340 	scheduler_proc_end();
341 
342 	return (s);
343 }
344 
345 static int
scheduler_proc_schedule(uint64_t evpid)346 scheduler_proc_schedule(uint64_t evpid)
347 {
348 	int	r;
349 
350 	log_debug("debug: scheduler-proc: PROC_SCHEDULER_SCHEDULE");
351 
352 	imsg_compose(&ibuf, PROC_SCHEDULER_SCHEDULE, 0, 0, -1,
353 	    &evpid, sizeof(evpid));
354 
355 	scheduler_proc_call();
356 
357 	scheduler_proc_read(&r, sizeof(r));
358 	scheduler_proc_end();
359 
360 	return (r);
361 }
362 
363 static int
scheduler_proc_remove(uint64_t evpid)364 scheduler_proc_remove(uint64_t evpid)
365 {
366 	int	r;
367 
368 	log_debug("debug: scheduler-proc: PROC_SCHEDULER_REMOVE");
369 
370 	imsg_compose(&ibuf, PROC_SCHEDULER_REMOVE, 0, 0, -1,
371 	    &evpid, sizeof(evpid));
372 
373 	scheduler_proc_call();
374 
375 	scheduler_proc_read(&r, sizeof(r));
376 	scheduler_proc_end();
377 
378 	return (r);
379 }
380 
381 static int
scheduler_proc_suspend(uint64_t evpid)382 scheduler_proc_suspend(uint64_t evpid)
383 {
384 	int	r;
385 
386 	log_debug("debug: scheduler-proc: PROC_SCHEDULER_SUSPEND");
387 
388 	imsg_compose(&ibuf, PROC_SCHEDULER_SUSPEND, 0, 0, -1,
389 	    &evpid, sizeof(evpid));
390 
391 	scheduler_proc_call();
392 
393 	scheduler_proc_read(&r, sizeof(r));
394 	scheduler_proc_end();
395 
396 	return (r);
397 }
398 
399 static int
scheduler_proc_resume(uint64_t evpid)400 scheduler_proc_resume(uint64_t evpid)
401 {
402 	int	r;
403 
404 	log_debug("debug: scheduler-proc: PROC_SCHEDULER_RESUME");
405 
406 	imsg_compose(&ibuf, PROC_SCHEDULER_RESUME, 0, 0, -1,
407 	    &evpid, sizeof(evpid));
408 
409 	scheduler_proc_call();
410 
411 	scheduler_proc_read(&r, sizeof(r));
412 	scheduler_proc_end();
413 
414 	return (r);
415 }
416 
417 struct scheduler_backend scheduler_backend_proc = {
418 	scheduler_proc_init,
419 	scheduler_proc_insert,
420 	scheduler_proc_commit,
421 	scheduler_proc_rollback,
422 	scheduler_proc_update,
423 	scheduler_proc_delete,
424 	scheduler_proc_hold,
425 	scheduler_proc_release,
426 	scheduler_proc_batch,
427 	scheduler_proc_messages,
428 	scheduler_proc_envelopes,
429 	scheduler_proc_schedule,
430 	scheduler_proc_remove,
431 	scheduler_proc_suspend,
432 	scheduler_proc_resume,
433 };
434