1 /* $OpenBSD: control.c,v 1.39 2009/10/25 19:46:31 gilles Exp $ */ 2 3 /* 4 * Copyright (c) 2008 Pierre-Yves Ritschard <pyr@openbsd.org> 5 * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> 6 * 7 * Permission to use, copy, modify, and distribute this software for any 8 * purpose with or without fee is hereby granted, provided that the above 9 * copyright notice and this permission notice appear in all copies. 10 * 11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18 */ 19 20 #include <sys/types.h> 21 #include <sys/queue.h> 22 #include <sys/tree.h> 23 #include <sys/param.h> 24 #include <sys/stat.h> 25 #include <sys/socket.h> 26 #include <sys/un.h> 27 28 #include <errno.h> 29 #include <event.h> 30 #include <fcntl.h> 31 #include <pwd.h> 32 #include <signal.h> 33 #include <stdio.h> 34 #include <stdlib.h> 35 #include <string.h> 36 #include <unistd.h> 37 38 #include "smtpd.h" 39 40 #define CONTROL_BACKLOG 5 41 42 /* control specific headers */ 43 struct { 44 struct event ev; 45 int fd; 46 } control_state; 47 48 __dead void control_shutdown(void); 49 int control_init(void); 50 int control_listen(struct smtpd *); 51 void control_cleanup(void); 52 void control_accept(int, short, void *); 53 struct ctl_conn *control_connbyfd(int); 54 void control_close(int); 55 void control_sig_handler(int, short, void *); 56 void control_dispatch_ext(int, short, void *); 57 void control_dispatch_lka(int, short, void *); 58 void control_dispatch_mfa(int, short, void *); 59 void control_dispatch_queue(int, short, void *); 60 void control_dispatch_runner(int, short, void *); 61 void control_dispatch_smtp(int, short, void *); 62 void control_dispatch_parent(int, short, void *); 63 64 struct ctl_connlist ctl_conns; 65 66 void 67 control_sig_handler(int sig, short event, void *p) 68 { 69 switch (sig) { 70 case SIGINT: 71 case SIGTERM: 72 control_shutdown(); 73 break; 74 default: 75 fatalx("control_sig_handler: unexpected signal"); 76 } 77 } 78 79 80 pid_t 81 control(struct smtpd *env) 82 { 83 struct sockaddr_un sun; 84 int fd; 85 mode_t old_umask; 86 pid_t pid; 87 struct passwd *pw; 88 struct event ev_sigint; 89 struct event ev_sigterm; 90 struct peer peers [] = { 91 { PROC_QUEUE, control_dispatch_queue }, 92 { PROC_RUNNER, control_dispatch_runner }, 93 { PROC_SMTP, control_dispatch_smtp }, 94 { PROC_MFA, control_dispatch_mfa }, 95 { PROC_PARENT, control_dispatch_parent }, 96 }; 97 98 switch (pid = fork()) { 99 case -1: 100 fatal("control: cannot fork"); 101 case 0: 102 break; 103 default: 104 return (pid); 105 } 106 107 purge_config(env, PURGE_EVERYTHING); 108 109 pw = env->sc_pw; 110 111 if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) 112 fatal("control: socket"); 113 114 sun.sun_family = AF_UNIX; 115 if (strlcpy(sun.sun_path, SMTPD_SOCKET, 116 sizeof(sun.sun_path)) >= sizeof(sun.sun_path)) 117 fatal("control: socket name too long"); 118 119 if (unlink(SMTPD_SOCKET) == -1) 120 if (errno != ENOENT) 121 fatal("control: cannot unlink socket"); 122 123 old_umask = umask(S_IXUSR|S_IXGRP|S_IWOTH|S_IROTH|S_IXOTH); 124 if (bind(fd, (struct sockaddr *)&sun, sizeof(sun)) == -1) { 125 (void)umask(old_umask); 126 fatal("control: bind"); 127 } 128 (void)umask(old_umask); 129 130 if (chmod(SMTPD_SOCKET, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH) == -1) { 131 (void)unlink(SMTPD_SOCKET); 132 fatal("control: chmod"); 133 } 134 135 session_socket_blockmode(fd, BM_NONBLOCK); 136 control_state.fd = fd; 137 138 #ifndef DEBUG 139 if (chroot(pw->pw_dir) == -1) 140 fatal("control: chroot"); 141 if (chdir("/") == -1) 142 fatal("control: chdir(\"/\")"); 143 #else 144 #warning disabling privilege revocation and chroot in DEBUG MODE 145 #endif 146 147 smtpd_process = PROC_CONTROL; 148 setproctitle("%s", env->sc_title[smtpd_process]); 149 150 #ifndef DEBUG 151 if (setgroups(1, &pw->pw_gid) || 152 setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) || 153 setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid)) 154 fatal("control: cannot drop privileges"); 155 #endif 156 157 event_init(); 158 159 signal_set(&ev_sigint, SIGINT, control_sig_handler, env); 160 signal_set(&ev_sigterm, SIGTERM, control_sig_handler, env); 161 signal_add(&ev_sigint, NULL); 162 signal_add(&ev_sigterm, NULL); 163 signal(SIGPIPE, SIG_IGN); 164 signal(SIGHUP, SIG_IGN); 165 166 TAILQ_INIT(&ctl_conns); 167 168 config_pipes(env, peers, nitems(peers)); 169 config_peers(env, peers, nitems(peers)); 170 control_listen(env); 171 event_dispatch(); 172 control_shutdown(); 173 174 return (0); 175 } 176 177 void 178 control_shutdown(void) 179 { 180 log_info("control process exiting"); 181 _exit(0); 182 } 183 184 int 185 control_listen(struct smtpd *env) 186 { 187 if (listen(control_state.fd, CONTROL_BACKLOG) == -1) { 188 log_warn("control_listen: listen"); 189 return (-1); 190 } 191 192 event_set(&control_state.ev, control_state.fd, EV_READ | EV_PERSIST, 193 control_accept, env); 194 event_add(&control_state.ev, NULL); 195 196 return (0); 197 } 198 199 void 200 control_cleanup(void) 201 { 202 (void)unlink(SMTPD_SOCKET); 203 } 204 205 /* ARGSUSED */ 206 void 207 control_accept(int listenfd, short event, void *arg) 208 { 209 int connfd; 210 socklen_t len; 211 struct sockaddr_un sun; 212 struct ctl_conn *c; 213 struct smtpd *env = arg; 214 215 len = sizeof(sun); 216 if ((connfd = accept(listenfd, 217 (struct sockaddr *)&sun, &len)) == -1) { 218 if (errno != EWOULDBLOCK && errno != EINTR) 219 log_warn("control_accept"); 220 return; 221 } 222 223 session_socket_blockmode(connfd, BM_NONBLOCK); 224 225 if ((c = calloc(1, sizeof(struct ctl_conn))) == NULL) { 226 close(connfd); 227 log_warn("control_accept"); 228 return; 229 } 230 231 imsg_init(&c->iev.ibuf, connfd); 232 c->iev.handler = control_dispatch_ext; 233 c->iev.events = EV_READ; 234 c->iev.data = env; 235 event_set(&c->iev.ev, c->iev.ibuf.fd, c->iev.events, 236 c->iev.handler, env); 237 event_add(&c->iev.ev, NULL); 238 239 TAILQ_INSERT_TAIL(&ctl_conns, c, entry); 240 } 241 242 struct ctl_conn * 243 control_connbyfd(int fd) 244 { 245 struct ctl_conn *c; 246 247 for (c = TAILQ_FIRST(&ctl_conns); c != NULL && c->iev.ibuf.fd != fd; 248 c = TAILQ_NEXT(c, entry)) 249 ; /* nothing */ 250 251 return (c); 252 } 253 254 void 255 control_close(int fd) 256 { 257 struct ctl_conn *c; 258 259 if ((c = control_connbyfd(fd)) == NULL) { 260 log_warn("control_close: fd %d: not found", fd); 261 return; 262 } 263 264 msgbuf_clear(&c->iev.ibuf.w); 265 TAILQ_REMOVE(&ctl_conns, c, entry); 266 267 event_del(&c->iev.ev); 268 close(c->iev.ibuf.fd); 269 free(c); 270 } 271 272 /* ARGSUSED */ 273 void 274 control_dispatch_ext(int fd, short event, void *arg) 275 { 276 struct ctl_conn *c; 277 struct smtpd *env = arg; 278 struct imsg imsg; 279 int n; 280 uid_t euid; 281 gid_t egid; 282 283 if (getpeereid(fd, &euid, &egid) == -1) 284 fatal("getpeereid"); 285 286 if ((c = control_connbyfd(fd)) == NULL) { 287 log_warn("control_dispatch_ext: fd %d: not found", fd); 288 return; 289 } 290 291 if (event & EV_READ) { 292 if ((n = imsg_read(&c->iev.ibuf)) == -1 || n == 0) { 293 control_close(fd); 294 return; 295 } 296 } 297 298 if (event & EV_WRITE) { 299 if (msgbuf_write(&c->iev.ibuf.w) < 0) { 300 control_close(fd); 301 return; 302 } 303 } 304 305 for (;;) { 306 if ((n = imsg_get(&c->iev.ibuf, &imsg)) == -1) { 307 control_close(fd); 308 return; 309 } 310 311 if (n == 0) 312 break; 313 314 switch (imsg.hdr.type) { 315 case IMSG_SMTP_ENQUEUE: 316 if (env->sc_flags & (SMTPD_SMTP_PAUSED | 317 SMTPD_CONFIGURING | SMTPD_EXITING)) { 318 imsg_compose_event(&c->iev, IMSG_CTL_FAIL, 0, 0, -1, 319 NULL, 0); 320 break; 321 } 322 imsg_compose_event(env->sc_ievs[PROC_SMTP], 323 IMSG_SMTP_ENQUEUE, fd, 0, -1, &euid, sizeof(euid)); 324 break; 325 case IMSG_STATS: 326 if (euid) 327 goto badcred; 328 imsg_compose_event(&c->iev, IMSG_STATS, 0, 0, -1, 329 env->stats, sizeof(struct stats)); 330 break; 331 case IMSG_RUNNER_SCHEDULE: { 332 struct sched *s = imsg.data; 333 334 if (euid) 335 goto badcred; 336 337 if (IMSG_DATA_SIZE(&imsg) != sizeof(*s)) 338 goto badcred; 339 340 s->fd = fd; 341 342 if (! valid_message_id(s->mid) && ! valid_message_uid(s->mid)) { 343 imsg_compose_event(&c->iev, IMSG_CTL_FAIL, 0, 0, -1, 344 NULL, 0); 345 break; 346 } 347 348 imsg_compose_event(env->sc_ievs[PROC_RUNNER], IMSG_RUNNER_SCHEDULE, 0, 0, -1, s, sizeof(*s)); 349 break; 350 } 351 /* 352 case IMSG_CONF_RELOAD: { 353 struct reload r; 354 355 log_debug("received reload request"); 356 357 if (euid) 358 goto badcred; 359 360 if (env->sc_flags & SMTPD_CONFIGURING) { 361 imsg_compose_event(&c->iev, IMSG_CTL_FAIL, 0, 0, -1, 362 NULL, 0); 363 break; 364 } 365 env->sc_flags |= SMTPD_CONFIGURING; 366 367 r.fd = fd; 368 imsg_compose_event(env->sc_ievs[PROC_PARENT], IMSG_CONF_RELOAD, 0, 0, -1, &r, sizeof(r)); 369 break; 370 } 371 */ 372 case IMSG_CTL_SHUTDOWN: 373 /* NEEDS_FIX */ 374 log_debug("received shutdown request"); 375 376 if (euid) 377 goto badcred; 378 379 if (env->sc_flags & SMTPD_EXITING) { 380 imsg_compose_event(&c->iev, IMSG_CTL_FAIL, 0, 0, -1, 381 NULL, 0); 382 break; 383 } 384 env->sc_flags |= SMTPD_EXITING; 385 imsg_compose_event(&c->iev, IMSG_CTL_OK, 0, 0, -1, NULL, 0); 386 break; 387 case IMSG_MDA_PAUSE: 388 if (euid) 389 goto badcred; 390 391 if (env->sc_flags & SMTPD_MDA_PAUSED) { 392 imsg_compose_event(&c->iev, IMSG_CTL_FAIL, 0, 0, -1, 393 NULL, 0); 394 break; 395 } 396 env->sc_flags |= SMTPD_MDA_PAUSED; 397 imsg_compose_event(env->sc_ievs[PROC_RUNNER], IMSG_MDA_PAUSE, 398 0, 0, -1, NULL, 0); 399 imsg_compose_event(&c->iev, IMSG_CTL_OK, 0, 0, -1, NULL, 0); 400 break; 401 case IMSG_MTA_PAUSE: 402 if (euid) 403 goto badcred; 404 405 if (env->sc_flags & SMTPD_MTA_PAUSED) { 406 imsg_compose_event(&c->iev, IMSG_CTL_FAIL, 0, 0, -1, 407 NULL, 0); 408 break; 409 } 410 env->sc_flags |= SMTPD_MTA_PAUSED; 411 imsg_compose_event(env->sc_ievs[PROC_RUNNER], IMSG_MTA_PAUSE, 412 0, 0, -1, NULL, 0); 413 imsg_compose_event(&c->iev, IMSG_CTL_OK, 0, 0, -1, NULL, 0); 414 break; 415 case IMSG_SMTP_PAUSE: 416 if (euid) 417 goto badcred; 418 419 if (env->sc_flags & SMTPD_SMTP_PAUSED) { 420 imsg_compose_event(&c->iev, IMSG_CTL_FAIL, 0, 0, -1, 421 NULL, 0); 422 break; 423 } 424 env->sc_flags |= SMTPD_SMTP_PAUSED; 425 imsg_compose_event(env->sc_ievs[PROC_SMTP], IMSG_SMTP_PAUSE, 426 0, 0, -1, NULL, 0); 427 imsg_compose_event(&c->iev, IMSG_CTL_OK, 0, 0, -1, NULL, 0); 428 break; 429 case IMSG_MDA_RESUME: 430 if (euid) 431 goto badcred; 432 433 if (! (env->sc_flags & SMTPD_MDA_PAUSED)) { 434 imsg_compose_event(&c->iev, IMSG_CTL_FAIL, 0, 0, -1, 435 NULL, 0); 436 break; 437 } 438 env->sc_flags &= ~SMTPD_MDA_PAUSED; 439 imsg_compose_event(env->sc_ievs[PROC_RUNNER], IMSG_MTA_RESUME, 440 0, 0, -1, NULL, 0); 441 imsg_compose_event(&c->iev, IMSG_CTL_OK, 0, 0, -1, NULL, 0); 442 break; 443 case IMSG_MTA_RESUME: 444 if (euid) 445 goto badcred; 446 447 if (!(env->sc_flags & SMTPD_MTA_PAUSED)) { 448 imsg_compose_event(&c->iev, IMSG_CTL_FAIL, 0, 0, -1, 449 NULL, 0); 450 break; 451 } 452 env->sc_flags &= ~SMTPD_MTA_PAUSED; 453 imsg_compose_event(env->sc_ievs[PROC_RUNNER], IMSG_MTA_RESUME, 454 0, 0, -1, NULL, 0); 455 imsg_compose_event(&c->iev, IMSG_CTL_OK, 0, 0, -1, NULL, 0); 456 break; 457 case IMSG_SMTP_RESUME: 458 if (euid) 459 goto badcred; 460 461 if (!(env->sc_flags & SMTPD_SMTP_PAUSED)) { 462 imsg_compose_event(&c->iev, IMSG_CTL_FAIL, 0, 0, -1, 463 NULL, 0); 464 break; 465 } 466 env->sc_flags &= ~SMTPD_SMTP_PAUSED; 467 imsg_compose_event(env->sc_ievs[PROC_SMTP], IMSG_SMTP_RESUME, 468 0, 0, -1, NULL, 0); 469 imsg_compose_event(&c->iev, IMSG_CTL_OK, 0, 0, -1, NULL, 0); 470 break; 471 default: 472 log_debug("control_dispatch_ext: " 473 "error handling imsg %d", imsg.hdr.type); 474 break; 475 } 476 imsg_free(&imsg); 477 continue; 478 479 badcred: 480 imsg_compose_event(&c->iev, IMSG_CTL_FAIL, 0, 0, -1, 481 NULL, 0); 482 } 483 484 imsg_event_add(&c->iev); 485 } 486 487 void 488 control_dispatch_parent(int sig, short event, void *p) 489 { 490 struct smtpd *env = p; 491 struct imsgev *iev; 492 struct imsgbuf *ibuf; 493 struct imsg imsg; 494 ssize_t n; 495 496 iev = env->sc_ievs[PROC_PARENT]; 497 ibuf = &iev->ibuf; 498 499 if (event & EV_READ) { 500 if ((n = imsg_read(ibuf)) == -1) 501 fatal("imsg_read_error"); 502 if (n == 0) { 503 /* this pipe is dead, so remove the event handler */ 504 event_del(&iev->ev); 505 event_loopexit(NULL); 506 return; 507 } 508 } 509 510 if (event & EV_WRITE) { 511 if (msgbuf_write(&ibuf->w) == -1) 512 fatal("msgbuf_write"); 513 } 514 515 for (;;) { 516 if ((n = imsg_get(ibuf, &imsg)) == -1) 517 fatal("control_dispatch_parent: imsg_get error"); 518 if (n == 0) 519 break; 520 521 switch (imsg.hdr.type) { 522 case IMSG_CONF_RELOAD: { 523 struct reload *r = imsg.data; 524 struct ctl_conn *c; 525 526 IMSG_SIZE_CHECK(r); 527 528 env->sc_flags &= ~SMTPD_CONFIGURING; 529 if ((c = control_connbyfd(r->fd)) == NULL) { 530 log_warn("control_dispatch_parent: fd %d not found", r->fd); 531 return; 532 } 533 534 if (r->ret) 535 imsg_compose_event(&c->iev, IMSG_CTL_OK, 0, 0, -1, NULL, 0); 536 else 537 imsg_compose_event(&c->iev, IMSG_CTL_FAIL, 0, 0, -1, NULL, 0); 538 break; 539 } 540 default: 541 log_warnx("control_dispatch_parent: got imsg %d", 542 imsg.hdr.type); 543 fatalx("control_dispatch_parent: unexpected imsg"); 544 } 545 imsg_free(&imsg); 546 } 547 imsg_event_add(iev); 548 } 549 550 void 551 control_dispatch_lka(int sig, short event, void *p) 552 { 553 struct smtpd *env = p; 554 struct imsgev *iev; 555 struct imsgbuf *ibuf; 556 struct imsg imsg; 557 ssize_t n; 558 559 iev = env->sc_ievs[PROC_LKA]; 560 ibuf = &iev->ibuf; 561 562 if (event & EV_READ) { 563 if ((n = imsg_read(ibuf)) == -1) 564 fatal("imsg_read_error"); 565 if (n == 0) { 566 /* this pipe is dead, so remove the event handler */ 567 event_del(&iev->ev); 568 event_loopexit(NULL); 569 return; 570 } 571 } 572 573 if (event & EV_WRITE) { 574 if (msgbuf_write(&ibuf->w) == -1) 575 fatal("msgbuf_write"); 576 } 577 578 for (;;) { 579 if ((n = imsg_get(ibuf, &imsg)) == -1) 580 fatal("control_dispatch_lka: imsg_get error"); 581 if (n == 0) 582 break; 583 584 switch (imsg.hdr.type) { 585 default: 586 log_warnx("control_dispatch_lka: got imsg %d", 587 imsg.hdr.type); 588 fatalx("control_dispatch_lka: unexpected imsg"); 589 } 590 imsg_free(&imsg); 591 } 592 imsg_event_add(iev); 593 } 594 595 void 596 control_dispatch_mfa(int sig, short event, void *p) 597 { 598 struct smtpd *env = p; 599 struct imsgev *iev; 600 struct imsgbuf *ibuf; 601 struct imsg imsg; 602 ssize_t n; 603 604 iev = env->sc_ievs[PROC_MFA]; 605 ibuf = &iev->ibuf; 606 607 if (event & EV_READ) { 608 if ((n = imsg_read(ibuf)) == -1) 609 fatal("imsg_read_error"); 610 if (n == 0) { 611 /* this pipe is dead, so remove the event handler */ 612 event_del(&iev->ev); 613 event_loopexit(NULL); 614 return; 615 } 616 } 617 618 if (event & EV_WRITE) { 619 if (msgbuf_write(&ibuf->w) == -1) 620 fatal("msgbuf_write"); 621 } 622 623 for (;;) { 624 if ((n = imsg_get(ibuf, &imsg)) == -1) 625 fatal("control_dispatch_mfa: imsg_get error"); 626 if (n == 0) 627 break; 628 629 switch (imsg.hdr.type) { 630 default: 631 log_warnx("control_dispatch_mfa: got imsg %d", 632 imsg.hdr.type); 633 fatalx("control_dispatch_mfa: unexpected imsg"); 634 } 635 imsg_free(&imsg); 636 } 637 imsg_event_add(iev); 638 } 639 640 void 641 control_dispatch_queue(int sig, short event, void *p) 642 { 643 struct smtpd *env = p; 644 struct imsgev *iev; 645 struct imsgbuf *ibuf; 646 struct imsg imsg; 647 ssize_t n; 648 649 iev = env->sc_ievs[PROC_QUEUE]; 650 ibuf = &iev->ibuf; 651 652 if (event & EV_READ) { 653 if ((n = imsg_read(ibuf)) == -1) 654 fatal("imsg_read_error"); 655 if (n == 0) { 656 /* this pipe is dead, so remove the event handler */ 657 event_del(&iev->ev); 658 event_loopexit(NULL); 659 return; 660 } 661 } 662 663 if (event & EV_WRITE) { 664 if (msgbuf_write(&ibuf->w) == -1) 665 fatal("msgbuf_write"); 666 } 667 668 for (;;) { 669 if ((n = imsg_get(ibuf, &imsg)) == -1) 670 fatal("control_dispatch_queue: imsg_get error"); 671 if (n == 0) 672 break; 673 674 switch (imsg.hdr.type) { 675 default: 676 log_warnx("control_dispatch_queue: got imsg %d", 677 imsg.hdr.type); 678 fatalx("control_dispatch_queue: unexpected imsg"); 679 } 680 imsg_free(&imsg); 681 } 682 imsg_event_add(iev); 683 } 684 685 void 686 control_dispatch_runner(int sig, short event, void *p) 687 { 688 struct smtpd *env = p; 689 struct imsgev *iev; 690 struct imsgbuf *ibuf; 691 struct imsg imsg; 692 ssize_t n; 693 694 iev = env->sc_ievs[PROC_RUNNER]; 695 ibuf = &iev->ibuf; 696 697 if (event & EV_READ) { 698 if ((n = imsg_read(ibuf)) == -1) 699 fatal("imsg_read_error"); 700 if (n == 0) { 701 /* this pipe is dead, so remove the event handler */ 702 event_del(&iev->ev); 703 event_loopexit(NULL); 704 return; 705 } 706 } 707 708 if (event & EV_WRITE) { 709 if (msgbuf_write(&ibuf->w) == -1) 710 fatal("msgbuf_write"); 711 } 712 713 for (;;) { 714 if ((n = imsg_get(ibuf, &imsg)) == -1) 715 fatal("control_dispatch_runner: imsg_get error"); 716 if (n == 0) 717 break; 718 719 switch (imsg.hdr.type) { 720 case IMSG_RUNNER_SCHEDULE: { 721 struct sched *s = imsg.data; 722 struct ctl_conn *c; 723 724 IMSG_SIZE_CHECK(s); 725 726 if ((c = control_connbyfd(s->fd)) == NULL) { 727 log_warn("control_dispatch_runner: fd %d not found", s->fd); 728 imsg_free(&imsg); 729 return; 730 } 731 732 if (s->ret) 733 imsg_compose_event(&c->iev, IMSG_CTL_OK, 0, 0, -1, NULL, 0); 734 else 735 imsg_compose_event(&c->iev, IMSG_CTL_FAIL, 0, 0, -1, NULL, 0); 736 break; 737 } 738 default: 739 log_warnx("control_dispatch_runner: got imsg %d", 740 imsg.hdr.type); 741 fatalx("control_dispatch_runner: unexpected imsg"); 742 } 743 imsg_free(&imsg); 744 } 745 imsg_event_add(iev); 746 } 747 748 void 749 control_dispatch_smtp(int sig, short event, void *p) 750 { 751 struct smtpd *env = p; 752 struct imsgev *iev; 753 struct imsgbuf *ibuf; 754 struct imsg imsg; 755 ssize_t n; 756 757 iev = env->sc_ievs[PROC_SMTP]; 758 ibuf = &iev->ibuf; 759 760 if (event & EV_READ) { 761 if ((n = imsg_read(ibuf)) == -1) 762 fatal("imsg_read_error"); 763 if (n == 0) { 764 /* this pipe is dead, so remove the event handler */ 765 event_del(&iev->ev); 766 event_loopexit(NULL); 767 return; 768 } 769 } 770 771 if (event & EV_WRITE) { 772 if (msgbuf_write(&ibuf->w) == -1) 773 fatal("msgbuf_write"); 774 } 775 776 for (;;) { 777 if ((n = imsg_get(ibuf, &imsg)) == -1) 778 fatal("control_dispatch_smtp: imsg_get error"); 779 if (n == 0) 780 break; 781 782 switch (imsg.hdr.type) { 783 case IMSG_SMTP_ENQUEUE: { 784 struct ctl_conn *c; 785 int client_fd; 786 787 client_fd = imsg.hdr.peerid; 788 789 if ((c = control_connbyfd(client_fd)) == NULL) { 790 log_warn("control_dispatch_smtp: fd %d not found", client_fd); 791 imsg_free(&imsg); 792 return; 793 } 794 795 imsg_compose_event(&c->iev, IMSG_CTL_OK, 0, 0, 796 imsg.fd, NULL, 0); 797 break; 798 } 799 default: 800 log_warnx("control_dispatch_smtp: got imsg %d", 801 imsg.hdr.type); 802 fatalx("control_dispatch_smtp: unexpected imsg"); 803 } 804 imsg_free(&imsg); 805 } 806 imsg_event_add(iev); 807 } 808 809 void 810 session_socket_blockmode(int fd, enum blockmodes bm) 811 { 812 int flags; 813 814 if ((flags = fcntl(fd, F_GETFL, 0)) == -1) 815 fatal("fcntl F_GETFL"); 816 817 if (bm == BM_NONBLOCK) 818 flags |= O_NONBLOCK; 819 else 820 flags &= ~O_NONBLOCK; 821 822 if ((flags = fcntl(fd, F_SETFL, flags)) == -1) 823 fatal("fcntl F_SETFL"); 824 } 825 826 void 827 session_socket_no_linger(int fd) 828 { 829 struct linger lng; 830 831 bzero(&lng, sizeof(lng)); 832 if (setsockopt(fd, SOL_SOCKET, SO_LINGER, &lng, sizeof(lng)) == -1) 833 fatal("session_socket_no_linger"); 834 } 835 836 int 837 session_socket_error(int fd) 838 { 839 int err, len; 840 841 len = sizeof(err); 842 if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &err, &len) == -1) 843 fatal("session_socket_error: getsockopt"); 844 845 return (err); 846 } 847