summaryrefslogtreecommitdiff
path: root/usr.sbin/smtpd/mda.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr.sbin/smtpd/mda.c')
-rw-r--r--usr.sbin/smtpd/mda.c176
1 files changed, 78 insertions, 98 deletions
diff --git a/usr.sbin/smtpd/mda.c b/usr.sbin/smtpd/mda.c
index a91e540295c..31e4197df55 100644
--- a/usr.sbin/smtpd/mda.c
+++ b/usr.sbin/smtpd/mda.c
@@ -1,9 +1,9 @@
-/* $OpenBSD: mda.c,v 1.44 2010/05/26 13:56:08 nicm Exp $ */
+/* $OpenBSD: mda.c,v 1.45 2010/05/31 23:38:56 jacekm Exp $ */
/*
* Copyright (c) 2008 Gilles Chehade <gilles@openbsd.org>
* Copyright (c) 2008 Pierre-Yves Ritschard <pyr@openbsd.org>
- * Copyright (c) 2009 Jacek Masiulaniec <jacekm@dobremiasto.net>
+ * Copyright (c) 2009-2010 Jacek Masiulaniec <jacekm@dobremiasto.net>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -36,6 +36,7 @@
#include <vis.h>
#include "smtpd.h"
+#include "queue_backend.h"
void mda_imsg(struct smtpd *, struct imsgev *, struct imsg *);
__dead void mda_shutdown(void);
@@ -46,74 +47,65 @@ void mda_store(struct mda_session *);
void mda_store_event(int, short, void *);
struct mda_session *mda_lookup(struct smtpd *, u_int32_t);
-u_int32_t mda_id;
-
void
mda_imsg(struct smtpd *env, struct imsgev *iev, struct imsg *imsg)
{
char output[128], *error, *parent_error;
struct deliver deliver;
struct mda_session *s;
- struct path *path;
+ struct action *action;
+ size_t action_sz;
if (iev->proc == PROC_QUEUE) {
switch (imsg->hdr.type) {
- case IMSG_MDA_SESS_NEW:
- /* make new session based on provided args */
- s = calloc(1, sizeof *s);
+ case IMSG_BATCH_CREATE:
+ s = malloc(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++;
+ bzero(&s->ev, sizeof s->ev);
+ s->id = imsg->hdr.peerid;
+ s->content_id = *(u_int64_t *)imsg->data;
s->datafp = fdopen(imsg->fd, "r");
if (s->datafp == NULL)
fatalx("mda: fdopen");
LIST_INSERT_HEAD(&env->mda_sessions, s, entry);
+ return;
+
+ case IMSG_BATCH_APPEND:
+ LIST_FOREACH(s, &env->mda_sessions, entry)
+ if (s->id == imsg->hdr.peerid)
+ break;
+ if (s == NULL)
+ fatalx("mda: bogus append");
+ action = imsg->data;
+ s->action_id = action->id;
+ s->auxraw = strdup(action->arg);
+ if (s->auxraw == NULL)
+ fatal(NULL);
+ auxsplit(&s->aux, s->auxraw);
+ 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;
-
- case A_MBOX:
- deliver.mode = A_EXT;
- strlcpy(deliver.user, "root",
- sizeof deliver.user);
+ case IMSG_BATCH_CLOSE:
+ LIST_FOREACH(s, &env->mda_sessions, entry)
+ if (s->id == imsg->hdr.peerid)
+ break;
+ if (s == NULL)
+ fatalx("mda: bogus close");
+ memcpy(&s->birth, imsg->data, sizeof s->birth);
+
+ /* request helper process from parent */
+ if (s->aux.mode[0] == 'M') {
+ deliver.mode = 'P';
+ 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("mda: unknown rule action");
+ "exec /usr/libexec/mail.local %s",
+ s->aux.user_to);
+ } else {
+ deliver.mode = s->aux.mode[0];
+ strlcpy(deliver.user, s->aux.user_to, sizeof deliver.user);
+ strlcpy(deliver.to, s->aux.path, sizeof deliver.to);
}
-
imsg_compose_event(env->sc_ievs[PROC_PARENT],
IMSG_PARENT_FORK_MDA, s->id, 0, -1, &deliver,
sizeof deliver);
@@ -136,6 +128,10 @@ mda_imsg(struct smtpd *env, struct imsgev *iev, struct imsg *imsg)
case IMSG_MDA_DONE:
s = mda_lookup(env, imsg->hdr.peerid);
+ /* all parent errors are temporary */
+ if (asprintf(&parent_error, "100 %s", (char *)imsg->data) < 0)
+ fatal("mda: asprintf");
+
/*
* Grab last line of mda stdout/stderr if available.
*/
@@ -162,12 +158,11 @@ mda_imsg(struct smtpd *env, struct imsgev *iev, struct imsg *imsg)
buf[len] = '\0';
ln = buf;
}
- strlcpy(output, "\"", sizeof output);
- strnvis(output + 1, ln,
- sizeof(output) - 2,
+ strlcpy(output, "100 \"", sizeof output);
+ strnvis(output + 5, ln,
+ sizeof(output) - 6,
VIS_SAFE | VIS_CSTYLE);
strlcat(output, "\"", sizeof output);
- log_debug("mda_out: %s", output);
}
free(buf);
fclose(fp);
@@ -178,11 +173,11 @@ mda_imsg(struct smtpd *env, struct imsgev *iev, struct imsg *imsg)
* child's output, the latter having preference over
* the former.
*/
- error = NULL;
- parent_error = imsg->data;
- if (strcmp(parent_error, "exited okay") == 0) {
+ if (strcmp(parent_error + 4, "exited okay") == 0) {
if (!feof(s->datafp) || s->w.queued)
- error = "mda exited prematurely";
+ error = "100 mda exited prematurely";
+ else
+ error = "200 ok";
} else {
if (output[0])
error = output;
@@ -191,35 +186,24 @@ mda_imsg(struct smtpd *env, struct imsgev *iev, struct imsg *imsg)
}
/* update queue entry */
- if (error == NULL)
- s->msg.status = S_MESSAGE_ACCEPTED;
- else
- strlcpy(s->msg.session_errorline, error,
- sizeof s->msg.session_errorline);
+ action_sz = sizeof *action + strlen(error) + 1;
+ action = malloc(action_sz);
+ if (action == NULL)
+ fatal(NULL);
+ action->id = s->action_id;
+ strlcpy(action->arg, error, action_sz - sizeof *action);
imsg_compose_event(env->sc_ievs[PROC_QUEUE],
- IMSG_QUEUE_MESSAGE_UPDATE, 0, 0, -1, &s->msg,
- sizeof s->msg);
-
- /*
- * XXX: which struct path gets used for logging depends
- * on whether lka did aliases or .forward processing;
- * lka may need to be changed to present data in more
- * unified way.
- */
- if (s->msg.recipient.rule.r_action == A_MAILDIR ||
- s->msg.recipient.rule.r_action == A_MBOX)
- path = &s->msg.recipient;
- else
- path = &s->msg.session_rcpt;
+ IMSG_BATCH_UPDATE, s->id, 0, -1, action, action_sz);
+ imsg_compose_event(env->sc_ievs[PROC_QUEUE],
+ IMSG_BATCH_DONE, s->id, 0, -1, NULL, 0);
/* log status */
- if (error && asprintf(&error, "Error (%s)", error) < 0)
- fatal("mda: asprintf");
- log_info("%s: to=<%s@%s>, delay=%d, stat=%s",
- s->msg.message_id, path->user, path->domain,
- time(NULL) - s->msg.creation,
- error ? error : "Sent");
- free(error);
+ log_info("%s: to=%s, delay=%d, stat=%s%s%s",
+ queue_be_decode(s->content_id), rcpt_pretty(&s->aux),
+ time(NULL) - s->birth,
+ *error == '2' ? "Sent" : "Error (",
+ *error == '2' ? "" : error + 4,
+ *error == '2' ? "" : ")");
/* destroy session */
LIST_REMOVE(s, entry);
@@ -229,11 +213,9 @@ mda_imsg(struct smtpd *env, struct imsgev *iev, struct imsg *imsg)
fclose(s->datafp);
msgbuf_clear(&s->w);
event_del(&s->ev);
+ free(s->auxraw);
free(s);
-
- /* update queue's session count */
- imsg_compose_event(env->sc_ievs[PROC_QUEUE],
- IMSG_MDA_SESS_NEW, 0, 0, -1, NULL, 0);
+ free(parent_error);
return;
case IMSG_CTL_VERBOSE:
@@ -325,13 +307,13 @@ mda(struct smtpd *env)
signal_add(&ev_sigint, NULL);
signal_add(&ev_sigterm, NULL);
signal(SIGPIPE, SIG_IGN);
- signal(SIGHUP, SIG_IGN);
config_pipes(env, peers, nitems(peers));
config_peers(env, peers, nitems(peers));
mda_setup_events(env);
- event_dispatch();
+ if (event_dispatch() < 0)
+ log_warn("event_dispatch");
mda_shutdown();
return (0);
@@ -344,14 +326,12 @@ mda_store(struct mda_session *s)
struct ibuf *buf;
int len;
- if (s->msg.sender.user[0] && s->msg.sender.domain[0])
- /* XXX: remove user provided Return-Path, if any */
- len = asprintf(&p, "Return-Path: %s@%s\nDelivered-To: %s@%s\n",
- s->msg.sender.user, s->msg.sender.domain,
- s->msg.session_rcpt.user, s->msg.session_rcpt.domain);
+ /* XXX: remove user provided Return-Path, if any */
+ if (s->aux.mail_from[0])
+ len = asprintf(&p, "Return-Path: %s\nDelivered-To: %s\n",
+ s->aux.mail_from, s->aux.rcpt_to);
else
- len = asprintf(&p, "Delivered-To: %s@%s\n",
- s->msg.session_rcpt.user, s->msg.session_rcpt.domain);
+ len = asprintf(&p, "Delivered-To: %s\n", s->aux.rcpt_to);
if (len == -1)
fatal("mda_store: asprintf");