diff options
author | Jacek Masiulaniec <jacekm@cvs.openbsd.org> | 2010-04-20 15:34:57 +0000 |
---|---|---|
committer | Jacek Masiulaniec <jacekm@cvs.openbsd.org> | 2010-04-20 15:34:57 +0000 |
commit | 318ca7cef0691f6d5daeca58557bfd79b3220e12 (patch) | |
tree | f6eae7893a3065a5685c10c071f6b64305ed5286 /usr.sbin | |
parent | 001b3d12570bfa08c409e5bc9e1a8a299473cb9e (diff) |
Kill *2400* lines of code by abstracting common bits of the imsg handlers.
Diffstat (limited to 'usr.sbin')
-rw-r--r-- | usr.sbin/smtpd/config.c | 6 | ||||
-rw-r--r-- | usr.sbin/smtpd/control.c | 422 | ||||
-rw-r--r-- | usr.sbin/smtpd/lka.c | 686 | ||||
-rw-r--r-- | usr.sbin/smtpd/mda.c | 332 | ||||
-rw-r--r-- | usr.sbin/smtpd/mfa.c | 270 | ||||
-rw-r--r-- | usr.sbin/smtpd/mta.c | 421 | ||||
-rw-r--r-- | usr.sbin/smtpd/queue.c | 576 | ||||
-rw-r--r-- | usr.sbin/smtpd/runner.c | 461 | ||||
-rw-r--r-- | usr.sbin/smtpd/smtp.c | 660 | ||||
-rw-r--r-- | usr.sbin/smtpd/smtpd.c | 626 | ||||
-rw-r--r-- | usr.sbin/smtpd/smtpd.h | 7 |
11 files changed, 1044 insertions, 3423 deletions
diff --git a/usr.sbin/smtpd/config.c b/usr.sbin/smtpd/config.c index 2f2142d6119..577b09c992e 100644 --- a/usr.sbin/smtpd/config.c +++ b/usr.sbin/smtpd/config.c @@ -1,4 +1,4 @@ -/* $OpenBSD: config.c,v 1.9 2009/11/12 12:35:03 jacekm Exp $ */ +/* $OpenBSD: config.c,v 1.10 2010/04/20 15:34:56 jacekm Exp $ */ /* * Copyright (c) 2008 Pierre-Yves Ritschard <pyr@openbsd.org> @@ -218,7 +218,9 @@ config_peers(struct smtpd *env, struct peer *p, u_int peercount) env->sc_pipes[src][dst][count]); env->sc_ievs[dst][count].handler = p[i].cb; env->sc_ievs[dst][count].events = EV_READ; - env->sc_ievs[dst][count].data = env; + env->sc_ievs[dst][count].proc = dst; + env->sc_ievs[dst][count].data = &env->sc_ievs[dst][count]; + env->sc_ievs[dst][count].env = env; event_set(&(env->sc_ievs[dst][count].ev), env->sc_ievs[dst][count].ibuf.fd, diff --git a/usr.sbin/smtpd/control.c b/usr.sbin/smtpd/control.c index 53d94339755..26c1b3897c3 100644 --- a/usr.sbin/smtpd/control.c +++ b/usr.sbin/smtpd/control.c @@ -1,4 +1,4 @@ -/* $OpenBSD: control.c,v 1.46 2010/01/10 16:42:35 gilles Exp $ */ +/* $OpenBSD: control.c,v 1.47 2010/04/20 15:34:56 jacekm Exp $ */ /* * Copyright (c) 2008 Pierre-Yves Ritschard <pyr@openbsd.org> @@ -45,6 +45,7 @@ struct { int fd; } control_state; +void control_imsg(struct smtpd *, struct imsgev *, struct imsg *); __dead void control_shutdown(void); int control_init(void); void control_listen(struct smtpd *); @@ -54,16 +55,72 @@ struct ctl_conn *control_connbyfd(int); void control_close(struct smtpd *, int); void control_sig_handler(int, short, void *); void control_dispatch_ext(int, short, void *); -void control_dispatch_lka(int, short, void *); -void control_dispatch_mfa(int, short, void *); -void control_dispatch_queue(int, short, void *); -void control_dispatch_runner(int, short, void *); -void control_dispatch_smtp(int, short, void *); -void control_dispatch_parent(int, short, void *); struct ctl_connlist ctl_conns; void +control_imsg(struct smtpd *env, struct imsgev *iev, struct imsg *imsg) +{ + struct ctl_conn *c; + struct reload *reload; + struct remove *rem; + struct sched *sched; + + if (iev->proc == PROC_SMTP) { + switch (imsg->hdr.type) { + case IMSG_SMTP_ENQUEUE: + c = control_connbyfd(imsg->hdr.peerid); + if (c == NULL) + return; + imsg_compose_event(&c->iev, IMSG_CTL_OK, 0, 0, + imsg->fd, NULL, 0); + return; + } + } + + if (iev->proc == PROC_RUNNER) { + switch (imsg->hdr.type) { + case IMSG_RUNNER_SCHEDULE: + sched = imsg->data; + c = control_connbyfd(sched->fd); + if (c == NULL) + return; + imsg_compose_event(&c->iev, + sched->ret ? IMSG_CTL_OK : IMSG_CTL_FAIL, 0, 0, -1, + NULL, 0); + return; + + case IMSG_RUNNER_REMOVE: + rem = imsg->data; + c = control_connbyfd(rem->fd); + if (c == NULL) + return; + imsg_compose_event(&c->iev, + rem->ret ? IMSG_CTL_OK : IMSG_CTL_FAIL, 0, 0, + -1, NULL, 0); + return; + } + } + + if (iev->proc == PROC_PARENT) { + switch (imsg->hdr.type) { + case IMSG_CONF_RELOAD: + env->sc_flags &= ~SMTPD_CONFIGURING; + reload = imsg->data; + c = control_connbyfd(reload->fd); + if (c == NULL) + return; + imsg_compose_event(&c->iev, + reload->ret ? IMSG_CTL_OK : IMSG_CTL_FAIL, 0, 0, + -1, NULL, 0); + return; + } + } + + fatalx("control_imsg: unexpected imsg"); +} + +void control_sig_handler(int sig, short event, void *p) { switch (sig) { @@ -88,11 +145,11 @@ control(struct smtpd *env) struct event ev_sigint; struct event ev_sigterm; struct peer peers [] = { - { PROC_QUEUE, control_dispatch_queue }, - { PROC_RUNNER, control_dispatch_runner }, - { PROC_SMTP, control_dispatch_smtp }, - { PROC_MFA, control_dispatch_mfa }, - { PROC_PARENT, control_dispatch_parent }, + { PROC_QUEUE, imsg_dispatch }, + { PROC_RUNNER, imsg_dispatch }, + { PROC_SMTP, imsg_dispatch }, + { PROC_MFA, imsg_dispatch }, + { PROC_PARENT, imsg_dispatch }, }; switch (pid = fork()) { @@ -158,6 +215,7 @@ control(struct smtpd *env) fatal("control: cannot drop privileges"); #endif + imsg_callback = control_imsg; event_init(); signal_set(&ev_sigint, SIGINT, control_sig_handler, env); @@ -535,343 +593,3 @@ badcred: imsg_event_add(&c->iev); } - -void -control_dispatch_parent(int sig, short event, void *p) -{ - struct smtpd *env = p; - struct imsgev *iev; - struct imsgbuf *ibuf; - struct imsg imsg; - ssize_t n; - - iev = env->sc_ievs[PROC_PARENT]; - ibuf = &iev->ibuf; - - if (event & EV_READ) { - if ((n = imsg_read(ibuf)) == -1) - fatal("imsg_read_error"); - if (n == 0) { - /* this pipe is dead, so remove the event handler */ - event_del(&iev->ev); - event_loopexit(NULL); - return; - } - } - - if (event & EV_WRITE) { - if (msgbuf_write(&ibuf->w) == -1) - fatal("msgbuf_write"); - } - - for (;;) { - if ((n = imsg_get(ibuf, &imsg)) == -1) - fatal("control_dispatch_parent: imsg_get error"); - if (n == 0) - break; - - switch (imsg.hdr.type) { - case IMSG_CONF_RELOAD: { - struct reload *r = imsg.data; - struct ctl_conn *c; - - IMSG_SIZE_CHECK(r); - - env->sc_flags &= ~SMTPD_CONFIGURING; - if ((c = control_connbyfd(r->fd)) == NULL) { - log_warn("control_dispatch_parent: fd %d not found", r->fd); - return; - } - - if (r->ret) - imsg_compose_event(&c->iev, IMSG_CTL_OK, 0, 0, -1, NULL, 0); - else - imsg_compose_event(&c->iev, IMSG_CTL_FAIL, 0, 0, -1, NULL, 0); - break; - } - default: - log_warnx("control_dispatch_parent: got imsg %d", - imsg.hdr.type); - fatalx("control_dispatch_parent: unexpected imsg"); - } - imsg_free(&imsg); - } - imsg_event_add(iev); -} - -void -control_dispatch_lka(int sig, short event, void *p) -{ - struct smtpd *env = p; - struct imsgev *iev; - struct imsgbuf *ibuf; - struct imsg imsg; - ssize_t n; - - iev = env->sc_ievs[PROC_LKA]; - ibuf = &iev->ibuf; - - if (event & EV_READ) { - if ((n = imsg_read(ibuf)) == -1) - fatal("imsg_read_error"); - if (n == 0) { - /* this pipe is dead, so remove the event handler */ - event_del(&iev->ev); - event_loopexit(NULL); - return; - } - } - - if (event & EV_WRITE) { - if (msgbuf_write(&ibuf->w) == -1) - fatal("msgbuf_write"); - } - - for (;;) { - if ((n = imsg_get(ibuf, &imsg)) == -1) - fatal("control_dispatch_lka: imsg_get error"); - if (n == 0) - break; - - switch (imsg.hdr.type) { - default: - log_warnx("control_dispatch_lka: got imsg %d", - imsg.hdr.type); - fatalx("control_dispatch_lka: unexpected imsg"); - } - imsg_free(&imsg); - } - imsg_event_add(iev); -} - -void -control_dispatch_mfa(int sig, short event, void *p) -{ - struct smtpd *env = p; - struct imsgev *iev; - struct imsgbuf *ibuf; - struct imsg imsg; - ssize_t n; - - iev = env->sc_ievs[PROC_MFA]; - ibuf = &iev->ibuf; - - if (event & EV_READ) { - if ((n = imsg_read(ibuf)) == -1) - fatal("imsg_read_error"); - if (n == 0) { - /* this pipe is dead, so remove the event handler */ - event_del(&iev->ev); - event_loopexit(NULL); - return; - } - } - - if (event & EV_WRITE) { - if (msgbuf_write(&ibuf->w) == -1) - fatal("msgbuf_write"); - } - - for (;;) { - if ((n = imsg_get(ibuf, &imsg)) == -1) - fatal("control_dispatch_mfa: imsg_get error"); - if (n == 0) - break; - - switch (imsg.hdr.type) { - default: - log_warnx("control_dispatch_mfa: got imsg %d", - imsg.hdr.type); - fatalx("control_dispatch_mfa: unexpected imsg"); - } - imsg_free(&imsg); - } - imsg_event_add(iev); -} - -void -control_dispatch_queue(int sig, short event, void *p) -{ - struct smtpd *env = p; - struct imsgev *iev; - struct imsgbuf *ibuf; - struct imsg imsg; - ssize_t n; - - iev = env->sc_ievs[PROC_QUEUE]; - ibuf = &iev->ibuf; - - if (event & EV_READ) { - if ((n = imsg_read(ibuf)) == -1) - fatal("imsg_read_error"); - if (n == 0) { - /* this pipe is dead, so remove the event handler */ - event_del(&iev->ev); - event_loopexit(NULL); - return; - } - } - - if (event & EV_WRITE) { - if (msgbuf_write(&ibuf->w) == -1) - fatal("msgbuf_write"); - } - - for (;;) { - if ((n = imsg_get(ibuf, &imsg)) == -1) - fatal("control_dispatch_queue: imsg_get error"); - if (n == 0) - break; - - switch (imsg.hdr.type) { - default: - log_warnx("control_dispatch_queue: got imsg %d", - imsg.hdr.type); - fatalx("control_dispatch_queue: unexpected imsg"); - } - imsg_free(&imsg); - } - imsg_event_add(iev); -} - -void -control_dispatch_runner(int sig, short event, void *p) -{ - struct smtpd *env = p; - struct imsgev *iev; - struct imsgbuf *ibuf; - struct imsg imsg; - ssize_t n; - - iev = env->sc_ievs[PROC_RUNNER]; - ibuf = &iev->ibuf; - - if (event & EV_READ) { - if ((n = imsg_read(ibuf)) == -1) - fatal("imsg_read_error"); - if (n == 0) { - /* this pipe is dead, so remove the event handler */ - event_del(&iev->ev); - event_loopexit(NULL); - return; - } - } - - if (event & EV_WRITE) { - if (msgbuf_write(&ibuf->w) == -1) - fatal("msgbuf_write"); - } - - for (;;) { - if ((n = imsg_get(ibuf, &imsg)) == -1) - fatal("control_dispatch_runner: imsg_get error"); - if (n == 0) - break; - - switch (imsg.hdr.type) { - case IMSG_RUNNER_SCHEDULE: { - struct sched *s = imsg.data; - struct ctl_conn *c; - - IMSG_SIZE_CHECK(s); - - if ((c = control_connbyfd(s->fd)) == NULL) { - log_warn("control_dispatch_runner: fd %d not found", s->fd); - imsg_free(&imsg); - return; - } - - if (s->ret) - imsg_compose_event(&c->iev, IMSG_CTL_OK, 0, 0, -1, NULL, 0); - else - imsg_compose_event(&c->iev, IMSG_CTL_FAIL, 0, 0, -1, NULL, 0); - break; - } - case IMSG_RUNNER_REMOVE: { - struct remove *s = imsg.data; - struct ctl_conn *c; - - IMSG_SIZE_CHECK(s); - - if ((c = control_connbyfd(s->fd)) == NULL) { - log_warn("control_dispatch_runner: fd %d not found", s->fd); - imsg_free(&imsg); - return; - } - - if (s->ret) - imsg_compose_event(&c->iev, IMSG_CTL_OK, 0, 0, -1, NULL, 0); - else - imsg_compose_event(&c->iev, IMSG_CTL_FAIL, 0, 0, -1, NULL, 0); - break; - } - default: - log_warnx("control_dispatch_runner: got imsg %d", - imsg.hdr.type); - fatalx("control_dispatch_runner: unexpected imsg"); - } - imsg_free(&imsg); - } - imsg_event_add(iev); -} - -void -control_dispatch_smtp(int sig, short event, void *p) -{ - struct smtpd *env = p; - struct imsgev *iev; - struct imsgbuf *ibuf; - struct imsg imsg; - ssize_t n; - - iev = env->sc_ievs[PROC_SMTP]; - ibuf = &iev->ibuf; - - if (event & EV_READ) { - if ((n = imsg_read(ibuf)) == -1) - fatal("imsg_read_error"); - if (n == 0) { - /* this pipe is dead, so remove the event handler */ - event_del(&iev->ev); - event_loopexit(NULL); - return; - } - } - - if (event & EV_WRITE) { - if (msgbuf_write(&ibuf->w) == -1) - fatal("msgbuf_write"); - } - - for (;;) { - if ((n = imsg_get(ibuf, &imsg)) == -1) - fatal("control_dispatch_smtp: imsg_get error"); - if (n == 0) - break; - - switch (imsg.hdr.type) { - case IMSG_SMTP_ENQUEUE: { - struct ctl_conn *c; - int client_fd; - - client_fd = imsg.hdr.peerid; - - if ((c = control_connbyfd(client_fd)) == NULL) { - log_warn("control_dispatch_smtp: fd %d not found", client_fd); - imsg_free(&imsg); - return; - } - - imsg_compose_event(&c->iev, IMSG_CTL_OK, 0, 0, - imsg.fd, NULL, 0); - break; - } - default: - log_warnx("control_dispatch_smtp: got imsg %d", - imsg.hdr.type); - fatalx("control_dispatch_smtp: unexpected imsg"); - } - imsg_free(&imsg); - } - imsg_event_add(iev); -} diff --git a/usr.sbin/smtpd/lka.c b/usr.sbin/smtpd/lka.c index 192f83cf333..dc4bc499238 100644 --- a/usr.sbin/smtpd/lka.c +++ b/usr.sbin/smtpd/lka.c @@ -1,4 +1,4 @@ -/* $OpenBSD: lka.c,v 1.101 2010/02/17 17:27:47 gilles Exp $ */ +/* $OpenBSD: lka.c,v 1.102 2010/04/20 15:34:56 jacekm Exp $ */ /* * Copyright (c) 2008 Pierre-Yves Ritschard <pyr@openbsd.org> @@ -41,14 +41,9 @@ #include "smtpd.h" +void lka_imsg(struct smtpd *, struct imsgev *, struct imsg *); __dead void lka_shutdown(void); void lka_sig_handler(int, short, void *); -void lka_dispatch_parent(int, short, void *); -void lka_dispatch_mfa(int, short, void *); -void lka_dispatch_smtp(int, short, void *); -void lka_dispatch_queue(int, short, void *); -void lka_dispatch_runner(int, short, void *); -void lka_dispatch_mta(int, short, void *); void lka_setup_events(struct smtpd *); void lka_disable_events(struct smtpd *); void lka_expand_pickup(struct smtpd *, struct lkasession *); @@ -69,543 +64,223 @@ void lka_expansion_done(struct smtpd *, struct lkasession *); void lka_session_fail(struct smtpd *, struct lkasession *, struct submit_status *); void -lka_sig_handler(int sig, short event, void *p) +lka_imsg(struct smtpd *env, struct imsgev *iev, struct imsg *imsg) { - int status; - pid_t pid; - - switch (sig) { - case SIGINT: - case SIGTERM: - lka_shutdown(); - break; - case SIGCHLD: - do { - pid = waitpid(-1, &status, WNOHANG); - } while (pid > 0 || (pid == -1 && errno == EINTR)); - break; - default: - fatalx("lka_sig_handler: unexpected signal"); + struct lkasession skey; + struct submit_status *ss; + struct forward_req *fwreq; + struct lkasession *s; + struct secret *secret; + struct mapel *mapel; + struct cond *cond; + struct rule *rule; + struct path *path; + struct map *map; + void *tmp; + + if (imsg->hdr.type == IMSG_DNS_A || imsg->hdr.type == IMSG_DNS_MX || + imsg->hdr.type == IMSG_DNS_PTR) { + dns_async(env, iev, imsg->hdr.type, imsg->data); + return; } -} -void -lka_dispatch_parent(int sig, short event, void *p) -{ - struct smtpd *env = p; - struct imsgev *iev; - struct imsgbuf *ibuf; - struct imsg imsg; - ssize_t n; - - iev = env->sc_ievs[PROC_PARENT]; - ibuf = &iev->ibuf; - - if (event & EV_READ) { - if ((n = imsg_read(ibuf)) == -1) - fatal("imsg_read_error"); - if (n == 0) { - /* this pipe is dead, so remove the event handler */ - event_del(&iev->ev); - event_loopexit(NULL); + if (iev->proc == PROC_MFA) { + switch (imsg->hdr.type) { + case IMSG_LKA_MAIL: + ss = imsg->data; + ss->code = 530; + if (ss->u.path.user[0] == '\0' && + ss->u.path.domain[0] == '\0') + ss->code = 250; + else + if (lka_verify_mail(env, &ss->u.path)) + ss->code = 250; + imsg_compose_event(iev, IMSG_LKA_MAIL, 0, 0, -1, ss, + sizeof *ss); + return; + + case IMSG_LKA_RULEMATCH: + ss = imsg->data; + ss->code = 530; + rule = ruleset_match(env, ss->msg.tag, &ss->u.path, + &ss->ss); + if (rule) { + ss->code = 250; + ss->u.path.rule = *rule; + } + imsg_compose_event(iev, IMSG_LKA_RULEMATCH, 0, 0, -1, + ss, sizeof *ss); + return; + + case IMSG_LKA_RCPT: + ss = imsg->data; + ss->code = 250; + path = &ss->u.path; + s = lka_session_init(env, ss); + if (! lka_resolve_path(env, s, path)) + lka_session_fail(env, s, ss); + else + lka_expand_pickup(env, s); return; } } - if (event & EV_WRITE) { - if (msgbuf_write(&ibuf->w) == -1) - fatal("msgbuf_write"); + if (iev->proc == PROC_MTA) { + switch (imsg->hdr.type) { + case IMSG_LKA_SECRET: + secret = imsg->data; + map = map_findbyname(env, "secrets"); + if (map == NULL) + fatalx("lka: secrets map not found"); + tmp = map_lookup(env, map->m_id, secret->host); + log_debug("lka: %s secret lookup (%d)", secret->host, + tmp != NULL); + secret->secret[0] = '\0'; + if (tmp == NULL) + log_warnx("%s secret not found", secret->host); + else if (lka_encode_credentials(secret->secret, + sizeof secret->secret, tmp) == 0) + log_warnx("%s secret parse fail", secret->host); + imsg_compose_event(iev, IMSG_LKA_SECRET, 0, 0, -1, secret, + sizeof *secret); + free(tmp); + return; + } } - for (;;) { - if ((n = imsg_get(ibuf, &imsg)) == -1) - fatal("lka_dispatch_parent: imsg_get error"); - if (n == 0) - break; - - switch (imsg.hdr.type) { + if (iev->proc == PROC_PARENT) { + switch (imsg->hdr.type) { case IMSG_CONF_START: - if ((env->sc_rules_reload = calloc(1, sizeof(*env->sc_rules))) == NULL) - fatal("mfa_dispatch_parent: calloc"); - if ((env->sc_maps_reload = calloc(1, sizeof(*env->sc_maps))) == NULL) - fatal("mfa_dispatch_parent: calloc"); + env->sc_rules_reload = calloc(1, sizeof *env->sc_rules); + if (env->sc_rules_reload == NULL) + fatal(NULL); + env->sc_maps_reload = calloc(1, sizeof *env->sc_maps); + if (env->sc_maps_reload == NULL) + fatal(NULL); TAILQ_INIT(env->sc_rules_reload); TAILQ_INIT(env->sc_maps_reload); - break; - case IMSG_CONF_RULE: { - struct rule *rule = imsg.data; - - IMSG_SIZE_CHECK(rule); + return; - rule = calloc(1, sizeof(*rule)); + case IMSG_CONF_RULE: + rule = calloc(1, sizeof *rule); if (rule == NULL) - fatal("mfa_dispatch_parent: calloc"); - *rule = *(struct rule *)imsg.data; - + fatal(NULL); + *rule = *(struct rule *)imsg->data; TAILQ_INIT(&rule->r_conditions); TAILQ_INSERT_TAIL(env->sc_rules_reload, rule, r_entry); - break; - } - case IMSG_CONF_CONDITION: { - struct rule *r = TAILQ_LAST(env->sc_rules_reload, rulelist); - struct cond *cond = imsg.data; - - IMSG_SIZE_CHECK(cond); + return; - cond = calloc(1, sizeof(*cond)); + case IMSG_CONF_CONDITION: + rule = TAILQ_LAST(env->sc_rules_reload, rulelist); + cond = calloc(1, sizeof *cond); if (cond == NULL) - fatal("mfa_dispatch_parent: calloc"); - *cond = *(struct cond *)imsg.data; - - TAILQ_INSERT_TAIL(&r->r_conditions, cond, c_entry); - break; - } - case IMSG_CONF_MAP: { - struct map *m = imsg.data; - - IMSG_SIZE_CHECK(m); - - m = calloc(1, sizeof(*m)); - if (m == NULL) - fatal("mfa_dispatch_parent: calloc"); - *m = *(struct map *)imsg.data; + fatal(NULL); + *cond = *(struct cond *)imsg->data; + TAILQ_INSERT_TAIL(&rule->r_conditions, cond, c_entry); + return; - TAILQ_INIT(&m->m_contents); - TAILQ_INSERT_TAIL(env->sc_maps_reload, m, m_entry); - break; - } - case IMSG_CONF_RULE_SOURCE: { - struct rule *rule = TAILQ_LAST(env->sc_rules_reload, rulelist); - char *sourcemap = imsg.data; - void *temp = env->sc_maps; + case IMSG_CONF_MAP: + map = calloc(1, sizeof *map); + if (map == NULL) + fatal(NULL); + *map = *(struct map *)imsg->data; + TAILQ_INIT(&map->m_contents); + TAILQ_INSERT_TAIL(env->sc_maps_reload, map, m_entry); + return; - /* map lookup must be done in the reloaded conf */ + case IMSG_CONF_RULE_SOURCE: + rule = TAILQ_LAST(env->sc_rules_reload, rulelist); + tmp = env->sc_maps; env->sc_maps = env->sc_maps_reload; - rule->r_sources = map_findbyname(env, sourcemap); + rule->r_sources = map_findbyname(env, imsg->data); if (rule->r_sources == NULL) - fatalx("maps inconsistency"); - env->sc_maps = temp; - break; - } - case IMSG_CONF_MAP_CONTENT: { - struct map *m = TAILQ_LAST(env->sc_maps_reload, maplist); - struct mapel *mapel = imsg.data; - - IMSG_SIZE_CHECK(mapel); - - mapel = calloc(1, sizeof(*mapel)); + fatalx("lka: maps inconsistency"); + env->sc_maps = tmp; + return; + + case IMSG_CONF_MAP_CONTENT: + map = TAILQ_LAST(env->sc_maps_reload, maplist); + mapel = calloc(1, sizeof *mapel); if (mapel == NULL) - fatal("mfa_dispatch_parent: calloc"); - *mapel = *(struct mapel *)imsg.data; + fatal(NULL); + *mapel = *(struct mapel *)imsg->data; + TAILQ_INSERT_TAIL(&map->m_contents, mapel, me_entry); + return; - TAILQ_INSERT_TAIL(&m->m_contents, mapel, me_entry); - break; - } - case IMSG_CONF_END: { - /* switch and destroy old ruleset */ + case IMSG_CONF_END: if (env->sc_rules) purge_config(env, PURGE_RULES); if (env->sc_maps) purge_config(env, PURGE_MAPS); env->sc_rules = env->sc_rules_reload; env->sc_maps = env->sc_maps_reload; - break; - } - case IMSG_PARENT_FORWARD_OPEN: { - int fd; - struct forward_req *fwreq = imsg.data; - struct lkasession key; - struct lkasession *lkasession; - struct path *path; - - IMSG_SIZE_CHECK(fwreq); - - key.id = fwreq->id; - lkasession = SPLAY_FIND(lkatree, &env->lka_sessions, &key); - if (lkasession == NULL) - fatal("lka_dispatch_parent: lka session is gone"); - fd = imsg.fd; - --lkasession->pending; - - strlcpy(lkasession->path.pw_name, fwreq->pw_name, - sizeof(lkasession->path.pw_name)); - lkasession->path.flags |= F_PATH_FORWARDED; - - /* received a descriptor, we have a forward file ... */ - if (fd != -1) { - if (! forwards_get(fd, &lkasession->expandtree)) { - lkasession->ss.code = 530; - lkasession->flags |= F_ERROR; - } - close(fd); - lkasession->path.flags |= F_PATH_FORWARDED; - lka_expand_pickup(env, lkasession); - break; - } - - /* did not receive a descriptor but expected one ... */ - if (! fwreq->status) { - lkasession->ss.code = 530; - lkasession->flags |= F_ERROR; - lka_expand_pickup(env, lkasession); - break; - } - - /* no forward file, convert pw_name to a struct path ... */ - path = path_dup(&lkasession->path); - strlcpy(path->pw_name, fwreq->pw_name, sizeof(path->pw_name)); - TAILQ_INSERT_TAIL(&lkasession->deliverylist, path, entry); - lka_expand_pickup(env, lkasession); - break; - } - case IMSG_CTL_VERBOSE: { - int verbose; - - IMSG_SIZE_CHECK(&verbose); - - memcpy(&verbose, imsg.data, sizeof(verbose)); - log_verbose(verbose); - break; - } - default: - log_warnx("lka_dispatch_parent: got imsg %d", - imsg.hdr.type); - fatalx("lka_dispatch_parent: unexpected imsg"); - } - imsg_free(&imsg); - } - imsg_event_add(iev); -} - -void -lka_dispatch_mfa(int sig, short event, void *p) -{ - struct smtpd *env = p; - struct imsgev *iev; - struct imsgbuf *ibuf; - struct imsg imsg; - ssize_t n; - - iev = env->sc_ievs[PROC_MFA]; - ibuf = &iev->ibuf; - - if (event & EV_READ) { - if ((n = imsg_read(ibuf)) == -1) - fatal("imsg_read_error"); - if (n == 0) { - /* this pipe is dead, so remove the event handler */ - event_del(&iev->ev); - event_loopexit(NULL); return; - } - } - - if (event & EV_WRITE) { - if (msgbuf_write(&ibuf->w) == -1) - fatal("msgbuf_write"); - } - - for (;;) { - if ((n = imsg_get(ibuf, &imsg)) == -1) - fatal("lka_dispatch_mfa: imsg_get error"); - if (n == 0) - break; - - switch (imsg.hdr.type) { - case IMSG_LKA_MAIL: { - struct submit_status *ss = imsg.data; - - IMSG_SIZE_CHECK(ss); - - ss->code = 530; - - if (ss->u.path.user[0] == '\0' && ss->u.path.domain[0] == '\0') - ss->code = 250; - else - if (lka_verify_mail(env, &ss->u.path)) - ss->code = 250; - - imsg_compose_event(iev, IMSG_LKA_MAIL, 0, 0, -1, - ss, sizeof(*ss)); - break; - } - case IMSG_LKA_RULEMATCH: { - struct submit_status *ss = imsg.data; - struct rule *r; - - IMSG_SIZE_CHECK(ss); - - ss->code = 530; - - r = ruleset_match(env, ss->msg.tag, &ss->u.path, &ss->ss); - if (r != NULL) { - ss->code = 250; - ss->u.path.rule = *r; + case IMSG_PARENT_FORWARD_OPEN: + fwreq = imsg->data; + skey.id = fwreq->id; + s = SPLAY_FIND(lkatree, &env->lka_sessions, &skey); + if (s == NULL) + fatalx("lka: session missing"); + s->pending--; + strlcpy(s->path.pw_name, fwreq->pw_name, + sizeof s->path.pw_name); + s->path.flags |= F_PATH_FORWARDED; + + if (imsg->fd != -1) { + /* opened .forward okay */ + if (! forwards_get(imsg->fd, &s->expandtree)) { + s->ss.code = 530; + s->flags |= F_ERROR; + } + close(imsg->fd); + s->path.flags |= F_PATH_FORWARDED; + lka_expand_pickup(env, s); + } else { + if (fwreq->status) { + /* .forward not present */ + path = path_dup(&s->path); + strlcpy(path->pw_name, fwreq->pw_name, + sizeof path->pw_name); + TAILQ_INSERT_TAIL(&s->deliverylist, path, entry); + lka_expand_pickup(env, s); + } else { + /* opening .forward failed */ + s->ss.code = 530; + s->flags |= F_ERROR; + lka_expand_pickup(env, s); + } } - - imsg_compose_event(env->sc_ievs[PROC_MFA], IMSG_LKA_RULEMATCH, 0, 0, -1, - ss, sizeof(*ss)); - - break; - } - case IMSG_LKA_RCPT: { - struct submit_status *ss = imsg.data; - struct lkasession *lkasession; - struct path *path; - - IMSG_SIZE_CHECK(ss); - - ss->code = 250; - path = &ss->u.path; - - lkasession = lka_session_init(env, ss); - - if (! lka_resolve_path(env, lkasession, path)) - lka_session_fail(env, lkasession, ss); - else - lka_expand_pickup(env, lkasession); - - break; - } - default: - log_warnx("lka_dispatch_mfa: got imsg %d", - imsg.hdr.type); - fatalx("lka_dispatch_mfa: unexpected imsg"); - } - imsg_free(&imsg); - } - imsg_event_add(iev); -} - -void -lka_dispatch_mta(int sig, short event, void *p) -{ - struct smtpd *env = p; - struct imsgev *iev; - struct imsgbuf *ibuf; - struct imsg imsg; - ssize_t n; - - iev = env->sc_ievs[PROC_MTA]; - ibuf = &iev->ibuf; - - if (event & EV_READ) { - if ((n = imsg_read(ibuf)) == -1) - fatal("imsg_read_error"); - if (n == 0) { - /* this pipe is dead, so remove the event handler */ - event_del(&iev->ev); - event_loopexit(NULL); return; - } - } - if (event & EV_WRITE) { - if (msgbuf_write(&ibuf->w) == -1) - fatal("msgbuf_write"); - } - - for (;;) { - if ((n = imsg_get(ibuf, &imsg)) == -1) - fatal("lka_dispatch_mta: imsg_get error"); - if (n == 0) - break; - - switch (imsg.hdr.type) { - case IMSG_LKA_SECRET: { - struct secret *query = imsg.data; - char *secret = NULL; - struct map *map = NULL; - char *mapname = "secrets"; - - IMSG_SIZE_CHECK(query); - - /* should not happen */ - map = map_findbyname(env, mapname); - if (map == NULL) - fatalx("secrets map has disappeared"); - secret = map_lookup(env, map->m_id, query->host); - - log_debug("secret for %s %s", query->host, - secret ? "found" : "not found"); - - query->secret[0] = '\0'; - - if (secret == NULL) { - log_warnx("failed to lookup %s in the %s map", - query->host, mapname); - } else if (! lka_encode_credentials(query->secret, - sizeof(query->secret), secret)) { - log_warnx("parse error for %s in the %s map", - query->host, mapname); - } - - imsg_compose_event(iev, IMSG_LKA_SECRET, 0, 0, -1, query, - sizeof(*query)); - free(secret); - break; - } - - case IMSG_DNS_MX: - case IMSG_DNS_PTR: { - struct dns *query = imsg.data; - - IMSG_SIZE_CHECK(query); - dns_async(env, iev, imsg.hdr.type, query); - break; - } - - default: - log_warnx("lka_dispatch_mta: got imsg %d", - imsg.hdr.type); - fatalx("lka_dispatch_mta: unexpected imsg"); - } - imsg_free(&imsg); - } - imsg_event_add(iev); -} - -void -lka_dispatch_smtp(int sig, short event, void *p) -{ - struct smtpd *env = p; - struct imsgev *iev; - struct imsgbuf *ibuf; - struct imsg imsg; - ssize_t n; - - iev = env->sc_ievs[PROC_SMTP]; - ibuf = &iev->ibuf; - - if (event & EV_READ) { - if ((n = imsg_read(ibuf)) == -1) - fatal("imsg_read_error"); - if (n == 0) { - /* this pipe is dead, so remove the event handler */ - event_del(&iev->ev); - event_loopexit(NULL); + case IMSG_CTL_VERBOSE: + log_verbose(*(int *)imsg->data); return; } } - if (event & EV_WRITE) { - if (msgbuf_write(&ibuf->w) == -1) - fatal("msgbuf_write"); - } - - for (;;) { - if ((n = imsg_get(ibuf, &imsg)) == -1) - fatal("lka_dispatch_smtp: imsg_get error"); - if (n == 0) - break; - - switch (imsg.hdr.type) { - case IMSG_DNS_PTR: { - struct dns *query = imsg.data; - - IMSG_SIZE_CHECK(query); - dns_async(env, iev, IMSG_DNS_PTR, query); - break; - } - default: - log_warnx("lka_dispatch_smtp: got imsg %d", - imsg.hdr.type); - fatalx("lka_dispatch_smtp: unexpected imsg"); - } - imsg_free(&imsg); - } - imsg_event_add(iev); + fatalx("lka_imsg: unexpected imsg"); } void -lka_dispatch_queue(int sig, short event, void *p) -{ - struct smtpd *env = p; - struct imsgev *iev; - struct imsgbuf *ibuf; - struct imsg imsg; - ssize_t n; - - iev = env->sc_ievs[PROC_QUEUE]; - ibuf = &iev->ibuf; - - if (event & EV_READ) { - if ((n = imsg_read(ibuf)) == -1) - fatal("imsg_read_error"); - if (n == 0) { - /* this pipe is dead, so remove the event handler */ - event_del(&iev->ev); - event_loopexit(NULL); - return; - } - } - - if (event & EV_WRITE) { - if (msgbuf_write(&ibuf->w) == -1) - fatal("msgbuf_write"); - } - - for (;;) { - if ((n = imsg_get(ibuf, &imsg)) == -1) - fatal("lka_dispatch_queue: imsg_get error"); - if (n == 0) - break; - - switch (imsg.hdr.type) { - default: - log_warnx("lka_dispatch_queue: got imsg %d", - imsg.hdr.type); - fatalx("lka_dispatch_queue: unexpected imsg"); - } - imsg_free(&imsg); - } - imsg_event_add(iev); -} - -void -lka_dispatch_runner(int sig, short event, void *p) +lka_sig_handler(int sig, short event, void *p) { - struct smtpd *env = p; - struct imsgev *iev; - struct imsgbuf *ibuf; - struct imsg imsg; - ssize_t n; - - iev = env->sc_ievs[PROC_RUNNER]; - ibuf = &iev->ibuf; - - if (event & EV_READ) { - if ((n = imsg_read(ibuf)) == -1) - fatal("imsg_read_error"); - if (n == 0) { - /* this pipe is dead, so remove the event handler */ - event_del(&iev->ev); - event_loopexit(NULL); - return; - } - } - - if (event & EV_WRITE) { - if (msgbuf_write(&ibuf->w) == -1) - fatal("msgbuf_write"); - } - - for (;;) { - if ((n = imsg_get(ibuf, &imsg)) == -1) - fatal("lka_dispatch_runner: imsg_get error"); - if (n == 0) - break; + int status; + pid_t pid; - switch (imsg.hdr.type) { - default: - log_warnx("lka_dispatch_runner: got imsg %d", - imsg.hdr.type); - fatalx("lka_dispatch_runner: unexpected imsg"); - } - imsg_free(&imsg); + switch (sig) { + case SIGINT: + case SIGTERM: + lka_shutdown(); + break; + case SIGCHLD: + do { + pid = waitpid(-1, &status, WNOHANG); + } while (pid > 0 || (pid == -1 && errno == EINTR)); + break; + default: + fatalx("lka_sig_handler: unexpected signal"); } - imsg_event_add(iev); } void @@ -636,12 +311,12 @@ lka(struct smtpd *env) struct event ev_sigchld; struct peer peers[] = { - { PROC_PARENT, lka_dispatch_parent }, - { PROC_MFA, lka_dispatch_mfa }, - { PROC_QUEUE, lka_dispatch_queue }, - { PROC_SMTP, lka_dispatch_smtp }, - { PROC_RUNNER, lka_dispatch_runner }, - { PROC_MTA, lka_dispatch_mta } + { PROC_PARENT, imsg_dispatch }, + { PROC_MFA, imsg_dispatch }, + { PROC_QUEUE, imsg_dispatch }, + { PROC_SMTP, imsg_dispatch }, + { PROC_RUNNER, imsg_dispatch }, + { PROC_MTA, imsg_dispatch } }; switch (pid = fork()) { @@ -667,6 +342,7 @@ lka(struct smtpd *env) fatal("lka: cannot drop privileges"); #endif + imsg_callback = lka_imsg; event_init(); SPLAY_INIT(&env->lka_sessions); diff --git a/usr.sbin/smtpd/mda.c b/usr.sbin/smtpd/mda.c index 750f80b8c97..a9b52bdb8bb 100644 --- a/usr.sbin/smtpd/mda.c +++ b/usr.sbin/smtpd/mda.c @@ -1,4 +1,4 @@ -/* $OpenBSD: mda.c,v 1.39 2010/04/19 20:10:36 jacekm Exp $ */ +/* $OpenBSD: mda.c,v 1.40 2010/04/20 15:34:56 jacekm Exp $ */ /* * Copyright (c) 2008 Gilles Chehade <gilles@openbsd.org> @@ -37,11 +37,9 @@ #include "smtpd.h" +void mda_imsg(struct smtpd *, struct imsgev *, struct imsg *); __dead void mda_shutdown(void); void mda_sig_handler(int, short, void *); -void mda_dispatch_parent(int, short, void *); -void mda_dispatch_queue(int, short, void *); -void mda_dispatch_runner(int, short, void *); void mda_setup_events(struct smtpd *); void mda_disable_events(struct smtpd *); void mda_store(struct mda_session *); @@ -51,88 +49,106 @@ struct mda_session *mda_lookup(struct smtpd *, u_int32_t); int mda_id; void -mda_sig_handler(int sig, short event, void *p) +mda_imsg(struct smtpd *env, struct imsgev *iev, struct imsg *imsg) { - switch (sig) { - case SIGINT: - case SIGTERM: - mda_shutdown(); - break; - default: - fatalx("mda_sig_handler: unexpected signal"); - } -} + char output[128], *error, *parent_error; + struct deliver deliver; + struct mda_session *s; + struct path *path; + + if (iev->proc == PROC_RUNNER) { + switch (imsg->hdr.type) { + case IMSG_MDA_SESS_NEW: + /* make new session based on provided args */ + s = calloc(1, sizeof *s); + if (s == NULL) + fatal(NULL); + msgbuf_init(&s->w); + s->msg = *(struct message *)imsg->data; + s->msg.status = S_MESSAGE_TEMPFAILURE; + s->id = mda_id++; + s->datafp = fdopen(imsg->fd, "r"); + if (s->datafp == NULL) + fatalx("mda: fdopen"); + LIST_INSERT_HEAD(&env->mda_sessions, s, entry); -void -mda_dispatch_parent(int sig, short event, void *p) -{ - struct smtpd *env = p; - struct imsgev *iev; - struct imsgbuf *ibuf; - struct imsg imsg; - ssize_t n; - - iev = env->sc_ievs[PROC_PARENT]; - ibuf = &iev->ibuf; - - if (event & EV_READ) { - if ((n = imsg_read(ibuf)) == -1) - fatal("imsg_read_error"); - if (n == 0) { - /* this pipe is dead, so remove the event handler */ - event_del(&iev->ev); - event_loopexit(NULL); - return; - } - } + /* request parent to fork a helper process */ + path = &s->msg.recipient; + switch (path->rule.r_action) { + case A_EXT: + deliver.mode = A_EXT; + strlcpy(deliver.user, path->pw_name, + sizeof deliver.user); + strlcpy(deliver.to, path->rule.r_value.path, + sizeof deliver.to); + break; - if (event & EV_WRITE) { - if (msgbuf_write(&ibuf->w) == -1) - fatal("msgbuf_write"); - } + case A_MBOX: + deliver.mode = A_EXT; + strlcpy(deliver.user, "root", + sizeof deliver.user); + snprintf(deliver.to, sizeof deliver.to, + "%s -f %s@%s %s", PATH_MAILLOCAL, + s->msg.sender.user, s->msg.sender.domain, + path->pw_name); + break; - for (;;) { - if ((n = imsg_get(ibuf, &imsg)) == -1) - fatal("mda_dispatch_parent: imsg_get error"); - if (n == 0) - break; + case A_MAILDIR: + deliver.mode = A_MAILDIR; + strlcpy(deliver.user, path->pw_name, + sizeof deliver.user); + strlcpy(deliver.to, path->rule.r_value.path, + sizeof deliver.to); + break; - switch (imsg.hdr.type) { - case IMSG_PARENT_FORK_MDA: { - struct mda_session *s; + case A_FILENAME: + deliver.mode = A_FILENAME; + /* XXX: unconditional SMTPD_USER is wrong. */ + strlcpy(deliver.user, SMTPD_USER, + sizeof deliver.user); + strlcpy(deliver.to, path->u.filename, + sizeof deliver.to); + break; - s = mda_lookup(env, imsg.hdr.peerid); + default: + fatalx("mda: unknown rule action"); + } - if (imsg.fd < 0) + imsg_compose_event(env->sc_ievs[PROC_PARENT], + IMSG_PARENT_FORK_MDA, s->id, 0, -1, &deliver, + sizeof deliver); + return; + } + } + + if (iev->proc == PROC_PARENT) { + switch (imsg->hdr.type) { + case IMSG_PARENT_FORK_MDA: + s = mda_lookup(env, imsg->hdr.peerid); + + if (imsg->fd < 0) fatalx("mda: fd pass fail"); - s->w.fd = imsg.fd; + s->w.fd = imsg->fd; - /* send message content to the helper process */ mda_store(s); - break; - } - - case IMSG_MDA_DONE: { - char output[128]; - struct mda_session *s; - struct path *path; - char *error, *parent_error; + return; - s = mda_lookup(env, imsg.hdr.peerid); + case IMSG_MDA_DONE: + s = mda_lookup(env, imsg->hdr.peerid); /* * Grab last line of mda stdout/stderr if available. */ output[0] = '\0'; - if (imsg.fd != -1) { + if (imsg->fd != -1) { char *ln, *buf; FILE *fp; size_t len; buf = NULL; - if (lseek(imsg.fd, 0, SEEK_SET) < 0) + if (lseek(imsg->fd, 0, SEEK_SET) < 0) fatalx("lseek"); - fp = fdopen(imsg.fd, "r"); + fp = fdopen(imsg->fd, "r"); if (fp == NULL) fatal("mda: fdopen"); while ((ln = fgetln(fp, &len))) { @@ -163,7 +179,7 @@ mda_dispatch_parent(int sig, short event, void *p) * the former. */ error = NULL; - parent_error = imsg.data; + parent_error = imsg->data; if (strcmp(parent_error, "exited okay") == 0) { if (!feof(s->datafp) || s->w.queued) error = "mda exited prematurely"; @@ -218,185 +234,30 @@ mda_dispatch_parent(int sig, short event, void *p) /* update runner's session count */ imsg_compose_event(env->sc_ievs[PROC_RUNNER], IMSG_MDA_SESS_NEW, 0, 0, -1, NULL, 0); - break; - } - - case IMSG_CTL_VERBOSE: { - int verbose; - - IMSG_SIZE_CHECK(&verbose); - - memcpy(&verbose, imsg.data, sizeof(verbose)); - log_verbose(verbose); - break; - } - - default: - log_warnx("mda_dispatch_parent: got imsg %d", - imsg.hdr.type); - fatalx("mda_dispatch_parent: unexpected imsg"); - } - imsg_free(&imsg); - } - imsg_event_add(iev); -} + return; -void -mda_dispatch_queue(int sig, short event, void *p) -{ - struct smtpd *env = p; - struct imsgev *iev; - struct imsgbuf *ibuf; - struct imsg imsg; - ssize_t n; - - iev = env->sc_ievs[PROC_QUEUE]; - ibuf = &iev->ibuf; - - if (event & EV_READ) { - if ((n = imsg_read(ibuf)) == -1) - fatal("imsg_read_error"); - if (n == 0) { - /* this pipe is dead, so remove the event handler */ - event_del(&iev->ev); - event_loopexit(NULL); + case IMSG_CTL_VERBOSE: + log_verbose(*(int *)imsg->data); return; } } - if (event & EV_WRITE) { - if (msgbuf_write(&ibuf->w) == -1) - fatal("msgbuf_write"); - } - - for (;;) { - if ((n = imsg_get(ibuf, &imsg)) == -1) - fatal("mda_dispatch_queue: imsg_get error"); - if (n == 0) - break; - - switch (imsg.hdr.type) { - default: - log_warnx("mda_dispatch_queue: got imsg %d", - imsg.hdr.type); - fatalx("mda_dispatch_queue: unexpected imsg"); - } - imsg_free(&imsg); - } - imsg_event_add(iev); + fatalx("mda_imsg: unexpected imsg"); } void -mda_dispatch_runner(int sig, short event, void *p) +mda_sig_handler(int sig, short event, void *p) { - struct smtpd *env = p; - struct imsgev *iev; - struct imsgbuf *ibuf; - struct imsg imsg; - ssize_t n; - - iev = env->sc_ievs[PROC_RUNNER]; - ibuf = &iev->ibuf; - - if (event & EV_READ) { - if ((n = imsg_read(ibuf)) == -1) - fatal("imsg_read_error"); - if (n == 0) { - /* this pipe is dead, so remove the event handler */ - event_del(&iev->ev); - event_loopexit(NULL); - return; - } - } - - if (event & EV_WRITE) { - if (msgbuf_write(&ibuf->w) == -1) - fatal("msgbuf_write"); - } - - for (;;) { - if ((n = imsg_get(ibuf, &imsg)) == -1) - fatal("mda_dispatch_runner: imsg_get error"); - if (n == 0) - break; - - switch (imsg.hdr.type) { - case IMSG_MDA_SESS_NEW: { - struct deliver deliver; - struct mda_session *s; - struct path *path; - - /* make new session based on provided args */ - s = calloc(1, sizeof *s); - if (s == NULL) - fatal(NULL); - msgbuf_init(&s->w); - s->msg = *(struct message *)imsg.data; - s->msg.status = S_MESSAGE_TEMPFAILURE; - s->id = mda_id++; - s->datafp = fdopen(imsg.fd, "r"); - if (s->datafp == NULL) - fatalx("mda: fdopen"); - LIST_INSERT_HEAD(&env->mda_sessions, s, entry); - - /* request parent to fork a helper process */ - path = &s->msg.recipient; - switch (path->rule.r_action) { - case A_EXT: - deliver.mode = A_EXT; - strlcpy(deliver.user, path->pw_name, - sizeof deliver.user); - strlcpy(deliver.to, path->rule.r_value.path, - sizeof deliver.to); - break; - - case A_MBOX: - deliver.mode = A_EXT; - strlcpy(deliver.user, "root", - sizeof deliver.user); - snprintf(deliver.to, sizeof deliver.to, - "%s -f %s@%s %s", PATH_MAILLOCAL, - s->msg.sender.user, s->msg.sender.domain, - path->pw_name); - break; - - case A_MAILDIR: - deliver.mode = A_MAILDIR; - strlcpy(deliver.user, path->pw_name, - sizeof deliver.user); - strlcpy(deliver.to, path->rule.r_value.path, - sizeof deliver.to); - break; - - case A_FILENAME: - deliver.mode = A_FILENAME; - /* XXX: unconditional SMTPD_USER is wrong. */ - strlcpy(deliver.user, SMTPD_USER, - sizeof deliver.user); - strlcpy(deliver.to, path->u.filename, - sizeof deliver.to); - break; - - default: - fatalx("unknown rule action"); - } - - imsg_compose_event(env->sc_ievs[PROC_PARENT], - IMSG_PARENT_FORK_MDA, s->id, 0, -1, &deliver, - sizeof deliver); - break; - } - default: - log_warnx("mda_dispatch_runner: got imsg %d", - imsg.hdr.type); - fatalx("mda_dispatch_runner: unexpected imsg"); - } - imsg_free(&imsg); + switch (sig) { + case SIGINT: + case SIGTERM: + mda_shutdown(); + break; + default: + fatalx("mda_sig_handler: unexpected signal"); } - imsg_event_add(iev); } - void mda_shutdown(void) { @@ -424,9 +285,9 @@ mda(struct smtpd *env) struct event ev_sigterm; struct peer peers[] = { - { PROC_PARENT, mda_dispatch_parent }, - { PROC_QUEUE, mda_dispatch_queue }, - { PROC_RUNNER, mda_dispatch_runner } + { PROC_PARENT, imsg_dispatch }, + { PROC_QUEUE, imsg_dispatch }, + { PROC_RUNNER, imsg_dispatch } }; switch (pid = fork()) { @@ -463,6 +324,7 @@ mda(struct smtpd *env) LIST_INIT(&env->mda_sessions); + imsg_callback = mda_imsg; event_init(); signal_set(&ev_sigint, SIGINT, mda_sig_handler, env); diff --git a/usr.sbin/smtpd/mfa.c b/usr.sbin/smtpd/mfa.c index c9001efe249..67be9daed7a 100644 --- a/usr.sbin/smtpd/mfa.c +++ b/usr.sbin/smtpd/mfa.c @@ -1,4 +1,4 @@ -/* $OpenBSD: mfa.c,v 1.43 2010/01/03 14:37:37 chl Exp $ */ +/* $OpenBSD: mfa.c,v 1.44 2010/04/20 15:34:56 jacekm Exp $ */ /* * Copyright (c) 2008 Gilles Chehade <gilles@openbsd.org> @@ -34,12 +34,9 @@ #include "smtpd.h" +void mfa_imsg(struct smtpd *, struct imsgev *, struct imsg *); __dead void mfa_shutdown(void); void mfa_sig_handler(int, short, void *); -void mfa_dispatch_parent(int, short, void *); -void mfa_dispatch_smtp(int, short, void *); -void mfa_dispatch_lka(int, short, void *); -void mfa_dispatch_control(int, short, void *); void mfa_setup_events(struct smtpd *); void mfa_disable_events(struct smtpd *); @@ -52,249 +49,57 @@ int strip_source_route(char *, size_t); struct rule *ruleset_match(struct smtpd *, struct path *, struct sockaddr_storage *); void -mfa_sig_handler(int sig, short event, void *p) -{ - switch (sig) { - case SIGINT: - case SIGTERM: - mfa_shutdown(); - break; - default: - fatalx("mfa_sig_handler: unexpected signal"); - } -} - -void -mfa_dispatch_parent(int sig, short event, void *p) +mfa_imsg(struct smtpd *env, struct imsgev *iev, struct imsg *imsg) { - struct smtpd *env = p; - struct imsgev *iev; - struct imsgbuf *ibuf; - struct imsg imsg; - ssize_t n; - - iev = env->sc_ievs[PROC_PARENT]; - ibuf = &iev->ibuf; - - if (event & EV_READ) { - if ((n = imsg_read(ibuf)) == -1) - fatal("imsg_read_error"); - if (n == 0) { - /* this pipe is dead, so remove the event handler */ - event_del(&iev->ev); - event_loopexit(NULL); + if (iev->proc == PROC_SMTP) { + switch (imsg->hdr.type) { + case IMSG_MFA_MAIL: + mfa_test_mail(env, imsg->data); return; - } - } - - if (event & EV_WRITE) { - if (msgbuf_write(&ibuf->w) == -1) - fatal("msgbuf_write"); - } - - for (;;) { - if ((n = imsg_get(ibuf, &imsg)) == -1) - fatal("mfa_dispatch_parent: imsg_get error"); - if (n == 0) - break; - switch (imsg.hdr.type) { - case IMSG_CTL_VERBOSE: { - int verbose; - - IMSG_SIZE_CHECK(&verbose); - - memcpy(&verbose, imsg.data, sizeof(verbose)); - log_verbose(verbose); - break; - } - default: - log_warnx("mfa_dispatch_parent: got imsg %d", - imsg.hdr.type); - fatalx("mfa_dispatch_parent: unexpected imsg"); - } - imsg_free(&imsg); - } - imsg_event_add(iev); -} - -void -mfa_dispatch_smtp(int sig, short event, void *p) -{ - struct smtpd *env = p; - struct imsgev *iev; - struct imsgbuf *ibuf; - struct imsg imsg; - ssize_t n; - - iev = env->sc_ievs[PROC_SMTP]; - ibuf = &iev->ibuf; - - if (event & EV_READ) { - if ((n = imsg_read(ibuf)) == -1) - fatal("imsg_read_error"); - if (n == 0) { - /* this pipe is dead, so remove the event handler */ - event_del(&iev->ev); - event_loopexit(NULL); + case IMSG_MFA_RCPT: + mfa_test_rcpt(env, imsg->data); return; } } - if (event & EV_WRITE) { - if (msgbuf_write(&ibuf->w) == -1) - fatal("msgbuf_write"); - } - - for (;;) { - if ((n = imsg_get(ibuf, &imsg)) == -1) - fatal("mfa_dispatch_smtp: imsg_get error"); - if (n == 0) - break; - - switch (imsg.hdr.type) { - case IMSG_MFA_MAIL: { - struct message *m = imsg.data; - - IMSG_SIZE_CHECK(m); - - mfa_test_mail(env, m); - break; - } - - case IMSG_MFA_RCPT: { - struct message *m = imsg.data; - - IMSG_SIZE_CHECK(m); - - mfa_test_rcpt(env, m); - break; - } + if (iev->proc == PROC_LKA) { + switch (imsg->hdr.type) { + case IMSG_LKA_MAIL: + case IMSG_LKA_RCPT: + imsg_compose_event(env->sc_ievs[PROC_SMTP], + IMSG_MFA_MAIL, 0, 0, -1, imsg->data, + sizeof(struct submit_status)); + return; - default: - log_warnx("mfa_dispatch_smtp: got imsg %d", - imsg.hdr.type); - fatalx("mfa_dispatch_smtp: unexpected imsg"); + case IMSG_LKA_RULEMATCH: + mfa_test_rcpt_resume(env, imsg->data); + return; } - imsg_free(&imsg); } - imsg_event_add(iev); -} -void -mfa_dispatch_lka(int sig, short event, void *p) -{ - struct smtpd *env = p; - struct imsgev *iev; - struct imsgbuf *ibuf; - struct imsg imsg; - ssize_t n; - - iev = env->sc_ievs[PROC_LKA]; - ibuf = &iev->ibuf; - - if (event & EV_READ) { - if ((n = imsg_read(ibuf)) == -1) - fatal("imsg_read_error"); - if (n == 0) { - /* this pipe is dead, so remove the event handler */ - event_del(&iev->ev); - event_loopexit(NULL); + if (iev->proc == PROC_PARENT) { + switch (imsg->hdr.type) { + case IMSG_CTL_VERBOSE: + log_verbose(*(int *)imsg->data); return; } } - if (event & EV_WRITE) { - if (msgbuf_write(&ibuf->w) == -1) - fatal("msgbuf_write"); - } - - for (;;) { - if ((n = imsg_get(ibuf, &imsg)) == -1) - fatal("mfa_dispatch_lka: imsg_get error"); - if (n == 0) - break; - - switch (imsg.hdr.type) { - case IMSG_LKA_MAIL: { - struct submit_status *ss = imsg.data; - - IMSG_SIZE_CHECK(ss); - - imsg_compose_event(env->sc_ievs[PROC_SMTP], IMSG_MFA_MAIL, - 0, 0, -1, ss, sizeof(*ss)); - break; - } - case IMSG_LKA_RCPT: { - struct submit_status *ss = imsg.data; - - IMSG_SIZE_CHECK(ss); - - imsg_compose_event(env->sc_ievs[PROC_SMTP], IMSG_MFA_RCPT, - 0, 0, -1, ss, sizeof(*ss)); - break; - } - case IMSG_LKA_RULEMATCH: { - struct submit_status *ss = imsg.data; - - IMSG_SIZE_CHECK(ss); - - mfa_test_rcpt_resume(env, ss); - break; - } - default: - log_warnx("mfa_dispatch_lka: got imsg %d", - imsg.hdr.type); - fatalx("mfa_dispatch_lka: unexpected imsg"); - } - imsg_free(&imsg); - } - imsg_event_add(iev); + fatalx("mfa_imsg: unexpected imsg"); } void -mfa_dispatch_control(int sig, short event, void *p) +mfa_sig_handler(int sig, short event, void *p) { - struct smtpd *env = p; - struct imsgev *iev; - struct imsgbuf *ibuf; - struct imsg imsg; - ssize_t n; - - iev = env->sc_ievs[PROC_CONTROL]; - ibuf = &iev->ibuf; - - if (event & EV_READ) { - if ((n = imsg_read(ibuf)) == -1) - fatal("imsg_read_error"); - if (n == 0) { - /* this pipe is dead, so remove the event handler */ - event_del(&iev->ev); - event_loopexit(NULL); - return; - } - } - - if (event & EV_WRITE) { - if (msgbuf_write(&ibuf->w) == -1) - fatal("msgbuf_write"); - } - - for (;;) { - if ((n = imsg_get(ibuf, &imsg)) == -1) - fatal("mfa_dispatch_control: imsg_get error"); - if (n == 0) - break; - - switch (imsg.hdr.type) { - default: - log_warnx("mfa_dispatch_control: got imsg %d", - imsg.hdr.type); - fatalx("mfa_dispatch_control: unexpected imsg"); - } - imsg_free(&imsg); + switch (sig) { + case SIGINT: + case SIGTERM: + mfa_shutdown(); + break; + default: + fatalx("mfa_sig_handler: unexpected signal"); } - imsg_event_add(iev); } void @@ -324,10 +129,10 @@ mfa(struct smtpd *env) struct event ev_sigterm; struct peer peers[] = { - { PROC_PARENT, mfa_dispatch_parent }, - { PROC_SMTP, mfa_dispatch_smtp }, - { PROC_LKA, mfa_dispatch_lka }, - { PROC_CONTROL, mfa_dispatch_control}, + { PROC_PARENT, imsg_dispatch }, + { PROC_SMTP, imsg_dispatch }, + { PROC_LKA, imsg_dispatch }, + { PROC_CONTROL, imsg_dispatch } }; switch (pid = fork()) { @@ -362,6 +167,7 @@ mfa(struct smtpd *env) fatal("mfa: cannot drop privileges"); #endif + imsg_callback = mfa_imsg; event_init(); signal_set(&ev_sigint, SIGINT, mfa_sig_handler, env); diff --git a/usr.sbin/smtpd/mta.c b/usr.sbin/smtpd/mta.c index f1c10568ff3..9e79befd184 100644 --- a/usr.sbin/smtpd/mta.c +++ b/usr.sbin/smtpd/mta.c @@ -1,4 +1,4 @@ -/* $OpenBSD: mta.c,v 1.84 2010/01/03 14:37:37 chl Exp $ */ +/* $OpenBSD: mta.c,v 1.85 2010/04/20 15:34:56 jacekm Exp $ */ /* * Copyright (c) 2008 Pierre-Yves Ritschard <pyr@openbsd.org> @@ -41,14 +41,11 @@ #include "smtpd.h" #include "client.h" +void mta_imsg(struct smtpd *, struct imsgev *, struct imsg *); + __dead void mta_shutdown(void); void mta_sig_handler(int, short, void *); -void mta_dispatch_parent(int, short, void *); -void mta_dispatch_runner(int, short, void *); -void mta_dispatch_queue(int, short, void *); -void mta_dispatch_lka(int, short, void *); - struct mta_session *mta_lookup(struct smtpd *, u_int64_t); void mta_enter_state(struct mta_session *, int, void *); void mta_pickup(struct mta_session *, void *); @@ -62,151 +59,22 @@ void mta_connect_done(int, short, void *); void mta_request_datafd(struct mta_session *); void -mta_sig_handler(int sig, short event, void *p) +mta_imsg(struct smtpd *env, struct imsgev *iev, struct imsg *imsg) { - switch (sig) { - case SIGINT: - case SIGTERM: - mta_shutdown(); - break; - default: - fatalx("mta_sig_handler: unexpected signal"); - } -} - -void -mta_dispatch_parent(int sig, short event, void *p) -{ - struct smtpd *env = p; - struct imsgev *iev; - struct imsgbuf *ibuf; - struct imsg imsg; - ssize_t n; - - iev = env->sc_ievs[PROC_PARENT]; - ibuf = &iev->ibuf; - - if (event & EV_READ) { - if ((n = imsg_read(ibuf)) == -1) - fatal("imsg_read_error"); - if (n == 0) { - /* this pipe is dead, so remove the event handler */ - event_del(&iev->ev); - event_loopexit(NULL); - return; - } - } - - if (event & EV_WRITE) { - if (msgbuf_write(&ibuf->w) == -1) - fatal("msgbuf_write"); - } - - for (;;) { - if ((n = imsg_get(ibuf, &imsg)) == -1) - fatal("mta_dispatch_parent: imsg_get error"); - if (n == 0) - break; - - switch (imsg.hdr.type) { - case IMSG_CONF_START: - if (env->sc_flags & SMTPD_CONFIGURING) - break; - env->sc_flags |= SMTPD_CONFIGURING; - - if ((env->sc_ssl = calloc(1, sizeof(*env->sc_ssl))) == NULL) - fatal("mta_dispatch_parent: calloc"); - break; - case IMSG_CONF_SSL: { - struct ssl *s; - struct ssl *x_ssl; - - if (!(env->sc_flags & SMTPD_CONFIGURING)) - break; - - if ((s = calloc(1, sizeof(*s))) == NULL) - fatal(NULL); - x_ssl = imsg.data; - (void)strlcpy(s->ssl_name, x_ssl->ssl_name, - sizeof(s->ssl_name)); - s->ssl_cert_len = x_ssl->ssl_cert_len; - if ((s->ssl_cert = - strdup((char *)imsg.data + sizeof(*s))) == NULL) - fatal(NULL); - s->ssl_key_len = x_ssl->ssl_key_len; - if ((s->ssl_key = strdup((char *)imsg.data + - (sizeof(*s) + s->ssl_cert_len))) == NULL) - fatal(NULL); - - SPLAY_INSERT(ssltree, env->sc_ssl, s); - break; - } - case IMSG_CONF_END: - if (!(env->sc_flags & SMTPD_CONFIGURING)) - break; - env->sc_flags &= ~SMTPD_CONFIGURING; - break; - case IMSG_CTL_VERBOSE: { - int verbose; - - IMSG_SIZE_CHECK(&verbose); - - memcpy(&verbose, imsg.data, sizeof(verbose)); - log_verbose(verbose); - break; - } - default: - log_warnx("mta_dispatch_parent: got imsg %d", - imsg.hdr.type); - fatalx("mta_dispatch_parent: unexpected imsg"); - } - imsg_free(&imsg); - } - imsg_event_add(iev); -} - -void -mta_dispatch_runner(int sig, short event, void *p) -{ - struct smtpd *env = p; - struct imsgev *iev; - struct imsgbuf *ibuf; - struct imsg imsg; - ssize_t n; - - iev = env->sc_ievs[PROC_RUNNER]; - ibuf = &iev->ibuf; - - if (event & EV_READ) { - if ((n = imsg_read(ibuf)) == -1) - fatal("imsg_read_error"); - if (n == 0) { - /* this pipe is dead, so remove the event handler */ - event_del(&iev->ev); - event_loopexit(NULL); - return; - } - } - - if (event & EV_WRITE) { - if (msgbuf_write(&ibuf->w) == -1) - fatal("msgbuf_write"); - } - - for (;;) { - if ((n = imsg_get(ibuf, &imsg)) == -1) - fatal("mta_dispatch_runner: imsg_get error"); - if (n == 0) - break; - - switch (imsg.hdr.type) { - case IMSG_BATCH_CREATE: { - struct batch *b = imsg.data; - struct mta_session *s; - - IMSG_SIZE_CHECK(b); - - if ((s = calloc(1, sizeof(*s))) == NULL) + struct mta_session *s; + struct mta_relay *relay; + struct message *m; + struct secret *secret; + struct batch *b; + struct dns *dns; + struct ssl *ssl; + + if (iev->proc == PROC_RUNNER) { + switch (imsg->hdr.type) { + case IMSG_BATCH_CREATE: + b = imsg->data; + s = calloc(1, sizeof *s); + if (s == NULL) fatal(NULL); s->id = b->id; s->state = MTA_INIT; @@ -258,190 +126,128 @@ mta_dispatch_runner(int sig, short event, void *p) TAILQ_INIT(&s->recipients); TAILQ_INIT(&s->relays); SPLAY_INSERT(mtatree, &env->mta_sessions, s); - break; - } - - case IMSG_BATCH_APPEND: { - struct message *append = imsg.data, *m; - struct mta_session *s; - - IMSG_SIZE_CHECK(append); + return; - s = mta_lookup(env, append->batch_id); - if ((m = malloc(sizeof(*m))) == NULL) + case IMSG_BATCH_APPEND: + m = imsg->data; + s = mta_lookup(env, m->batch_id); + m = malloc(sizeof *m); + if (m == NULL) fatal(NULL); - *m = *append; + *m = *(struct message *)imsg->data; strlcpy(m->session_errorline, "000 init", sizeof(m->session_errorline)); TAILQ_INSERT_TAIL(&s->recipients, m, entry); - break; - } - - case IMSG_BATCH_CLOSE: { - struct batch *b = imsg.data; + return; - IMSG_SIZE_CHECK(b); + case IMSG_BATCH_CLOSE: + b = imsg->data; mta_pickup(mta_lookup(env, b->id), NULL); - break; - } - - default: - log_warnx("mta_dispatch_runner: got imsg %d", - imsg.hdr.type); - fatalx("mta_dispatch_runner: unexpected imsg"); - } - imsg_free(&imsg); - } - imsg_event_add(iev); -} - -void -mta_dispatch_lka(int sig, short event, void *p) -{ - struct smtpd *env = p; - struct imsgev *iev; - struct imsgbuf *ibuf; - struct imsg imsg; - ssize_t n; - - iev = env->sc_ievs[PROC_LKA]; - ibuf = &iev->ibuf; - - if (event & EV_READ) { - if ((n = imsg_read(ibuf)) == -1) - fatal("imsg_read_error"); - if (n == 0) { - /* this pipe is dead, so remove the event handler */ - event_del(&iev->ev); - event_loopexit(NULL); return; } } - if (event & EV_WRITE) { - if (msgbuf_write(&ibuf->w) == -1) - fatal("msgbuf_write"); - } - - for (;;) { - if ((n = imsg_get(ibuf, &imsg)) == -1) - fatal("mta_dispatch_lka: imsg_get error"); - if (n == 0) - break; - - switch (imsg.hdr.type) { - case IMSG_LKA_SECRET: { - struct secret *reply = imsg.data; - - IMSG_SIZE_CHECK(reply); - - mta_pickup(mta_lookup(env, reply->id), reply->secret); - break; - } - - case IMSG_DNS_A: { - struct dns *reply = imsg.data; - struct mta_relay *relay; - struct mta_session *s; - - IMSG_SIZE_CHECK(reply); + if (iev->proc == PROC_LKA) { + switch (imsg->hdr.type) { + case IMSG_LKA_SECRET: + secret = imsg->data; + mta_pickup(mta_lookup(env, secret->id), secret->secret); + return; - s = mta_lookup(env, reply->id); - if ((relay = calloc(1, sizeof(*relay))) == NULL) + case IMSG_DNS_A: + dns = imsg->data; + s = mta_lookup(env, dns->id); + relay = calloc(1, sizeof *relay); + if (relay == NULL) fatal(NULL); - relay->sa = reply->ss; + relay->sa = dns->ss; TAILQ_INSERT_TAIL(&s->relays, relay, entry); - break; - } - - case IMSG_DNS_A_END: { - struct dns *reply = imsg.data; - - IMSG_SIZE_CHECK(reply); - - mta_pickup(mta_lookup(env, reply->id), &reply->error); - break; - } - - case IMSG_DNS_PTR: { - struct dns *reply = imsg.data; - struct mta_session *s; - struct mta_relay *r; + return; - IMSG_SIZE_CHECK(reply); + case IMSG_DNS_A_END: + dns = imsg->data; + mta_pickup(mta_lookup(env, dns->id), &dns->error); + return; - s = mta_lookup(env, reply->id); - r = TAILQ_FIRST(&s->relays); - if (reply->error) - strlcpy(r->fqdn, "<unknown>", sizeof(r->fqdn)); + case IMSG_DNS_PTR: + dns = imsg->data; + s = mta_lookup(env, dns->id); + relay = TAILQ_FIRST(&s->relays); + if (dns->error) + strlcpy(relay->fqdn, "<unknown>", + sizeof relay->fqdn); else - strlcpy(r->fqdn, reply->host, sizeof(r->fqdn)); + strlcpy(relay->fqdn, dns->host, + sizeof relay->fqdn); mta_pickup(s, NULL); - break; - } - - default: - log_warnx("mta_dispatch_parent: got imsg %d", - imsg.hdr.type); - fatalx("mta_dispatch_lka: unexpected imsg"); + return; } - imsg_free(&imsg); } - imsg_event_add(iev); -} -void -mta_dispatch_queue(int sig, short event, void *p) -{ - struct smtpd *env = p; - struct imsgev *iev; - struct imsgbuf *ibuf; - struct imsg imsg; - ssize_t n; - - iev = env->sc_ievs[PROC_QUEUE]; - ibuf = &iev->ibuf; - - if (event & EV_READ) { - if ((n = imsg_read(ibuf)) == -1) - fatal("imsg_read_error"); - if (n == 0) { - /* this pipe is dead, so remove the event handler */ - event_del(&iev->ev); - event_loopexit(NULL); + if (iev->proc == PROC_QUEUE) { + switch (imsg->hdr.type) { + case IMSG_QUEUE_MESSAGE_FD: + b = imsg->data; + mta_pickup(mta_lookup(env, b->id), &imsg->fd); return; } } - if (event & EV_WRITE) { - if (msgbuf_write(&ibuf->w) == -1) - fatal("msgbuf_write"); - } - - for (;;) { - if ((n = imsg_get(ibuf, &imsg)) == -1) - fatal("mta_dispatch_queue: imsg_get error"); - if (n == 0) - break; + if (iev->proc == PROC_PARENT) { + switch (imsg->hdr.type) { + case IMSG_CONF_START: + if (env->sc_flags & SMTPD_CONFIGURING) + return; + env->sc_flags |= SMTPD_CONFIGURING; + env->sc_ssl = calloc(1, sizeof *env->sc_ssl); + if (env->sc_ssl == NULL) + fatal(NULL); + return; - switch (imsg.hdr.type) { - case IMSG_QUEUE_MESSAGE_FD: { - struct batch *b = imsg.data; + case IMSG_CONF_SSL: + if (!(env->sc_flags & SMTPD_CONFIGURING)) + return; + ssl = calloc(1, sizeof *ssl); + if (ssl == NULL) + fatal(NULL); + *ssl = *(struct ssl *)imsg->data; + ssl->ssl_cert = strdup((char *)imsg->data + + sizeof *ssl); + if (ssl->ssl_cert == NULL) + fatal(NULL); + ssl->ssl_key = strdup((char *)imsg->data + + sizeof *ssl + ssl->ssl_cert_len); + if (ssl->ssl_key == NULL) + fatal(NULL); + SPLAY_INSERT(ssltree, env->sc_ssl, ssl); + return; - IMSG_SIZE_CHECK(b); + case IMSG_CONF_END: + if (!(env->sc_flags & SMTPD_CONFIGURING)) + return; + env->sc_flags &= ~SMTPD_CONFIGURING; + return; - mta_pickup(mta_lookup(env, b->id), &imsg.fd); - break; + case IMSG_CTL_VERBOSE: + log_verbose(*(int *)imsg->data); + return; } + } - default: - log_warnx("mta_dispatch_queue: got imsg %d", - imsg.hdr.type); - fatalx("mta_dispatch_queue: unexpected imsg"); - } - imsg_free(&imsg); + fatalx("mta_imsg: unexpected imsg"); +} + +void +mta_sig_handler(int sig, short event, void *p) +{ + switch (sig) { + case SIGINT: + case SIGTERM: + mta_shutdown(); + break; + default: + fatalx("mta_sig_handler: unexpected signal"); } - imsg_event_add(iev); } void @@ -461,10 +267,10 @@ mta(struct smtpd *env) struct event ev_sigterm; struct peer peers[] = { - { PROC_PARENT, mta_dispatch_parent }, - { PROC_QUEUE, mta_dispatch_queue }, - { PROC_RUNNER, mta_dispatch_runner }, - { PROC_LKA, mta_dispatch_lka } + { PROC_PARENT, imsg_dispatch }, + { PROC_QUEUE, imsg_dispatch }, + { PROC_RUNNER, imsg_dispatch }, + { PROC_LKA, imsg_dispatch } }; switch (pid = fork()) { @@ -499,6 +305,7 @@ mta(struct smtpd *env) fatal("mta: cannot drop privileges"); #endif + imsg_callback = mta_imsg; event_init(); signal_set(&ev_sigint, SIGINT, mta_sig_handler, env); diff --git a/usr.sbin/smtpd/queue.c b/usr.sbin/smtpd/queue.c index a0f4be9b27d..9225facffb1 100644 --- a/usr.sbin/smtpd/queue.c +++ b/usr.sbin/smtpd/queue.c @@ -1,4 +1,4 @@ -/* $OpenBSD: queue.c,v 1.77 2010/01/03 14:37:37 chl Exp $ */ +/* $OpenBSD: queue.c,v 1.78 2010/04/20 15:34:56 jacekm Exp $ */ /* * Copyright (c) 2008 Gilles Chehade <gilles@openbsd.org> @@ -37,15 +37,9 @@ #include "smtpd.h" +void queue_imsg(struct smtpd *, struct imsgev *, struct imsg *); __dead void queue_shutdown(void); void queue_sig_handler(int, short, void *); -void queue_dispatch_parent(int, short, void *); -void queue_dispatch_control(int, short, void *); -void queue_dispatch_smtp(int, short, void *); -void queue_dispatch_mda(int, short, void *); -void queue_dispatch_mta(int, short, void *); -void queue_dispatch_lka(int, short, void *); -void queue_dispatch_runner(int, short, void *); void queue_setup_events(struct smtpd *); void queue_disable_events(struct smtpd *); void queue_purge(char *); @@ -57,504 +51,157 @@ int queue_remove_layout_envelope(char *, struct message *); int queue_commit_layout_message(char *, struct message *); int queue_open_layout_messagefile(char *, struct message *); -void queue_submit_envelope(struct smtpd *, struct message *); -void queue_commit_envelopes(struct smtpd *, struct message*); - -void -queue_sig_handler(int sig, short event, void *p) -{ - switch (sig) { - case SIGINT: - case SIGTERM: - queue_shutdown(); - break; - default: - fatalx("queue_sig_handler: unexpected signal"); - } -} - -void -queue_dispatch_parent(int sig, short event, void *p) -{ - struct smtpd *env = p; - struct imsgev *iev; - struct imsgbuf *ibuf; - struct imsg imsg; - ssize_t n; - - iev = env->sc_ievs[PROC_PARENT]; - ibuf = &iev->ibuf; - - if (event & EV_READ) { - if ((n = imsg_read(ibuf)) == -1) - fatal("imsg_read_error"); - if (n == 0) { - /* this pipe is dead, so remove the event handler */ - event_del(&iev->ev); - event_loopexit(NULL); - return; - } - } - - if (event & EV_WRITE) { - if (msgbuf_write(&ibuf->w) == -1) - fatal("msgbuf_write"); - } - - for (;;) { - if ((n = imsg_get(ibuf, &imsg)) == -1) - fatal("queue_dispatch_parent: imsg_get error"); - if (n == 0) - break; - - switch (imsg.hdr.type) { - case IMSG_CTL_VERBOSE: { - int verbose; - - IMSG_SIZE_CHECK(&verbose); - - memcpy(&verbose, imsg.data, sizeof(verbose)); - log_verbose(verbose); - break; - } - default: - log_warnx("got imsg %d", imsg.hdr.type); - fatalx("queue_dispatch_parent: unexpected imsg"); - } - imsg_free(&imsg); - } - imsg_event_add(iev); -} - -void -queue_dispatch_control(int sig, short event, void *p) -{ - struct smtpd *env = p; - struct imsgev *iev; - struct imsgbuf *ibuf; - struct imsg imsg; - ssize_t n; - - iev = env->sc_ievs[PROC_CONTROL]; - ibuf = &iev->ibuf; - - if (event & EV_READ) { - if ((n = imsg_read(ibuf)) == -1) - fatal("imsg_read_error"); - if (n == 0) { - /* this pipe is dead, so remove the event handler */ - event_del(&iev->ev); - event_loopexit(NULL); - return; - } - } - - if (event & EV_WRITE) { - if (msgbuf_write(&ibuf->w) == -1) - fatal("msgbuf_write"); - } - - for (;;) { - if ((n = imsg_get(ibuf, &imsg)) == -1) - fatal("queue_dispatch_control: imsg_get error"); - if (n == 0) - break; - - switch (imsg.hdr.type) { - default: - log_warnx("queue_dispatch_control: got imsg %d", - imsg.hdr.type); - fatalx("queue_dispatch_control: unexpected imsg"); - } - imsg_free(&imsg); - } - imsg_event_add(iev); -} - void -queue_dispatch_smtp(int sig, short event, void *p) +queue_imsg(struct smtpd *env, struct imsgev *iev, struct imsg *imsg) { - struct smtpd *env = p; - struct imsgev *iev; - struct imsgbuf *ibuf; - struct imsg imsg; - ssize_t n; - - iev = env->sc_ievs[PROC_SMTP]; - ibuf = &iev->ibuf; - - if (event & EV_READ) { - if ((n = imsg_read(ibuf)) == -1) - fatal("imsg_read_error"); - if (n == 0) { - /* this pipe is dead, so remove the event handler */ - event_del(&iev->ev); - event_loopexit(NULL); - return; - } - } - - if (event & EV_WRITE) { - if (msgbuf_write(&ibuf->w) == -1) - fatal("msgbuf_write"); - } + struct submit_status ss; + struct message *m; + struct batch *b; + int fd, ret, verbose; - for (;;) { - if ((n = imsg_get(ibuf, &imsg)) == -1) - fatal("queue_dispatch_smtp: imsg_get error"); - if (n == 0) - break; + if (iev->proc == PROC_SMTP) { + m = imsg->data; - switch (imsg.hdr.type) { - case IMSG_QUEUE_CREATE_MESSAGE: { - struct message *messagep = imsg.data; - struct submit_status ss; - int (*f)(char *); - - log_debug("queue_dispatch_smtp: creating message file"); - - IMSG_SIZE_CHECK(messagep); - - ss.id = messagep->session_id; + switch (imsg->hdr.type) { + case IMSG_QUEUE_CREATE_MESSAGE: + ss.id = m->session_id; ss.code = 250; - bzero(ss.u.msgid, MAX_ID_SIZE); - - if (messagep->flags & F_MESSAGE_ENQUEUED) - f = enqueue_create_layout; + bzero(ss.u.msgid, sizeof ss.u.msgid); + if (m->flags & F_MESSAGE_ENQUEUED) + ret = enqueue_create_layout(ss.u.msgid); else - f = queue_create_incoming_layout; - - if (! f(ss.u.msgid)) + ret = queue_create_incoming_layout(ss.u.msgid); + if (ret == 0) ss.code = 421; - imsg_compose_event(iev, IMSG_QUEUE_CREATE_MESSAGE, 0, 0, -1, - &ss, sizeof(ss)); - break; - } - case IMSG_QUEUE_REMOVE_MESSAGE: { - struct message *messagep = imsg.data; - void (*f)(char *); - - IMSG_SIZE_CHECK(messagep); + &ss, sizeof ss); + return; - if (messagep->flags & F_MESSAGE_ENQUEUED) - f = enqueue_delete_message; + case IMSG_QUEUE_REMOVE_MESSAGE: + if (m->flags & F_MESSAGE_ENQUEUED) + enqueue_delete_message(m->message_id); else - f = queue_delete_incoming_message; - - f(messagep->message_id); - - break; - } - case IMSG_QUEUE_COMMIT_MESSAGE: { - struct message *messagep = imsg.data; - struct submit_status ss; - size_t *counter; - int (*f)(struct message *); - - IMSG_SIZE_CHECK(messagep); - - ss.id = messagep->session_id; + queue_delete_incoming_message(m->message_id); + return; - if (messagep->flags & F_MESSAGE_ENQUEUED) { - f = enqueue_commit_message; - counter = &env->stats->queue.inserts_local; + case IMSG_QUEUE_COMMIT_MESSAGE: + ss.id = m->session_id; + if (m->flags & F_MESSAGE_ENQUEUED) { + if (enqueue_commit_message(m)) + env->stats->queue.inserts_local++; + else + ss.code = 421; } else { - f = queue_commit_incoming_message; - counter = &env->stats->queue.inserts_remote; + if (queue_commit_incoming_message(m)) + env->stats->queue.inserts_remote++; + else + ss.code = 421; } - - if (f(messagep)) - (*counter)++; - else - ss.code = 421; - imsg_compose_event(iev, IMSG_QUEUE_COMMIT_MESSAGE, 0, 0, -1, - &ss, sizeof(ss)); - - break; - } - case IMSG_QUEUE_MESSAGE_FILE: { - struct message *messagep = imsg.data; - struct submit_status ss; - int fd; - int (*f)(struct message *); - - IMSG_SIZE_CHECK(messagep); - - ss.id = messagep->session_id; + &ss, sizeof ss); + return; - if (messagep->flags & F_MESSAGE_ENQUEUED) - f = enqueue_open_messagefile; + case IMSG_QUEUE_MESSAGE_FILE: + ss.id = m->session_id; + if (m->flags & F_MESSAGE_ENQUEUED) + fd = enqueue_open_messagefile(m); else - f = queue_open_incoming_message_file; - - fd = f(messagep); + fd = queue_open_incoming_message_file(m); if (fd == -1) ss.code = 421; - imsg_compose_event(iev, IMSG_QUEUE_MESSAGE_FILE, 0, 0, fd, - &ss, sizeof(ss)); - break; - } - default: - log_warnx("queue_dispatch_smtp: got imsg %d", - imsg.hdr.type); - fatalx("queue_dispatch_smtp: unexpected imsg"); - } - imsg_free(&imsg); - } - imsg_event_add(iev); -} - -void -queue_dispatch_mda(int sig, short event, void *p) -{ - struct smtpd *env = p; - struct imsgev *iev; - struct imsgbuf *ibuf; - struct imsg imsg; - ssize_t n; - - iev = env->sc_ievs[PROC_MDA]; - ibuf = &iev->ibuf; - - if (event & EV_READ) { - if ((n = imsg_read(ibuf)) == -1) - fatal("imsg_read_error"); - if (n == 0) { - /* this pipe is dead, so remove the event handler */ - event_del(&iev->ev); - event_loopexit(NULL); - return; - } - } - - if (event & EV_WRITE) { - if (msgbuf_write(&ibuf->w) == -1) - fatal("msgbuf_write"); - } - - for (;;) { - if ((n = imsg_get(ibuf, &imsg)) == -1) - fatal("queue_dispatch_mda: imsg_get error"); - if (n == 0) - break; - - switch (imsg.hdr.type) { - - case IMSG_QUEUE_MESSAGE_UPDATE: { - imsg_compose_event(env->sc_ievs[PROC_RUNNER], IMSG_RUNNER_UPDATE_ENVELOPE, - 0, 0, -1, imsg.data, sizeof(struct message)); - break; - } - - default: - log_warnx("got imsg %d", imsg.hdr.type); - fatalx("queue_dispatch_mda: unexpected imsg"); - } - imsg_free(&imsg); - } - imsg_event_add(iev); -} - -void -queue_dispatch_mta(int sig, short event, void *p) -{ - struct smtpd *env = p; - struct imsgev *iev; - struct imsgbuf *ibuf; - struct imsg imsg; - ssize_t n; - - iev = env->sc_ievs[PROC_MTA]; - ibuf = &iev->ibuf; - - if (event & EV_READ) { - if ((n = imsg_read(ibuf)) == -1) - fatal("imsg_read_error"); - if (n == 0) { - /* this pipe is dead, so remove the event handler */ - event_del(&iev->ev); - event_loopexit(NULL); - return; - } - } - - if (event & EV_WRITE) { - if (msgbuf_write(&ibuf->w) == -1) - fatal("msgbuf_write"); - } - - for (;;) { - if ((n = imsg_get(ibuf, &imsg)) == -1) - fatal("queue_dispatch_mta: imsg_get error"); - if (n == 0) - break; - - switch (imsg.hdr.type) { - - case IMSG_QUEUE_MESSAGE_FD: { - struct batch *batchp = imsg.data; - int fd; - - IMSG_SIZE_CHECK(batchp); - - fd = queue_open_message_file(batchp->message_id); - imsg_compose_event(iev, IMSG_QUEUE_MESSAGE_FD, 0, 0, fd, batchp, - sizeof(*batchp)); - break; - } - - case IMSG_QUEUE_MESSAGE_UPDATE: { - imsg_compose_event(env->sc_ievs[PROC_RUNNER], IMSG_RUNNER_UPDATE_ENVELOPE, - 0, 0, -1, imsg.data, sizeof(struct message)); - break; - } - - default: - log_warnx("got imsg %d", imsg.hdr.type); - fatalx("queue_dispatch_mda: unexpected imsg"); - } - imsg_free(&imsg); - } - imsg_event_add(iev); -} - -void -queue_dispatch_lka(int sig, short event, void *p) -{ - struct smtpd *env = p; - struct imsgev *iev; - struct imsgbuf *ibuf; - struct imsg imsg; - ssize_t n; - - iev = env->sc_ievs[PROC_LKA]; - ibuf = &iev->ibuf; - - if (event & EV_READ) { - if ((n = imsg_read(ibuf)) == -1) - fatal("imsg_read_error"); - if (n == 0) { - /* this pipe is dead, so remove the event handler */ - event_del(&iev->ev); - event_loopexit(NULL); + &ss, sizeof ss); return; } } - if (event & EV_WRITE) { - if (msgbuf_write(&ibuf->w) == -1) - fatal("msgbuf_write"); - } - - for (;;) { - if ((n = imsg_get(ibuf, &imsg)) == -1) - fatal("queue_dispatch_lka: imsg_get error"); - if (n == 0) - break; + if (iev->proc == PROC_LKA) { + m = imsg->data; - switch (imsg.hdr.type) { + switch (imsg->hdr.type) { + case IMSG_QUEUE_SUBMIT_ENVELOPE: + m->id = generate_uid(); + ss.id = m->session_id; - case IMSG_QUEUE_SUBMIT_ENVELOPE: { - struct message *messagep = imsg.data; - struct submit_status ss; - int (*f)(struct message *); - - IMSG_SIZE_CHECK(messagep); - - messagep->id = generate_uid(); - ss.id = messagep->session_id; - - if (IS_MAILBOX(messagep->recipient) || - IS_EXT(messagep->recipient)) - messagep->type = T_MDA_MESSAGE; + if (IS_MAILBOX(m->recipient) || IS_EXT(m->recipient)) + m->type = T_MDA_MESSAGE; else - messagep->type = T_MTA_MESSAGE; + m->type = T_MTA_MESSAGE; /* Write to disk */ - if (messagep->flags & F_MESSAGE_ENQUEUED) - f = enqueue_record_envelope; + if (m->flags & F_MESSAGE_ENQUEUED) + ret = enqueue_record_envelope(m); else - f = queue_record_incoming_envelope; + ret = queue_record_incoming_envelope(m); - if (! f(messagep)) { + if (ret == 0) { ss.code = 421; imsg_compose_event(env->sc_ievs[PROC_SMTP], IMSG_QUEUE_TEMPFAIL, 0, 0, -1, &ss, - sizeof(ss)); + sizeof ss); } + return; - break; - } - - case IMSG_QUEUE_COMMIT_ENVELOPES: { - struct message *messagep = imsg.data; - struct submit_status ss; - - IMSG_SIZE_CHECK(messagep); - - ss.id = messagep->session_id; + case IMSG_QUEUE_COMMIT_ENVELOPES: + ss.id = m->session_id; ss.code = 250; - - imsg_compose_event(env->sc_ievs[PROC_SMTP], IMSG_QUEUE_COMMIT_ENVELOPES, - 0, 0, -1, &ss, sizeof(ss)); - - break; + imsg_compose_event(env->sc_ievs[PROC_SMTP], + IMSG_QUEUE_COMMIT_ENVELOPES, 0, 0, -1, &ss, + sizeof ss); + return; } + } + + if (iev->proc == PROC_MTA) { + switch (imsg->hdr.type) { + case IMSG_QUEUE_MESSAGE_FD: + b = imsg->data; + fd = queue_open_message_file(b->message_id); + imsg_compose_event(iev, IMSG_QUEUE_MESSAGE_FD, 0, 0, + fd, b, sizeof *b); + return; - default: - log_warnx("got imsg %d", imsg.hdr.type); - fatalx("queue_dispatch_lka: unexpected imsg"); + case IMSG_QUEUE_MESSAGE_UPDATE: + imsg_compose_event(env->sc_ievs[PROC_RUNNER], + IMSG_RUNNER_UPDATE_ENVELOPE, 0, 0, -1, imsg->data, + sizeof(struct message)); + return; } - imsg_free(&imsg); } - imsg_event_add(iev); -} -void -queue_dispatch_runner(int sig, short event, void *p) -{ - struct smtpd *env = p; - struct imsgev *iev; - struct imsgbuf *ibuf; - struct imsg imsg; - ssize_t n; - - iev = env->sc_ievs[PROC_RUNNER]; - ibuf = &iev->ibuf; - - if (event & EV_READ) { - if ((n = imsg_read(ibuf)) == -1) - fatal("imsg_read_error"); - if (n == 0) { - /* this pipe is dead, so remove the event handler */ - event_del(&iev->ev); - event_loopexit(NULL); + if (iev->proc == PROC_MDA) { + switch (imsg->hdr.type) { + case IMSG_QUEUE_MESSAGE_UPDATE: + imsg_compose_event(env->sc_ievs[PROC_RUNNER], + IMSG_RUNNER_UPDATE_ENVELOPE, 0, 0, -1, imsg->data, + sizeof(struct message)); return; } } - if (event & EV_WRITE) { - if (msgbuf_write(&ibuf->w) == -1) - fatal("msgbuf_write"); + if (iev->proc == PROC_PARENT) { + switch (imsg->hdr.type) { + case IMSG_CTL_VERBOSE: + memcpy(&verbose, imsg->data, sizeof verbose); + log_verbose(verbose); + return; + } } - for (;;) { - if ((n = imsg_get(ibuf, &imsg)) == -1) - fatal("queue_dispatch_runner: imsg_get error"); - if (n == 0) - break; + fatalx("queue_imsg: unexpected imsg"); +} - switch (imsg.hdr.type) { - default: - log_warnx("got imsg %d", imsg.hdr.type); - fatalx("queue_dispatch_runner: unexpected imsg"); - } - imsg_free(&imsg); +void +queue_sig_handler(int sig, short event, void *p) +{ + switch (sig) { + case SIGINT: + case SIGTERM: + queue_shutdown(); + break; + default: + fatalx("queue_sig_handler: unexpected signal"); } - imsg_event_add(iev); } void @@ -584,13 +231,13 @@ queue(struct smtpd *env) struct event ev_sigterm; struct peer peers[] = { - { PROC_PARENT, queue_dispatch_parent }, - { PROC_CONTROL, queue_dispatch_control }, - { PROC_SMTP, queue_dispatch_smtp }, - { PROC_MDA, queue_dispatch_mda }, - { PROC_MTA, queue_dispatch_mta }, - { PROC_LKA, queue_dispatch_lka }, - { PROC_RUNNER, queue_dispatch_runner } + { PROC_PARENT, imsg_dispatch }, + { PROC_CONTROL, imsg_dispatch }, + { PROC_SMTP, imsg_dispatch }, + { PROC_MDA, imsg_dispatch }, + { PROC_MTA, imsg_dispatch }, + { PROC_LKA, imsg_dispatch }, + { PROC_RUNNER, imsg_dispatch } }; switch (pid = fork()) { @@ -625,6 +272,7 @@ queue(struct smtpd *env) fatal("queue: cannot drop privileges"); #endif + imsg_callback = queue_imsg; event_init(); signal_set(&ev_sigint, SIGINT, queue_sig_handler, env); diff --git a/usr.sbin/smtpd/runner.c b/usr.sbin/smtpd/runner.c index acbf095a648..f35068a0661 100644 --- a/usr.sbin/smtpd/runner.c +++ b/usr.sbin/smtpd/runner.c @@ -1,4 +1,4 @@ -/* $OpenBSD: runner.c,v 1.79 2010/04/19 08:14:07 jacekm Exp $ */ +/* $OpenBSD: runner.c,v 1.80 2010/04/20 15:34:56 jacekm Exp $ */ /* * Copyright (c) 2008 Gilles Chehade <gilles@openbsd.org> @@ -47,15 +47,10 @@ #include "smtpd.h" +void runner_imsg(struct smtpd *, struct imsgev *, struct imsg *); + __dead void runner_shutdown(void); void runner_sig_handler(int, short, void *); -void runner_dispatch_parent(int, short, void *); -void runner_dispatch_control(int, short, void *); -void runner_dispatch_queue(int, short, void *); -void runner_dispatch_mda(int, short, void *); -void runner_dispatch_mta(int, short, void *); -void runner_dispatch_lka(int, short, void *); -void runner_dispatch_smtp(int, short, void *); void runner_setup_events(struct smtpd *); void runner_disable_events(struct smtpd *); @@ -85,412 +80,117 @@ int runner_force_envelope_remove(char *); int runner_force_message_remove(char *); void -runner_sig_handler(int sig, short event, void *p) +runner_imsg(struct smtpd *env, struct imsgev *iev, struct imsg *imsg) { - switch (sig) { - case SIGINT: - case SIGTERM: - runner_shutdown(); - break; - default: - fatalx("runner_sig_handler: unexpected signal"); - } -} + struct message *m; + struct remove *rem; + struct sched *sched; -void -runner_dispatch_parent(int sig, short event, void *p) -{ - struct smtpd *env = p; - struct imsgev *iev; - struct imsgbuf *ibuf; - struct imsg imsg; - ssize_t n; - - iev = env->sc_ievs[PROC_PARENT]; - ibuf = &iev->ibuf; - - if (event & EV_READ) { - if ((n = imsg_read(ibuf)) == -1) - fatal("imsg_read_error"); - if (n == 0) { - /* this pipe is dead, so remove the event handler */ - event_del(&iev->ev); - event_loopexit(NULL); + if (iev->proc == PROC_QUEUE) { + switch (imsg->hdr.type) { + case IMSG_RUNNER_UPDATE_ENVELOPE: + env->stats->runner.active--; + queue_message_update(imsg->data); return; } } - if (event & EV_WRITE) { - if (msgbuf_write(&ibuf->w) == -1) - fatal("msgbuf_write"); - } - - for (;;) { - if ((n = imsg_get(ibuf, &imsg)) == -1) - fatal("runner_dispatch_parent: imsg_get error"); - if (n == 0) - break; - - switch (imsg.hdr.type) { - case IMSG_PARENT_ENQUEUE_OFFLINE: - runner_process_offline(env); - break; - case IMSG_CTL_VERBOSE: { - int verbose; - - IMSG_SIZE_CHECK(&verbose); - - memcpy(&verbose, imsg.data, sizeof(verbose)); - log_verbose(verbose); - break; - } - default: - log_warnx("runner_dispatch_parent: got imsg %d", - imsg.hdr.type); - fatalx("runner_dispatch_parent: unexpected imsg"); + if (iev->proc == PROC_MDA) { + switch (imsg->hdr.type) { + case IMSG_MDA_SESS_NEW: + env->stats->mda.sessions_active--; + return; } - imsg_free(&imsg); } - imsg_event_add(iev); -} -void -runner_dispatch_control(int sig, short event, void *p) -{ - struct smtpd *env = p; - struct imsgev *iev; - struct imsgbuf *ibuf; - struct imsg imsg; - ssize_t n; - - iev = env->sc_ievs[PROC_CONTROL]; - ibuf = &iev->ibuf; - - if (event & EV_READ) { - if ((n = imsg_read(ibuf)) == -1) - fatal("imsg_read_error"); - if (n == 0) { - /* this pipe is dead, so remove the event handler */ - event_del(&iev->ev); - event_loopexit(NULL); + if (iev->proc == PROC_MTA) { + switch (imsg->hdr.type) { + case IMSG_BATCH_DONE: + env->stats->mta.sessions_active--; return; } } - if (event & EV_WRITE) { - if (msgbuf_write(&ibuf->w) == -1) - fatal("msgbuf_write"); + if (iev->proc == PROC_SMTP) { + switch (imsg->hdr.type) { + case IMSG_SMTP_ENQUEUE: + m = imsg->data; + if (imsg->fd < 0 || !bounce_session(env, imsg->fd, m)) { + m->status = S_MESSAGE_TEMPFAILURE; + queue_message_update(m); + } + return; + } } - for (;;) { - if ((n = imsg_get(ibuf, &imsg)) == -1) - fatal("runner_dispatch_control: imsg_get error"); - if (n == 0) - break; - - switch (imsg.hdr.type) { + if (iev->proc == PROC_CONTROL) { + switch (imsg->hdr.type) { case IMSG_MDA_PAUSE: env->sc_opts |= SMTPD_MDA_PAUSED; - break; + return; + case IMSG_MTA_PAUSE: env->sc_opts |= SMTPD_MTA_PAUSED; - break; + return; + case IMSG_MDA_RESUME: env->sc_opts &= ~SMTPD_MDA_PAUSED; - break; + return; + case IMSG_MTA_RESUME: env->sc_opts &= ~SMTPD_MTA_PAUSED; - break; - case IMSG_RUNNER_SCHEDULE: { - struct sched *s = imsg.data; - - IMSG_SIZE_CHECK(s); - - s->ret = 0; - if (valid_message_uid(s->mid)) - s->ret = runner_force_envelope_schedule(s->mid); - else if (valid_message_id(s->mid)) - s->ret = runner_force_message_schedule(s->mid); - - imsg_compose_event(iev, IMSG_RUNNER_SCHEDULE, 0, 0, -1, s, sizeof(*s)); - break; - } - case IMSG_RUNNER_REMOVE: { - struct remove *s = imsg.data; - - IMSG_SIZE_CHECK(s); - - s->ret = 0; - if (valid_message_uid(s->mid)) - s->ret = runner_force_envelope_remove(s->mid); - else if (valid_message_id(s->mid)) - s->ret = runner_force_message_remove(s->mid); - - imsg_compose_event(iev, IMSG_RUNNER_REMOVE, 0, 0, -1, s, sizeof(*s)); - break; - } - default: - log_warnx("runner_dispatch_control: got imsg %d", - imsg.hdr.type); - fatalx("runner_dispatch_control: unexpected imsg"); - } - imsg_free(&imsg); - } - imsg_event_add(iev); -} - -void -runner_dispatch_queue(int sig, short event, void *p) -{ - struct smtpd *env = p; - struct imsgev *iev; - struct imsgbuf *ibuf; - struct imsg imsg; - ssize_t n; - - iev = env->sc_ievs[PROC_QUEUE]; - ibuf = &iev->ibuf; - - if (event & EV_READ) { - if ((n = imsg_read(ibuf)) == -1) - fatal("imsg_read_error"); - if (n == 0) { - /* this pipe is dead, so remove the event handler */ - event_del(&iev->ev); - event_loopexit(NULL); return; - } - } - - if (event & EV_WRITE) { - if (msgbuf_write(&ibuf->w) == -1) - fatal("msgbuf_write"); - } - for (;;) { - if ((n = imsg_get(ibuf, &imsg)) == -1) - fatal("runner_dispatch_queue: imsg_get error"); - if (n == 0) - break; - - switch (imsg.hdr.type) { - case IMSG_RUNNER_UPDATE_ENVELOPE: { - struct message *m = imsg.data; - - IMSG_SIZE_CHECK(m); - - env->stats->runner.active--; - queue_message_update(m); - break; - } - default: - log_warnx("runner_dispatch_queue: got imsg %d", - imsg.hdr.type); - fatalx("runner_dispatch_queue: unexpected imsg"); - } - imsg_free(&imsg); - } - imsg_event_add(iev); -} - -void -runner_dispatch_mda(int sig, short event, void *p) -{ - struct smtpd *env = p; - struct imsgev *iev; - struct imsgbuf *ibuf; - struct imsg imsg; - ssize_t n; - - iev = env->sc_ievs[PROC_MDA]; - ibuf = &iev->ibuf; - - if (event & EV_READ) { - if ((n = imsg_read(ibuf)) == -1) - fatal("imsg_read_error"); - if (n == 0) { - /* this pipe is dead, so remove the event handler */ - event_del(&iev->ev); - event_loopexit(NULL); + case IMSG_RUNNER_SCHEDULE: + sched = imsg->data; + sched->ret = 0; + if (valid_message_uid(sched->mid)) + sched->ret = runner_force_envelope_schedule(sched->mid); + else if (valid_message_id(sched->mid)) + sched->ret = runner_force_message_schedule(sched->mid); + imsg_compose_event(iev, IMSG_RUNNER_SCHEDULE, 0, 0, -1, + sched, sizeof *sched); return; - } - } - - if (event & EV_WRITE) { - if (msgbuf_write(&ibuf->w) == -1) - fatal("msgbuf_write"); - } - - for (;;) { - if ((n = imsg_get(ibuf, &imsg)) == -1) - fatal("runner_dispatch_mda: imsg_get error"); - if (n == 0) - break; - - switch (imsg.hdr.type) { - case IMSG_MDA_SESS_NEW: - env->stats->mda.sessions_active--; - break; - default: - log_warnx("runner_dispatch_mda: got imsg %d", - imsg.hdr.type); - fatalx("runner_dispatch_mda: unexpected imsg"); - } - imsg_free(&imsg); - } - imsg_event_add(iev); -} - -void -runner_dispatch_mta(int sig, short event, void *p) -{ - struct smtpd *env = p; - struct imsgev *iev; - struct imsgbuf *ibuf; - struct imsg imsg; - ssize_t n; - - iev = env->sc_ievs[PROC_MTA]; - ibuf = &iev->ibuf; - - if (event & EV_READ) { - if ((n = imsg_read(ibuf)) == -1) - fatal("imsg_read_error"); - if (n == 0) { - /* this pipe is dead, so remove the event handler */ - event_del(&iev->ev); - event_loopexit(NULL); + case IMSG_RUNNER_REMOVE: + rem = imsg->data; + rem->ret = 0; + if (valid_message_uid(rem->mid)) + rem->ret = runner_force_envelope_remove(rem->mid); + else if (valid_message_id(rem->mid)) + rem->ret = runner_force_message_remove(rem->mid); + imsg_compose_event(iev, IMSG_RUNNER_REMOVE, 0, 0, -1, + rem, sizeof *rem); return; } } - if (event & EV_WRITE) { - if (msgbuf_write(&ibuf->w) == -1) - fatal("msgbuf_write"); - } - - for (;;) { - if ((n = imsg_get(ibuf, &imsg)) == -1) - fatal("runner_dispatch_mta: imsg_get error"); - if (n == 0) - break; - - switch (imsg.hdr.type) { - case IMSG_BATCH_DONE: - env->stats->mta.sessions_active--; - break; - - default: - log_warnx("runner_dispatch_mta: got imsg %d", - imsg.hdr.type); - fatalx("runner_dispatch_mta: unexpected imsg"); - } - imsg_free(&imsg); - } - imsg_event_add(iev); -} + if (iev->proc == PROC_PARENT) { + switch (imsg->hdr.type) { + case IMSG_PARENT_ENQUEUE_OFFLINE: + runner_process_offline(env); + return; -void -runner_dispatch_lka(int sig, short event, void *p) -{ - struct smtpd *env = p; - struct imsgev *iev; - struct imsgbuf *ibuf; - struct imsg imsg; - ssize_t n; - - iev = env->sc_ievs[PROC_LKA]; - ibuf = &iev->ibuf; - - if (event & EV_READ) { - if ((n = imsg_read(ibuf)) == -1) - fatal("imsg_read_error"); - if (n == 0) { - /* this pipe is dead, so remove the event handler */ - event_del(&iev->ev); - event_loopexit(NULL); + case IMSG_CTL_VERBOSE: + log_verbose(*(int *)imsg->data); return; } } - if (event & EV_WRITE) { - if (msgbuf_write(&ibuf->w) == -1) - fatal("msgbuf_write"); - } - - for (;;) { - if ((n = imsg_get(ibuf, &imsg)) == -1) - fatal("runner_dispatch_lka: imsg_get error"); - if (n == 0) - break; - - switch (imsg.hdr.type) { - default: - log_warnx("runner_dispatch_lka: got imsg %d", - imsg.hdr.type); - fatalx("runner_dispatch_lka: unexpected imsg"); - } - imsg_free(&imsg); - } - imsg_event_add(iev); + fatalx("runner_imsg: unexpected imsg"); } void -runner_dispatch_smtp(int sig, short event, void *p) +runner_sig_handler(int sig, short event, void *p) { - struct smtpd *env = p; - struct imsgev *iev; - struct imsgbuf *ibuf; - struct imsg imsg; - ssize_t n; - - iev = env->sc_ievs[PROC_SMTP]; - ibuf = &iev->ibuf; - - if (event & EV_READ) { - if ((n = imsg_read(ibuf)) == -1) - fatal("imsg_read_error"); - if (n == 0) { - /* this pipe is dead, so remove the event handler */ - event_del(&iev->ev); - event_loopexit(NULL); - return; - } - } - - if (event & EV_WRITE) { - if (msgbuf_write(&ibuf->w) == -1) - fatal("msgbuf_write"); - } - - for (;;) { - if ((n = imsg_get(ibuf, &imsg)) == -1) - fatal("runner_dispatch_smtp: imsg_get error"); - if (n == 0) - break; - - switch (imsg.hdr.type) { - case IMSG_SMTP_ENQUEUE: { - struct message *m = imsg.data; - - IMSG_SIZE_CHECK(m); - - if (imsg.fd < 0 || ! bounce_session(env, imsg.fd, m)) { - m->status = S_MESSAGE_TEMPFAILURE; - queue_message_update(m); - } - break; - } - - default: - log_warnx("runner_dispatch_smtp: got imsg %d", - imsg.hdr.type); - fatalx("runner_dispatch_smtp: unexpected imsg"); - } - imsg_free(&imsg); + switch (sig) { + case SIGINT: + case SIGTERM: + runner_shutdown(); + break; + default: + fatalx("runner_sig_handler: unexpected signal"); } - imsg_event_add(iev); } void @@ -527,13 +227,13 @@ runner(struct smtpd *env) struct event ev_sigterm; struct peer peers[] = { - { PROC_PARENT, runner_dispatch_parent }, - { PROC_CONTROL, runner_dispatch_control }, - { PROC_MDA, runner_dispatch_mda }, - { PROC_MTA, runner_dispatch_mta }, - { PROC_QUEUE, runner_dispatch_queue }, - { PROC_LKA, runner_dispatch_lka }, - { PROC_SMTP, runner_dispatch_smtp } + { PROC_PARENT, imsg_dispatch }, + { PROC_CONTROL, imsg_dispatch }, + { PROC_MDA, imsg_dispatch }, + { PROC_MTA, imsg_dispatch }, + { PROC_QUEUE, imsg_dispatch }, + { PROC_LKA, imsg_dispatch }, + { PROC_SMTP, imsg_dispatch } }; switch (pid = fork()) { @@ -570,6 +270,7 @@ runner(struct smtpd *env) SPLAY_INIT(&env->batch_queue); + imsg_callback = runner_imsg; event_init(); signal_set(&ev_sigint, SIGINT, runner_sig_handler, env); diff --git a/usr.sbin/smtpd/smtp.c b/usr.sbin/smtpd/smtp.c index 9d779887f53..cd137f710a0 100644 --- a/usr.sbin/smtpd/smtp.c +++ b/usr.sbin/smtpd/smtp.c @@ -1,4 +1,4 @@ -/* $OpenBSD: smtp.c,v 1.67 2010/01/03 14:37:37 chl Exp $ */ +/* $OpenBSD: smtp.c,v 1.68 2010/04/20 15:34:56 jacekm Exp $ */ /* * Copyright (c) 2008 Gilles Chehade <gilles@openbsd.org> @@ -38,14 +38,9 @@ #include "smtpd.h" +void smtp_imsg(struct smtpd *, struct imsgev *, struct imsg *); __dead void smtp_shutdown(void); void smtp_sig_handler(int, short, void *); -void smtp_dispatch_parent(int, short, void *); -void smtp_dispatch_mfa(int, short, void *); -void smtp_dispatch_lka(int, short, void *); -void smtp_dispatch_queue(int, short, void *); -void smtp_dispatch_control(int, short, void *); -void smtp_dispatch_runner(int, short, void *); void smtp_setup_events(struct smtpd *); void smtp_disable_events(struct smtpd *); void smtp_pause(struct smtpd *); @@ -55,58 +50,114 @@ struct session *smtp_new(struct listener *); struct session *session_lookup(struct smtpd *, u_int64_t); void -smtp_sig_handler(int sig, short event, void *p) +smtp_imsg(struct smtpd *env, struct imsgev *iev, struct imsg *imsg) { - switch (sig) { - case SIGINT: - case SIGTERM: - smtp_shutdown(); - break; - default: - fatalx("smtp_sig_handler: unexpected signal"); + struct session skey; + struct submit_status *ss; + struct listener *l; + struct session *s; + struct auth *auth; + struct ssl *ssl; + struct dns *dns; + + if (iev->proc == PROC_LKA) { + switch (imsg->hdr.type) { + case IMSG_DNS_PTR: + dns = imsg->data; + s = session_lookup(env, dns->id); + if (s == NULL) + fatalx("smtp: impossible quit"); + strlcpy(s->s_hostname, + dns->error ? "<unknown>" : dns->host, + sizeof s->s_hostname); + strlcpy(s->s_msg.session_hostname, s->s_hostname, + sizeof s->s_msg.session_hostname); + session_init(s->s_l, s); + return; + } } -} -void -smtp_dispatch_parent(int sig, short event, void *p) -{ - struct smtpd *env = p; - struct imsgev *iev; - struct imsgbuf *ibuf; - struct imsg imsg; - ssize_t n; - - iev = env->sc_ievs[PROC_PARENT]; - ibuf = &iev->ibuf; - - - if (event & EV_READ) { - if ((n = imsg_read(ibuf)) == -1) - fatal("imsg_read_error"); - if (n == 0) { - /* this pipe is dead, so remove the event handler */ - event_del(&iev->ev); - event_loopexit(NULL); + if (iev->proc == PROC_MFA) { + switch (imsg->hdr.type) { + case IMSG_MFA_RCPT: + case IMSG_MFA_MAIL: + log_debug("smtp: got imsg_mfa_mail/rcpt"); + ss = imsg->data; + s = session_lookup(env, ss->id); + if (s == NULL) + return; + session_pickup(s, ss); return; } } - if (event & EV_WRITE) { - if (msgbuf_write(&ibuf->w) == -1) - fatal("msgbuf_write"); - } + if (iev->proc == PROC_QUEUE) { + ss = imsg->data; - for (;;) { - if ((n = imsg_get(ibuf, &imsg)) == -1) - fatal("smtp_dispatch_parent: imsg_get error"); - if (n == 0) - break; + switch (imsg->hdr.type) { + case IMSG_QUEUE_CREATE_MESSAGE: + log_debug("smtp: imsg_queue_create_message returned"); + s = session_lookup(env, ss->id); + if (s == NULL) + return; + strlcpy(s->s_msg.message_id, ss->u.msgid, + sizeof s->s_msg.message_id); + session_pickup(s, ss); + return; - switch (imsg.hdr.type) { - case IMSG_CONF_RELOAD: { - struct session *s; + case IMSG_QUEUE_MESSAGE_FILE: + log_debug("smtp: imsg_queue_message_file returned"); + s = session_lookup(env, ss->id); + if (s == NULL) { + close(imsg->fd); + return; + } + s->datafp = fdopen(imsg->fd, "w"); + if (s->datafp == NULL) { + /* queue may have experienced tempfail. */ + if (ss->code != 421) + fatalx("smtp: fdopen"); + close(imsg->fd); + } + session_pickup(s, ss); + return; - /* reloading may invalidate various pointers our + case IMSG_QUEUE_TEMPFAIL: + log_debug("smtp: got imsg_queue_tempfail"); + skey.s_id = ss->id; + s = SPLAY_FIND(sessiontree, &env->sc_sessions, &skey); + if (s == NULL) + fatalx("smtp: session is gone"); + if (s->s_flags & F_WRITEONLY) + /* session is write-only, must not destroy it. */ + s->s_msg.status |= S_MESSAGE_TEMPFAILURE; + else + fatalx("smtp: corrupt session"); + return; + + case IMSG_QUEUE_COMMIT_ENVELOPES: + log_debug("smtp: got imsg_queue_commit_envelopes"); + s = session_lookup(env, ss->id); + if (s == NULL) + return; + session_pickup(s, ss); + return; + + case IMSG_QUEUE_COMMIT_MESSAGE: + log_debug("smtp: got imsg_queue_commit_message"); + s = session_lookup(env, ss->id); + if (s == NULL) + return; + session_pickup(s, ss); + return; + } + } + + if (iev->proc == PROC_PARENT) { + switch (imsg->hdr.type) { + case IMSG_CONF_RELOAD: + /* + * Reloading may invalidate various pointers our * sessions rely upon, we better tell clients we * want them to retry. */ @@ -118,474 +169,129 @@ smtp_dispatch_parent(int sig, short event, void *p) smtp_disable_events(env); imsg_compose_event(iev, IMSG_PARENT_SEND_CONFIG, 0, 0, -1, NULL, 0); - break; - } + return; + case IMSG_CONF_START: if (env->sc_flags & SMTPD_CONFIGURING) - break; + return; env->sc_flags |= SMTPD_CONFIGURING; - - if ((env->sc_listeners = calloc(1, sizeof(*env->sc_listeners))) == NULL) - fatal("smtp_dispatch_parent: calloc"); - if ((env->sc_ssl = calloc(1, sizeof(*env->sc_ssl))) == NULL) - fatal("smtp_dispatch_parent: calloc"); + env->sc_listeners = calloc(1, sizeof *env->sc_listeners); + env->sc_ssl = calloc(1, sizeof *env->sc_ssl); + if (env->sc_listeners == NULL || env->sc_ssl == NULL) + fatal(NULL); TAILQ_INIT(env->sc_listeners); - break; - case IMSG_CONF_SSL: { - struct ssl *s; - struct ssl *x_ssl; + return; + case IMSG_CONF_SSL: if (!(env->sc_flags & SMTPD_CONFIGURING)) - break; - - if ((s = calloc(1, sizeof(*s))) == NULL) + return; + ssl = calloc(1, sizeof *ssl); + if (ssl == NULL) fatal(NULL); - x_ssl = imsg.data; - (void)strlcpy(s->ssl_name, x_ssl->ssl_name, - sizeof(s->ssl_name)); - s->ssl_cert_len = x_ssl->ssl_cert_len; - if ((s->ssl_cert = - strdup((char *)imsg.data + sizeof(*s))) == NULL) + *ssl = *(struct ssl *)imsg->data; + ssl->ssl_cert = strdup((char *)imsg->data + + sizeof *ssl); + if (ssl->ssl_cert == NULL) fatal(NULL); - s->ssl_key_len = x_ssl->ssl_key_len; - if ((s->ssl_key = strdup((char *)imsg.data + - (sizeof(*s) + s->ssl_cert_len))) == NULL) + ssl->ssl_key = strdup((char *)imsg->data + sizeof *ssl + + ssl->ssl_cert_len); + if (ssl->ssl_key == NULL) fatal(NULL); + SPLAY_INSERT(ssltree, env->sc_ssl, ssl); + return; - SPLAY_INSERT(ssltree, env->sc_ssl, s); - break; - } - case IMSG_CONF_LISTENER: { - struct listener *l; - struct ssl key; - + case IMSG_CONF_LISTENER: if (!(env->sc_flags & SMTPD_CONFIGURING)) - break; - - if ((l = calloc(1, sizeof(*l))) == NULL) + return; + l = calloc(1, sizeof *l); + if (l == NULL) fatal(NULL); - memcpy(l, imsg.data, sizeof(*l)); - - if ((l->fd = imsg.fd) == -1) - fatal("cannot get fd"); - - (void)strlcpy(key.ssl_name, l->ssl_cert_name, - sizeof(key.ssl_name)); - - if (l->flags & F_SSL) - if ((l->ssl = SPLAY_FIND(ssltree, - env->sc_ssl, &key)) == NULL) - fatal("parent and smtp desynchronized"); - + *l = *(struct listener *)imsg->data; + l->fd = imsg->fd; + if (l->fd < 0) + fatalx("smtp: listener pass failed"); + if (l->flags & F_SSL) { + struct ssl key; + + strlcpy(key.ssl_name, l->ssl_cert_name, + sizeof key.ssl_name); + l->ssl = SPLAY_FIND(ssltree, env->sc_ssl, &key); + if (l->ssl == NULL) + fatalx("smtp: ssltree out of sync"); + } TAILQ_INSERT_TAIL(env->sc_listeners, l, entry); - break; - } + return; + case IMSG_CONF_END: if (!(env->sc_flags & SMTPD_CONFIGURING)) - break; + return; smtp_setup_events(env); env->sc_flags &= ~SMTPD_CONFIGURING; - break; - case IMSG_PARENT_AUTHENTICATE: { - struct auth *reply = imsg.data; - struct session *s; - - log_debug("smtp_dispatch_parent: got auth reply"); - - IMSG_SIZE_CHECK(reply); - - if ((s = session_lookup(env, reply->id)) == NULL) - break; + return; - if (reply->success) { + case IMSG_PARENT_AUTHENTICATE: + auth = imsg->data; + s = session_lookup(env, auth->id); + if (s == NULL) + return; + if (auth->success) { s->s_flags |= F_AUTHENTICATED; s->s_msg.flags |= F_MESSAGE_AUTHENTICATED; } else { s->s_flags &= ~F_AUTHENTICATED; s->s_msg.flags &= ~F_MESSAGE_AUTHENTICATED; } - session_pickup(s, NULL); - break; - } - case IMSG_CTL_VERBOSE: { - int verbose; - - IMSG_SIZE_CHECK(&verbose); - - memcpy(&verbose, imsg.data, sizeof(verbose)); - log_verbose(verbose); - break; - } - default: - log_warnx("smtp_dispatch_parent: got imsg %d", - imsg.hdr.type); - fatalx("smtp_dispatch_parent: unexpected imsg"); - } - imsg_free(&imsg); - } - imsg_event_add(iev); -} - -void -smtp_dispatch_mfa(int sig, short event, void *p) -{ - struct smtpd *env = p; - struct imsgev *iev; - struct imsgbuf *ibuf; - struct imsg imsg; - ssize_t n; - - iev = env->sc_ievs[PROC_MFA]; - ibuf = &iev->ibuf; - - if (event & EV_READ) { - if ((n = imsg_read(ibuf)) == -1) - fatal("imsg_read_error"); - if (n == 0) { - /* this pipe is dead, so remove the event handler */ - event_del(&iev->ev); - event_loopexit(NULL); return; - } - } - - if (event & EV_WRITE) { - if (msgbuf_write(&ibuf->w) == -1) - fatal("msgbuf_write"); - } - - for (;;) { - if ((n = imsg_get(ibuf, &imsg)) == -1) - fatal("smtp_dispatch_mfa: imsg_get error"); - if (n == 0) - break; - - switch (imsg.hdr.type) { - case IMSG_MFA_MAIL: - case IMSG_MFA_RCPT: { - struct submit_status *ss = imsg.data; - struct session *s; - - log_debug("smtp_dispatch_mfa: mfa handled return path"); - IMSG_SIZE_CHECK(ss); - - if ((s = session_lookup(env, ss->id)) == NULL) - break; - - session_pickup(s, ss); - break; - } - default: - log_warnx("smtp_dispatch_mfa: got imsg %d", - imsg.hdr.type); - fatalx("smtp_dispatch_mfa: unexpected imsg"); - } - imsg_free(&imsg); - } - imsg_event_add(iev); -} - -void -smtp_dispatch_lka(int sig, short event, void *p) -{ - struct smtpd *env = p; - struct imsgev *iev; - struct imsgbuf *ibuf; - struct imsg imsg; - ssize_t n; - - iev = env->sc_ievs[PROC_LKA]; - ibuf = &iev->ibuf; - - if (event & EV_READ) { - if ((n = imsg_read(ibuf)) == -1) - fatal("imsg_read_error"); - if (n == 0) { - /* this pipe is dead, so remove the event handler */ - event_del(&iev->ev); - event_loopexit(NULL); + case IMSG_CTL_VERBOSE: + log_verbose(*(int *)imsg->data); return; } } - if (event & EV_WRITE) { - if (msgbuf_write(&ibuf->w) == -1) - fatal("msgbuf_write"); - } - - for (;;) { - if ((n = imsg_get(ibuf, &imsg)) == -1) - fatal("smtp_dispatch_lka: imsg_get error"); - if (n == 0) - break; - - switch (imsg.hdr.type) { - case IMSG_DNS_PTR: { - struct dns *reply = imsg.data; - struct session *s; - struct session key; - - IMSG_SIZE_CHECK(reply); - - key.s_id = reply->id; - - s = SPLAY_FIND(sessiontree, &env->sc_sessions, &key); - if (s == NULL) - fatal("smtp_dispatch_lka: session is gone"); - - strlcpy(s->s_hostname, - reply->error ? "<unknown>" : reply->host, - sizeof(s->s_hostname)); - - strlcpy(s->s_msg.session_hostname, s->s_hostname, - sizeof(s->s_msg.session_hostname)); - - session_init(s->s_l, s); - - break; - } - default: - log_warnx("smtp_dispatch_lka: got imsg %d", - imsg.hdr.type); - fatalx("smtp_dispatch_lka: unexpected imsg"); - } - imsg_free(&imsg); - } - imsg_event_add(iev); -} - -void -smtp_dispatch_queue(int sig, short event, void *p) -{ - struct smtpd *env = p; - struct imsgev *iev; - struct imsgbuf *ibuf; - struct imsg imsg; - ssize_t n; - - iev = env->sc_ievs[PROC_QUEUE]; - ibuf = &iev->ibuf; - - if (event & EV_READ) { - if ((n = imsg_read(ibuf)) == -1) - fatal("imsg_read_error"); - if (n == 0) { - /* this pipe is dead, so remove the event handler */ - event_del(&iev->ev); - event_loopexit(NULL); - return; - } - } - - if (event & EV_WRITE) { - if (msgbuf_write(&ibuf->w) == -1) - fatal("msgbuf_write"); - } - - for (;;) { - if ((n = imsg_get(ibuf, &imsg)) == -1) - fatal("smtp_dispatch_queue: imsg_get error"); - if (n == 0) - break; - - switch (imsg.hdr.type) { - case IMSG_QUEUE_CREATE_MESSAGE: { - struct submit_status *ss = imsg.data; - struct session *s; - - log_debug("smtp_dispatch_queue: queue handled message creation"); - - IMSG_SIZE_CHECK(ss); - - if ((s = session_lookup(env, ss->id)) == NULL) - break; - - (void)strlcpy(s->s_msg.message_id, ss->u.msgid, - sizeof(s->s_msg.message_id)); - session_pickup(s, ss); - break; - } - case IMSG_QUEUE_MESSAGE_FILE: { - struct submit_status *ss = imsg.data; - struct session *s; - int fd; - - log_debug("smtp_dispatch_queue: queue handled message creation"); - - IMSG_SIZE_CHECK(ss); - - fd = imsg.fd; - - if ((s = session_lookup(env, ss->id)) == NULL) { - close(fd); - break; - } - - if ((s->datafp = fdopen(fd, "w")) == NULL) { - /* queue may have experienced tempfail. */ - if (ss->code != 421) - fatal("smtp_dispatch_queue: fdopen"); - close(fd); - } - - session_pickup(s, ss); - break; - } - case IMSG_QUEUE_TEMPFAIL: { - struct submit_status *ss = imsg.data; - struct session *s; - struct session key; - - log_debug("smtp_dispatch_queue: tempfail in queue"); - - IMSG_SIZE_CHECK(ss); - - key.s_id = ss->id; - s = SPLAY_FIND(sessiontree, &env->sc_sessions, &key); - if (s == NULL) - fatalx("smtp_dispatch_queue: session is gone"); - - if (s->s_flags & F_WRITEONLY) { - /* - * Session is write-only, can't destroy it. - */ - s->s_msg.status |= S_MESSAGE_TEMPFAILURE; - } else - fatalx("smtp_dispatch_queue: corrupt session"); - break; - } - - case IMSG_QUEUE_COMMIT_ENVELOPES: - case IMSG_QUEUE_COMMIT_MESSAGE: { - struct submit_status *ss = imsg.data; - struct session *s; - - log_debug("smtp_dispatch_queue: queue acknowledged message submission"); - - IMSG_SIZE_CHECK(ss); - - if ((s = session_lookup(env, ss->id)) == NULL) - break; - - session_pickup(s, ss); - break; - } - default: - log_warnx("smtp_dispatch_queue: got imsg %d", - imsg.hdr.type); - fatalx("smtp_dispatch_queue: unexpected imsg"); - } - imsg_free(&imsg); - } - imsg_event_add(iev); -} - -void -smtp_dispatch_control(int sig, short event, void *p) -{ - struct smtpd *env = p; - struct imsgev *iev; - struct imsgbuf *ibuf; - struct imsg imsg; - ssize_t n; - - iev = env->sc_ievs[PROC_CONTROL]; - ibuf = &iev->ibuf; - - if (event & EV_READ) { - if ((n = imsg_read(ibuf)) == -1) - fatal("imsg_read_error"); - if (n == 0) { - /* this pipe is dead, so remove the event handler */ - event_del(&iev->ev); - event_loopexit(NULL); - return; - } - } - - if (event & EV_WRITE) { - if (msgbuf_write(&ibuf->w) == -1) - fatal("msgbuf_write"); - } - - for (;;) { - if ((n = imsg_get(ibuf, &imsg)) == -1) - fatal("smtp_dispatch_control: imsg_get error"); - if (n == 0) - break; - - switch (imsg.hdr.type) { + if (iev->proc == PROC_CONTROL) { + switch (imsg->hdr.type) { case IMSG_SMTP_ENQUEUE: imsg_compose_event(iev, IMSG_SMTP_ENQUEUE, - imsg.hdr.peerid, 0, smtp_enqueue(env, imsg.data), + imsg->hdr.peerid, 0, smtp_enqueue(env, imsg->data), NULL, 0); - break; + return; + case IMSG_SMTP_PAUSE: smtp_pause(env); - break; + return; + case IMSG_SMTP_RESUME: smtp_resume(env); - break; - default: - log_warnx("smtp_dispatch_control: got imsg %d", - imsg.hdr.type); - fatalx("smtp_dispatch_control: unexpected imsg"); - } - imsg_free(&imsg); - } - imsg_event_add(iev); -} - -void -smtp_dispatch_runner(int sig, short event, void *p) -{ - struct smtpd *env = p; - struct imsgev *iev; - struct imsgbuf *ibuf; - struct imsg imsg; - ssize_t n; - - iev = env->sc_ievs[PROC_RUNNER]; - ibuf = &iev->ibuf; - - if (event & EV_READ) { - if ((n = imsg_read(ibuf)) == -1) - fatal("imsg_read_error"); - if (n == 0) { - /* this pipe is dead, so remove the event handler */ - event_del(&iev->ev); - event_loopexit(NULL); return; } } - if (event & EV_WRITE) { - if (msgbuf_write(&ibuf->w) == -1) - fatal("msgbuf_write"); - } - - for (;;) { - if ((n = imsg_get(ibuf, &imsg)) == -1) - fatal("smtp_dispatch_runner: imsg_get error"); - if (n == 0) - break; - - switch (imsg.hdr.type) { + if (iev->proc == PROC_RUNNER) { + switch (imsg->hdr.type) { case IMSG_SMTP_ENQUEUE: imsg_compose_event(iev, IMSG_SMTP_ENQUEUE, 0, 0, - smtp_enqueue(env, NULL), imsg.data, + smtp_enqueue(env, NULL), imsg->data, sizeof(struct message)); - break; - default: - log_warnx("smtp_dispatch_runner: got imsg %d", - imsg.hdr.type); - fatalx("smtp_dispatch_runner: unexpected imsg"); + return; } - imsg_free(&imsg); } - imsg_event_add(iev); + + fatalx("smtp_imsg: unexpected imsg"); +} + +void +smtp_sig_handler(int sig, short event, void *p) +{ + switch (sig) { + case SIGINT: + case SIGTERM: + smtp_shutdown(); + break; + default: + fatalx("smtp_sig_handler: unexpected signal"); + } } void @@ -605,12 +311,12 @@ smtp(struct smtpd *env) struct event ev_sigterm; struct peer peers[] = { - { PROC_PARENT, smtp_dispatch_parent }, - { PROC_MFA, smtp_dispatch_mfa }, - { PROC_QUEUE, smtp_dispatch_queue }, - { PROC_LKA, smtp_dispatch_lka }, - { PROC_CONTROL, smtp_dispatch_control }, - { PROC_RUNNER, smtp_dispatch_runner } + { PROC_PARENT, imsg_dispatch }, + { PROC_MFA, imsg_dispatch }, + { PROC_QUEUE, imsg_dispatch }, + { PROC_LKA, imsg_dispatch }, + { PROC_CONTROL, imsg_dispatch }, + { PROC_RUNNER, imsg_dispatch } }; switch (pid = fork()) { @@ -646,6 +352,7 @@ smtp(struct smtpd *env) fatal("smtp: cannot drop privileges"); #endif + imsg_callback = smtp_imsg; event_init(); signal_set(&ev_sigint, SIGINT, smtp_sig_handler, env); @@ -813,6 +520,7 @@ smtp_accept(int fd, short event, void *p) fatal("smtp_accept"); } + s->s_flags |= F_WRITEONLY; dns_query_ptr(l->env, &s->s_ss, s->s_id); } diff --git a/usr.sbin/smtpd/smtpd.c b/usr.sbin/smtpd/smtpd.c index 536b269cfa7..4e97facd3df 100644 --- a/usr.sbin/smtpd/smtpd.c +++ b/usr.sbin/smtpd/smtpd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: smtpd.c,v 1.100 2010/04/20 01:01:43 jacekm Exp $ */ +/* $OpenBSD: smtpd.c,v 1.101 2010/04/20 15:34:56 jacekm Exp $ */ /* * Copyright (c) 2008 Gilles Chehade <gilles@openbsd.org> @@ -46,20 +46,13 @@ #include "smtpd.h" +void parent_imsg(struct smtpd *, struct imsgev *, struct imsg *); __dead void usage(void); void parent_shutdown(struct smtpd *); void parent_send_config(int, short, void *); void parent_send_config_listeners(struct smtpd *); void parent_send_config_client_certs(struct smtpd *); void parent_send_config_ruleset(struct smtpd *, int); -void parent_dispatch_lka(int, short, void *); -void parent_dispatch_mda(int, short, void *); -void parent_dispatch_mfa(int, short, void *); -void parent_dispatch_mta(int, short, void *); -void parent_dispatch_smtp(int, short, void *); -void parent_dispatch_runner(int, short, void *); -void parent_dispatch_queue(int, short, void *); -void parent_dispatch_control(int, short, void *); void parent_sig_handler(int, short, void *); void forkmda(struct smtpd *, struct imsgev *, u_int32_t, @@ -76,9 +69,121 @@ void child_del(struct smtpd *, pid_t); struct child *child_lookup(struct smtpd *, pid_t); extern char **environ; +void (*imsg_callback)(struct smtpd *, struct imsgev *, struct imsg *); int __b64_pton(char const *, unsigned char *, size_t); +void +parent_imsg(struct smtpd *env, struct imsgev *iev, struct imsg *imsg) +{ + struct smtpd newenv; + struct forward_req *fwreq; + struct reload *reload; + struct auth *auth; + int fd; + + if (iev->proc == PROC_SMTP) { + switch (imsg->hdr.type) { + case IMSG_PARENT_SEND_CONFIG: + parent_send_config_listeners(env); + return; + + case IMSG_PARENT_AUTHENTICATE: + auth = imsg->data; + auth->success = authenticate_user(auth->user, + auth->pass); + imsg_compose_event(iev, IMSG_PARENT_AUTHENTICATE, 0, 0, + -1, auth, sizeof *auth); + return; + } + } + + if (iev->proc == PROC_LKA) { + switch (imsg->hdr.type) { + case IMSG_PARENT_FORWARD_OPEN: + fwreq = imsg->data; + fd = parent_forward_open(fwreq->pw_name); + fwreq->status = 0; + if (fd == -2) { + /* no ~/.forward, however it's optional. */ + fwreq->status = 1; + fd = -1; + } else if (fd != -1) + fwreq->status = 1; + imsg_compose_event(iev, IMSG_PARENT_FORWARD_OPEN, 0, 0, + fd, fwreq, sizeof *fwreq); + return; + } + } + + if (iev->proc == PROC_RUNNER) { + switch (imsg->hdr.type) { + case IMSG_PARENT_ENQUEUE_OFFLINE: + if (! parent_enqueue_offline(env, imsg->data)) + imsg_compose_event(iev, + IMSG_PARENT_ENQUEUE_OFFLINE, 0, 0, -1, + NULL, 0); + return; + } + } + + if (iev->proc == PROC_MDA) { + switch (imsg->hdr.type) { + case IMSG_PARENT_FORK_MDA: + forkmda(env, iev, imsg->hdr.peerid, imsg->data); + return; + } + } + + if (iev->proc == PROC_CONTROL) { + switch (imsg->hdr.type) { + case IMSG_CONF_RELOAD: + reload->ret = 0; + if (parse_config(&newenv, env->sc_conffile, 0) == 0) { + strlcpy(env->sc_hostname, newenv.sc_hostname, + sizeof env->sc_hostname); + env->sc_listeners = newenv.sc_listeners; + env->sc_maps = newenv.sc_maps; + env->sc_rules = newenv.sc_rules; + env->sc_rules = newenv.sc_rules; + env->sc_ssl = newenv.sc_ssl; + + parent_send_config_client_certs(env); + parent_send_config_ruleset(env, PROC_MFA); + parent_send_config_ruleset(env, PROC_LKA); + imsg_compose_event(env->sc_ievs[PROC_SMTP], + IMSG_CONF_RELOAD, 0, 0, -1, NULL, 0); + reload->ret = 1; + } + imsg_compose_event(iev, IMSG_CONF_RELOAD, 0, 0, -1, + reload, sizeof *reload); + return; + + case IMSG_CTL_VERBOSE: + log_verbose(*(int *)imsg->data); + + /* forward to other processes */ + imsg_compose_event(env->sc_ievs[PROC_LKA], IMSG_CTL_VERBOSE, + 0, 0, -1, imsg->data, sizeof(int)); + imsg_compose_event(env->sc_ievs[PROC_MDA], IMSG_CTL_VERBOSE, + 0, 0, -1, imsg->data, sizeof(int)); + imsg_compose_event(env->sc_ievs[PROC_MFA], IMSG_CTL_VERBOSE, + 0, 0, -1, imsg->data, sizeof(int)); + imsg_compose_event(env->sc_ievs[PROC_MTA], IMSG_CTL_VERBOSE, + 0, 0, -1, imsg->data, sizeof(int)); + imsg_compose_event(env->sc_ievs[PROC_QUEUE], IMSG_CTL_VERBOSE, + 0, 0, -1, imsg->data, sizeof(int)); + imsg_compose_event(env->sc_ievs[PROC_RUNNER], IMSG_CTL_VERBOSE, + 0, 0, -1, imsg->data, sizeof(int)); + imsg_compose_event(env->sc_ievs[PROC_SMTP], IMSG_CTL_VERBOSE, + 0, 0, -1, imsg->data, sizeof(int)); + return; + } + } + + fatalx("parent_imsg: unexpected imsg"); +} + __dead void usage(void) { @@ -226,458 +331,6 @@ parent_send_config_ruleset(struct smtpd *env, int proc) } void -parent_dispatch_lka(int imsgfd, short event, void *p) -{ - struct smtpd *env = p; - struct imsgev *iev; - struct imsgbuf *ibuf; - struct imsg imsg; - ssize_t n; - - iev = env->sc_ievs[PROC_LKA]; - ibuf = &iev->ibuf; - - if (event & EV_READ) { - if ((n = imsg_read(ibuf)) == -1) - fatal("imsg_read_error"); - if (n == 0) { - /* this pipe is dead, so remove the event handler */ - event_del(&iev->ev); - event_loopexit(NULL); - return; - } - } - - if (event & EV_WRITE) { - if (msgbuf_write(&ibuf->w) == -1) - fatal("msgbuf_write"); - } - - for (;;) { - if ((n = imsg_get(ibuf, &imsg)) == -1) - fatal("parent_dispatch_lka: imsg_get error"); - if (n == 0) - break; - - switch (imsg.hdr.type) { - case IMSG_PARENT_FORWARD_OPEN: { - struct forward_req *fwreq = imsg.data; - int fd; - - IMSG_SIZE_CHECK(fwreq); - - fd = parent_forward_open(fwreq->pw_name); - fwreq->status = 0; - if (fd == -2) { - /* user has no ~/.forward. it is optional, so - * set status to ok. */ - fwreq->status = 1; - fd = -1; - } else if (fd != -1) - fwreq->status = 1; - imsg_compose_event(iev, IMSG_PARENT_FORWARD_OPEN, 0, 0, fd, fwreq, sizeof(*fwreq)); - break; - } - default: - log_warnx("parent_dispatch_lka: got imsg %d", - imsg.hdr.type); - fatalx("parent_dispatch_lka: unexpected imsg"); - } - imsg_free(&imsg); - } - imsg_event_add(iev); -} - -void -parent_dispatch_mfa(int fd, short event, void *p) -{ - struct smtpd *env = p; - struct imsgev *iev; - struct imsgbuf *ibuf; - struct imsg imsg; - ssize_t n; - - iev = env->sc_ievs[PROC_MFA]; - ibuf = &iev->ibuf; - - if (event & EV_READ) { - if ((n = imsg_read(ibuf)) == -1) - fatal("imsg_read_error"); - if (n == 0) { - /* this pipe is dead, so remove the event handler */ - event_del(&iev->ev); - event_loopexit(NULL); - return; - } - } - - if (event & EV_WRITE) { - if (msgbuf_write(&ibuf->w) == -1) - fatal("msgbuf_write"); - } - - for (;;) { - if ((n = imsg_get(ibuf, &imsg)) == -1) - fatal("parent_dispatch_mfa: imsg_get error"); - if (n == 0) - break; - - switch (imsg.hdr.type) { - default: - log_warnx("parent_dispatch_mfa: got imsg %d", - imsg.hdr.type); - fatalx("parent_dispatch_mfa: unexpected imsg"); - } - imsg_free(&imsg); - } - imsg_event_add(iev); -} - -void -parent_dispatch_mta(int fd, short event, void *p) -{ - struct smtpd *env = p; - struct imsgev *iev; - struct imsgbuf *ibuf; - struct imsg imsg; - ssize_t n; - - iev = env->sc_ievs[PROC_MTA]; - ibuf = &iev->ibuf; - - if (event & EV_READ) { - if ((n = imsg_read(ibuf)) == -1) - fatal("imsg_read_error"); - if (n == 0) { - /* this pipe is dead, so remove the event handler */ - event_del(&iev->ev); - event_loopexit(NULL); - return; - } - } - - if (event & EV_WRITE) { - if (msgbuf_write(&ibuf->w) == -1) - fatal("msgbuf_write"); - } - - for (;;) { - if ((n = imsg_get(ibuf, &imsg)) == -1) - fatal("parent_dispatch_mta: imsg_get error"); - if (n == 0) - break; - - switch (imsg.hdr.type) { - default: - log_warnx("parent_dispatch_mta: got imsg %d", - imsg.hdr.type); - fatalx("parent_dispatch_mta: unexpected imsg"); - } - imsg_free(&imsg); - } - imsg_event_add(iev); -} - -void -parent_dispatch_mda(int imsgfd, short event, void *p) -{ - struct smtpd *env = p; - struct imsgev *iev; - struct imsgbuf *ibuf; - struct imsg imsg; - ssize_t n; - - iev = env->sc_ievs[PROC_MDA]; - ibuf = &iev->ibuf; - - if (event & EV_READ) { - if ((n = imsg_read(ibuf)) == -1) - fatal("imsg_read_error"); - if (n == 0) { - /* this pipe is dead, so remove the event handler */ - event_del(&iev->ev); - event_loopexit(NULL); - return; - } - } - - if (event & EV_WRITE) { - if (msgbuf_write(&ibuf->w) == -1) - fatal("msgbuf_write"); - } - - for (;;) { - if ((n = imsg_get(ibuf, &imsg)) == -1) - fatal("parent_dispatch_mda: imsg_get error"); - if (n == 0) - break; - - switch (imsg.hdr.type) { - case IMSG_PARENT_FORK_MDA: - forkmda(env, iev, imsg.hdr.peerid, imsg.data); - break; - - default: - log_warnx("parent_dispatch_mda: got imsg %d", - imsg.hdr.type); - fatalx("parent_dispatch_mda: unexpected imsg"); - } - imsg_free(&imsg); - } - imsg_event_add(iev); -} - -void -parent_dispatch_smtp(int fd, short event, void *p) -{ - struct smtpd *env = p; - struct imsgev *iev; - struct imsgbuf *ibuf; - struct imsg imsg; - ssize_t n; - - iev = env->sc_ievs[PROC_SMTP]; - ibuf = &iev->ibuf; - - if (event & EV_READ) { - if ((n = imsg_read(ibuf)) == -1) - fatal("imsg_read_error"); - if (n == 0) { - /* this pipe is dead, so remove the event handler */ - event_del(&iev->ev); - event_loopexit(NULL); - return; - } - } - - if (event & EV_WRITE) { - if (msgbuf_write(&ibuf->w) == -1) - fatal("msgbuf_write"); - } - - for (;;) { - if ((n = imsg_get(ibuf, &imsg)) == -1) - fatal("parent_dispatch_smtp: imsg_get error"); - if (n == 0) - break; - - switch (imsg.hdr.type) { - case IMSG_PARENT_SEND_CONFIG: { - parent_send_config_listeners(env); - break; - } - case IMSG_PARENT_AUTHENTICATE: { - struct auth *req = imsg.data; - - IMSG_SIZE_CHECK(req); - - req->success = authenticate_user(req->user, req->pass); - - imsg_compose_event(iev, IMSG_PARENT_AUTHENTICATE, 0, 0, - -1, req, sizeof(*req)); - break; - } - default: - log_warnx("parent_dispatch_smtp: got imsg %d", - imsg.hdr.type); - fatalx("parent_dispatch_smtp: unexpected imsg"); - } - imsg_free(&imsg); - } - imsg_event_add(iev); -} - -void -parent_dispatch_queue(int sig, short event, void *p) -{ - struct smtpd *env = p; - struct imsgev *iev; - struct imsgbuf *ibuf; - struct imsg imsg; - ssize_t n; - - iev = env->sc_ievs[PROC_QUEUE]; - ibuf = &iev->ibuf; - - if (event & EV_READ) { - if ((n = imsg_read(ibuf)) == -1) - fatal("imsg_read_error"); - if (n == 0) { - /* this pipe is dead, so remove the event handler */ - event_del(&iev->ev); - event_loopexit(NULL); - return; - } - } - - if (event & EV_WRITE) { - if (msgbuf_write(&ibuf->w) == -1) - fatal("msgbuf_write"); - } - - for (;;) { - if ((n = imsg_get(ibuf, &imsg)) == -1) - fatal("parent_dispatch_queue: imsg_get error"); - if (n == 0) - break; - - switch (imsg.hdr.type) { - default: - log_warnx("parent_dispatch_queue: got imsg %d", - imsg.hdr.type); - fatalx("parent_dispatch_queue: unexpected imsg"); - } - imsg_free(&imsg); - } - imsg_event_add(iev); -} - -void -parent_dispatch_runner(int sig, short event, void *p) -{ - struct smtpd *env = p; - struct imsgev *iev; - struct imsgbuf *ibuf; - struct imsg imsg; - ssize_t n; - - iev = env->sc_ievs[PROC_RUNNER]; - ibuf = &iev->ibuf; - - if (event & EV_READ) { - if ((n = imsg_read(ibuf)) == -1) - fatal("imsg_read_error"); - if (n == 0) { - /* this pipe is dead, so remove the event handler */ - event_del(&iev->ev); - event_loopexit(NULL); - return; - } - } - - if (event & EV_WRITE) { - if (msgbuf_write(&ibuf->w) == -1) - fatal("msgbuf_write"); - } - - for (;;) { - if ((n = imsg_get(ibuf, &imsg)) == -1) - fatal("parent_dispatch_runner: imsg_get error"); - if (n == 0) - break; - - switch (imsg.hdr.type) { - case IMSG_PARENT_ENQUEUE_OFFLINE: - if (! parent_enqueue_offline(env, imsg.data)) - imsg_compose_event(iev, IMSG_PARENT_ENQUEUE_OFFLINE, - 0, 0, -1, NULL, 0); - break; - default: - log_warnx("parent_dispatch_runner: got imsg %d", - imsg.hdr.type); - fatalx("parent_dispatch_runner: unexpected imsg"); - } - imsg_free(&imsg); - } - imsg_event_add(iev); -} - -void -parent_dispatch_control(int sig, short event, void *p) -{ - struct smtpd *env = p; - struct imsgev *iev; - struct imsgbuf *ibuf; - struct imsg imsg; - ssize_t n; - - iev = env->sc_ievs[PROC_CONTROL]; - ibuf = &iev->ibuf; - - if (event & EV_READ) { - if ((n = imsg_read(ibuf)) == -1) - fatal("imsg_read_error"); - if (n == 0) { - /* this pipe is dead, so remove the event handler */ - event_del(&iev->ev); - event_loopexit(NULL); - return; - } - } - - if (event & EV_WRITE) { - if (msgbuf_write(&ibuf->w) == -1) - fatal("msgbuf_write"); - } - - for (;;) { - if ((n = imsg_get(ibuf, &imsg)) == -1) - fatal("parent_dispatch_control: imsg_get error"); - if (n == 0) - break; - - switch (imsg.hdr.type) { - case IMSG_CONF_RELOAD: { - struct reload *r = imsg.data; - struct smtpd newenv; - - r->ret = 0; - if (parse_config(&newenv, env->sc_conffile, 0) == 0) { - - (void)strlcpy(env->sc_hostname, newenv.sc_hostname, - sizeof(env->sc_hostname)); - env->sc_listeners = newenv.sc_listeners; - env->sc_maps = newenv.sc_maps; - env->sc_rules = newenv.sc_rules; - env->sc_rules = newenv.sc_rules; - env->sc_ssl = newenv.sc_ssl; - - parent_send_config_client_certs(env); - parent_send_config_ruleset(env, PROC_MFA); - parent_send_config_ruleset(env, PROC_LKA); - imsg_compose_event(env->sc_ievs[PROC_SMTP], - IMSG_CONF_RELOAD, 0, 0, -1, NULL, 0); - r->ret = 1; - } - imsg_compose_event(iev, IMSG_CONF_RELOAD, 0, 0, -1, r, sizeof(*r)); - break; - } - case IMSG_CTL_VERBOSE: { - int verbose; - - IMSG_SIZE_CHECK(&verbose); - - memcpy(&verbose, imsg.data, sizeof(verbose)); - log_verbose(verbose); - - /* forward to other processes */ - imsg_compose_event(env->sc_ievs[PROC_LKA], IMSG_CTL_VERBOSE, - 0, 0, -1, &verbose, sizeof(verbose)); - imsg_compose_event(env->sc_ievs[PROC_MDA], IMSG_CTL_VERBOSE, - 0, 0, -1, &verbose, sizeof(verbose)); - imsg_compose_event(env->sc_ievs[PROC_MFA], IMSG_CTL_VERBOSE, - 0, 0, -1, &verbose, sizeof(verbose)); - imsg_compose_event(env->sc_ievs[PROC_MTA], IMSG_CTL_VERBOSE, - 0, 0, -1, &verbose, sizeof(verbose)); - imsg_compose_event(env->sc_ievs[PROC_QUEUE], IMSG_CTL_VERBOSE, - 0, 0, -1, &verbose, sizeof(verbose)); - imsg_compose_event(env->sc_ievs[PROC_RUNNER], IMSG_CTL_VERBOSE, - 0, 0, -1, &verbose, sizeof(verbose)); - imsg_compose_event(env->sc_ievs[PROC_SMTP], IMSG_CTL_VERBOSE, - 0, 0, -1, &verbose, sizeof(verbose)); - break; - } - default: - log_warnx("parent_dispatch_control: got imsg %d", - imsg.hdr.type); - fatalx("parent_dispatch_control: unexpected imsg"); - } - imsg_free(&imsg); - } - imsg_event_add(iev); -} - -void parent_sig_handler(int sig, short event, void *p) { struct smtpd *env = p; @@ -775,14 +428,14 @@ main(int argc, char *argv[]) struct event ev_sighup; struct timeval tv; struct peer peers[] = { - { PROC_CONTROL, parent_dispatch_control }, - { PROC_LKA, parent_dispatch_lka }, - { PROC_MDA, parent_dispatch_mda }, - { PROC_MFA, parent_dispatch_mfa }, - { PROC_MTA, parent_dispatch_mta }, - { PROC_SMTP, parent_dispatch_smtp }, - { PROC_QUEUE, parent_dispatch_queue }, - { PROC_RUNNER, parent_dispatch_runner } + { PROC_CONTROL, imsg_dispatch }, + { PROC_LKA, imsg_dispatch }, + { PROC_MDA, imsg_dispatch }, + { PROC_MFA, imsg_dispatch }, + { PROC_MTA, imsg_dispatch }, + { PROC_SMTP, imsg_dispatch }, + { PROC_QUEUE, imsg_dispatch }, + { PROC_RUNNER, imsg_dispatch } }; opts = 0; @@ -865,6 +518,7 @@ main(int argc, char *argv[]) fork_peers(&env); + imsg_callback = parent_imsg; event_init(); signal_set(&ev_sigint, SIGINT, parent_sig_handler, &env); @@ -1509,4 +1163,38 @@ child_cmp(struct child *c1, struct child *c2) return (0); } +void +imsg_dispatch(int fd, short event, void *p) +{ + struct imsgev *iev = p; + struct imsg imsg; + ssize_t n; + + if (event & EV_READ) { + if ((n = imsg_read(&iev->ibuf)) == -1) + fatal("imsg_read"); + if (n == 0) { + /* this pipe is dead, so remove the event handler */ + event_del(&iev->ev); + event_loopexit(NULL); + return; + } + } + + if (event & EV_WRITE) { + if (msgbuf_write(&iev->ibuf.w) == -1) + fatal("msgbuf_write"); + } + + for (;;) { + if ((n = imsg_get(&iev->ibuf, &imsg)) == -1) + fatal("imsg_get"); + if (n == 0) + break; + imsg_callback(iev->env, iev, &imsg); + imsg_free(&imsg); + } + imsg_event_add(iev); +} + SPLAY_GENERATE(childtree, child, entry, child_cmp); diff --git a/usr.sbin/smtpd/smtpd.h b/usr.sbin/smtpd/smtpd.h index f1f66d07f9a..96651f0ce9b 100644 --- a/usr.sbin/smtpd/smtpd.h +++ b/usr.sbin/smtpd/smtpd.h @@ -1,4 +1,4 @@ -/* $OpenBSD: smtpd.h,v 1.173 2010/04/19 10:12:48 gilles Exp $ */ +/* $OpenBSD: smtpd.h,v 1.174 2010/04/20 15:34:56 jacekm Exp $ */ /* * Copyright (c) 2008 Gilles Chehade <gilles@openbsd.org> @@ -202,6 +202,8 @@ struct imsgev { void (*handler)(int, short, void *); struct event ev; void *data; + struct smtpd *env; + int proc; short events; }; @@ -817,6 +819,8 @@ struct mta_session { void *pcb; }; +extern void (*imsg_callback)(struct smtpd *, struct imsgev *, struct imsg *); + /* aliases.c */ int aliases_exist(struct smtpd *, objid_t, char *); int aliases_get(struct smtpd *, objid_t, struct expandtree *, char *); @@ -874,6 +878,7 @@ SPLAY_PROTOTYPE(childtree, child, entry, child_cmp); void imsg_event_add(struct imsgev *); int imsg_compose_event(struct imsgev *, u_int16_t, u_int32_t, pid_t, int, void *, u_int16_t); +void imsg_dispatch(int, short, void *); /* lka.c */ pid_t lka(struct smtpd *); |