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 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 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", 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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