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