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