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