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