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