diff options
Diffstat (limited to 'usr.sbin/smtpd/mta.c')
-rw-r--r-- | usr.sbin/smtpd/mta.c | 421 |
1 files changed, 114 insertions, 307 deletions
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); |