summaryrefslogtreecommitdiff
path: root/usr.sbin
diff options
context:
space:
mode:
authorGilles Chehade <gilles@cvs.openbsd.org>2011-10-23 09:30:08 +0000
committerGilles Chehade <gilles@cvs.openbsd.org>2011-10-23 09:30:08 +0000
commite3cfbeb71221f3f3bee3fcbfef00515742b2db32 (patch)
treeb6982699bd3a5aa673680f516988242d259225b7 /usr.sbin
parent436e188d636566b43d727d0356572ecdff1c87d9 (diff)
fsqueue no longer stores envelopes by dumping the structure, instead use a
couple of load/dump functions to convert to and from a human readable fmt. while at it kill struct delivery and merge back its fields to the envelope. this basically means we shouldn't require users to flush their queues every time we make a change to struct envelope. work is not done, but we're at a better state than the binary fsqueue so we'll improve it in-tree. has been running on my own box for the last 12 hours or so ok eric@, chl@
Diffstat (limited to 'usr.sbin')
-rw-r--r--usr.sbin/smtpd/bounce.c23
-rw-r--r--usr.sbin/smtpd/lka.c6
-rw-r--r--usr.sbin/smtpd/lka_session.c111
-rw-r--r--usr.sbin/smtpd/mda.c40
-rw-r--r--usr.sbin/smtpd/mfa.c16
-rw-r--r--usr.sbin/smtpd/mfa_session.c4
-rw-r--r--usr.sbin/smtpd/mta.c44
-rw-r--r--usr.sbin/smtpd/queue.c24
-rw-r--r--usr.sbin/smtpd/queue_backend.c39
-rw-r--r--usr.sbin/smtpd/queue_fsqueue.c103
-rw-r--r--usr.sbin/smtpd/queue_fsqueue_ascii.c783
-rw-r--r--usr.sbin/smtpd/queue_shared.c83
-rw-r--r--usr.sbin/smtpd/ramqueue.c42
-rw-r--r--usr.sbin/smtpd/ruleset.c10
-rw-r--r--usr.sbin/smtpd/runner.c69
-rw-r--r--usr.sbin/smtpd/smtp.c24
-rw-r--r--usr.sbin/smtpd/smtp_session.c76
-rw-r--r--usr.sbin/smtpd/smtpctl.c3
-rw-r--r--usr.sbin/smtpd/smtpctl/Makefile4
-rw-r--r--usr.sbin/smtpd/smtpd.h77
-rw-r--r--usr.sbin/smtpd/smtpd/Makefile4
-rw-r--r--usr.sbin/smtpd/util.c40
22 files changed, 1235 insertions, 390 deletions
diff --git a/usr.sbin/smtpd/bounce.c b/usr.sbin/smtpd/bounce.c
index af6a60dda93..6c729aa6ae8 100644
--- a/usr.sbin/smtpd/bounce.c
+++ b/usr.sbin/smtpd/bounce.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: bounce.c,v 1.33 2011/09/01 19:56:49 eric Exp $ */
+/* $OpenBSD: bounce.c,v 1.34 2011/10/23 09:30:06 gilles Exp $ */
/*
* Copyright (c) 2009 Gilles Chehade <gilles@openbsd.org>
@@ -54,7 +54,7 @@ bounce_session(int fd, struct envelope *m)
FILE *msgfp = NULL;
u_int32_t msgid;
- msgid = evpid_to_msgid(m->delivery.id);
+ msgid = evpid_to_msgid(m->id);
/* get message content */
if ((msgfd = queue_message_fd_r(Q_QUEUE, msgid)) == -1)
@@ -72,11 +72,11 @@ bounce_session(int fd, struct envelope *m)
client_ssl_optional(cc->pcb);
client_sender(cc->pcb, "");
- client_rcpt(cc->pcb, NULL, "%s@%s", m->delivery.from.user,
- m->delivery.from.domain);
+ client_rcpt(cc->pcb, NULL, "%s@%s", m->sender.user,
+ m->sender.domain);
/* Construct an appropriate reason line. */
- reason = m->delivery.errorline;
+ reason = m->errorline;
if (strlen(reason) > 4 && (*reason == '1' || *reason == '6'))
reason += 4;
@@ -100,9 +100,9 @@ bounce_session(int fd, struct envelope *m)
"Below is a copy of the original message:\n"
"\n",
env->sc_hostname,
- m->delivery.from.user, m->delivery.from.domain,
+ m->sender.user, m->sender.domain,
time_to_text(time(NULL)),
- m->delivery.rcpt.user, m->delivery.rcpt.domain,
+ m->dest.user, m->dest.domain,
reason);
/* setup event */
@@ -147,13 +147,16 @@ bounce_event(int fd, short event, void *p)
}
out:
- if (*ep == '2')
+ if (*ep == '2') {
+ log_debug("#### %s: queue_envelope_delete: %016llx",
+ __func__, cc->m.id);
queue_envelope_delete(Q_QUEUE, &cc->m);
+ }
else {
if (*ep == '5' || *ep == '6')
- cc->m.delivery.status = DS_PERMFAILURE;
+ cc->m.status = DS_PERMFAILURE;
else
- cc->m.delivery.status = DS_TEMPFAILURE;
+ cc->m.status = DS_TEMPFAILURE;
envelope_set_errormsg(&cc->m, "%s", ep);
queue_message_update(&cc->m);
}
diff --git a/usr.sbin/smtpd/lka.c b/usr.sbin/smtpd/lka.c
index 3ba0514430f..086c7395953 100644
--- a/usr.sbin/smtpd/lka.c
+++ b/usr.sbin/smtpd/lka.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: lka.c,v 1.128 2011/10/09 18:39:53 eric Exp $ */
+/* $OpenBSD: lka.c,v 1.129 2011/10/23 09:30:06 gilles Exp $ */
/*
* Copyright (c) 2008 Pierre-Yves Ritschard <pyr@openbsd.org>
@@ -92,9 +92,9 @@ lka_imsg(struct imsgev *iev, struct imsg *imsg)
ss->code = 250;
ss->envelope.rule = *rule;
if (IS_RELAY(*rule))
- ss->envelope.delivery.type = D_MTA;
+ ss->envelope.type = D_MTA;
else
- ss->envelope.delivery.type = D_MDA;
+ ss->envelope.type = D_MDA;
}
imsg_compose_event(iev, IMSG_LKA_RULEMATCH, 0, 0, -1,
ss, sizeof *ss);
diff --git a/usr.sbin/smtpd/lka_session.c b/usr.sbin/smtpd/lka_session.c
index df60ebf1dd3..6c0ddcb82a3 100644
--- a/usr.sbin/smtpd/lka_session.c
+++ b/usr.sbin/smtpd/lka_session.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: lka_session.c,v 1.10 2011/10/22 18:03:27 eric Exp $ */
+/* $OpenBSD: lka_session.c,v 1.11 2011/10/23 09:30:07 gilles Exp $ */
/*
* Copyright (c) 2011 Gilles Chehade <gilles@openbsd.org>
@@ -81,7 +81,7 @@ lka_session_envelope_expand(struct lka_session *lks, struct envelope *ep)
char username[MAX_LOCALPART_SIZE];
/* remote delivery, no need to process further */
- if (ep->delivery.type == D_MTA) {
+ if (ep->type == D_MTA) {
lka_session_deliver(lks, ep);
return 1;
}
@@ -90,10 +90,10 @@ lka_session_envelope_expand(struct lka_session *lks, struct envelope *ep)
case C_ALL:
case C_NET:
case C_DOM: {
- if (ep->delivery.agent.mda.to.user[0] == '\0')
- user = ep->delivery.rcpt.user;
+ if (ep->agent.mda.to.user[0] == '\0')
+ user = ep->dest.user;
else
- user = ep->delivery.agent.mda.to.user;
+ user = ep->agent.mda.to.user;
lowercase(username, user, sizeof(username));
/* gilles+hackers@ -> gilles@ */
@@ -113,24 +113,24 @@ lka_session_envelope_expand(struct lka_session *lks, struct envelope *ep)
if (! ub->getbyname(&u, username))
return 0;
- (void)strlcpy(ep->delivery.agent.mda.as_user, u.username,
- sizeof (ep->delivery.agent.mda.as_user));
+ (void)strlcpy(ep->agent.mda.as_user, u.username,
+ sizeof (ep->agent.mda.as_user));
- ep->delivery.type = D_MDA;
+ ep->type = D_MDA;
switch (ep->rule.r_action) {
case A_MBOX:
- ep->delivery.agent.mda.method = A_MBOX;
- (void)strlcpy(ep->delivery.agent.mda.to.user,
+ ep->agent.mda.method = A_MBOX;
+ (void)strlcpy(ep->agent.mda.to.user,
u.username,
- sizeof (ep->delivery.agent.mda.to.user));
+ sizeof (ep->agent.mda.to.user));
break;
case A_MAILDIR:
case A_FILENAME:
case A_EXT:
- ep->delivery.agent.mda.method = ep->rule.r_action;
- (void)strlcpy(ep->delivery.agent.mda.to.buffer,
+ ep->agent.mda.method = ep->rule.r_action;
+ (void)strlcpy(ep->agent.mda.to.buffer,
ep->rule.r_value.buffer,
- sizeof (ep->delivery.agent.mda.to.buffer));
+ sizeof (ep->agent.mda.to.buffer));
break;
default:
fatalx("lka_session_envelope_expand: unexpected rule action");
@@ -142,9 +142,9 @@ lka_session_envelope_expand(struct lka_session *lks, struct envelope *ep)
}
case C_VDOM: {
- if (aliases_virtual_exist(ep->rule.r_condition.c_map, &ep->delivery.rcpt)) {
+ if (aliases_virtual_exist(ep->rule.r_condition.c_map, &ep->dest)) {
if (! aliases_virtual_get(ep->rule.r_condition.c_map,
- &lks->expandtree, &ep->delivery.rcpt))
+ &lks->expandtree, &ep->dest))
return 0;
return 1;
}
@@ -373,8 +373,8 @@ lka_session_deliver(struct lka_session *lks, struct envelope *ep)
if (new_ep == NULL)
fatal("lka_session_deliver: calloc");
*new_ep = *ep;
- if (new_ep->delivery.type == D_MDA) {
- d_mda = &new_ep->delivery.agent.mda;
+ if (new_ep->type == D_MDA) {
+ d_mda = &new_ep->agent.mda;
if (d_mda->method == A_INVALID)
fatalx("lka_session_deliver: mda method == A_INVALID");
@@ -391,11 +391,12 @@ lka_session_deliver(struct lka_session *lks, struct envelope *ep)
default:
break;
}
- } else if (new_ep->delivery.type == D_MTA) {
+ }
+ else if (new_ep->type == D_MTA) {
if (ep->rule.r_action == A_RELAYVIA)
- new_ep->delivery.agent.mta.relay = ep->rule.r_value.relayhost;
+ new_ep->agent.mta.relay = ep->rule.r_value.relayhost;
if (ep->rule.r_as)
- new_ep->delivery.from = *ep->rule.r_as;
+ new_ep->sender = *ep->rule.r_as;
}
TAILQ_INSERT_TAIL(&lks->deliverylist, new_ep, entry);
}
@@ -403,12 +404,12 @@ lka_session_deliver(struct lka_session *lks, struct envelope *ep)
int
lka_session_resolve_node(struct envelope *ep, struct expandnode *xn)
{
- struct delivery *dlv;
- struct delivery olddlv;
+// struct delivery *dlv;
+// struct delivery olddlv;
+ struct envelope oldep;
- dlv = &ep->delivery;
- memcpy(&olddlv, dlv, sizeof (*dlv));
- bzero(&dlv->agent, sizeof (dlv->agent));
+ memcpy(&oldep, ep, sizeof (*ep));
+ bzero(&ep->agent, sizeof (ep->agent));
switch (xn->type) {
case EXPAND_INVALID:
@@ -419,13 +420,13 @@ lka_session_resolve_node(struct envelope *ep, struct expandnode *xn)
case EXPAND_ADDRESS:
log_debug("lka_resolve_node: node is address: %s@%s",
xn->u.mailaddr.user, xn->u.mailaddr.domain);
- dlv->rcpt = xn->u.mailaddr;
+ ep->dest = xn->u.mailaddr;
/* evaluation of ruleset assumes local source
* since we're expanding on already accepted
* source.
*/
- dlv->flags |= DF_INTERNAL;
+ ep->flags |= DF_INTERNAL;
if (! lka_session_rcpt_action(ep))
return -1;
return 0;
@@ -433,8 +434,8 @@ lka_session_resolve_node(struct envelope *ep, struct expandnode *xn)
case EXPAND_USERNAME:
log_debug("lka_resolve_node: node is local username: %s",
xn->u.user);
- dlv->type = D_MDA;
- dlv->agent.mda.to = xn->u;
+ ep->type = D_MDA;
+ ep->agent.mda.to = xn->u;
/* overwrite the initial condition before we expand the
* envelope again. if we came from a C_VDOM, not doing
@@ -448,35 +449,35 @@ lka_session_resolve_node(struct envelope *ep, struct expandnode *xn)
/* if expansion of a user results in same user ... deliver */
if (strcmp(xn->u.user, xn->as_user) == 0) {
- ep->delivery.agent.mda.method = olddlv.agent.mda.method;
+ ep->agent.mda.method = oldep.agent.mda.method;
break;
}
/* otherwise rewrite delivery user with expansion result */
- (void)strlcpy(dlv->agent.mda.to.user, xn->u.user,
- sizeof (dlv->agent.mda.to.user));
- (void)strlcpy(dlv->agent.mda.as_user, xn->u.user,
- sizeof (dlv->agent.mda.as_user));
+ (void)strlcpy(ep->agent.mda.to.user, xn->u.user,
+ sizeof (ep->agent.mda.to.user));
+ (void)strlcpy(ep->agent.mda.as_user, xn->u.user,
+ sizeof (ep->agent.mda.as_user));
return 0;
case EXPAND_FILENAME:
log_debug("lka_resolve_node: node is filename: %s",
xn->u.buffer);
- dlv->type = D_MDA;
- dlv->agent.mda.to = xn->u;
- dlv->agent.mda.method = A_FILENAME;
- (void)strlcpy(dlv->agent.mda.as_user, xn->as_user,
- sizeof (dlv->agent.mda.as_user));
+ ep->type = D_MDA;
+ ep->agent.mda.to = xn->u;
+ ep->agent.mda.method = A_FILENAME;
+ (void)strlcpy(ep->agent.mda.as_user, xn->as_user,
+ sizeof (ep->agent.mda.as_user));
break;
case EXPAND_FILTER:
log_debug("lka_resolve_node: node is filter: %s",
xn->u.buffer);
- dlv->type = D_MDA;
- dlv->agent.mda.to = xn->u;
- dlv->agent.mda.method = A_EXT;
- (void)strlcpy(dlv->agent.mda.as_user, xn->as_user,
- sizeof (dlv->agent.mda.as_user));
+ ep->type = D_MDA;
+ ep->agent.mda.to = xn->u;
+ ep->agent.mda.method = A_EXT;
+ (void)strlcpy(ep->agent.mda.as_user, xn->as_user,
+ sizeof (ep->agent.mda.as_user));
break;
}
@@ -491,7 +492,7 @@ lka_session_expand_format(char *buf, size_t len, struct envelope *ep)
struct user_backend *ub;
struct user u;
char lbuffer[MAX_RULEBUFFER_LEN];
- struct delivery *dlv = &ep->delivery;
+// struct delivery *dlv = &ep->delivery;
bzero(lbuffer, sizeof (lbuffer));
pbuf = lbuffer;
@@ -504,7 +505,7 @@ lka_session_expand_format(char *buf, size_t len, struct envelope *ep)
bzero(&u, sizeof (u));
ub = user_backend_lookup(USER_GETPWNAM);
- if (! ub->getbyname(&u, dlv->agent.mda.as_user))
+ if (! ub->getbyname(&u, ep->agent.mda.as_user))
return 0;
lret = strlcat(pbuf, u.directory, len);
@@ -549,19 +550,19 @@ lka_session_expand_format(char *buf, size_t len, struct envelope *ep)
}
switch (*tmp) {
case 'U':
- string = dlv->from.user;
+ string = ep->sender.user;
break;
case 'D':
- string = dlv->from.domain;
+ string = ep->sender.domain;
break;
case 'a':
- string = dlv->agent.mda.as_user;
+ string = ep->agent.mda.as_user;
break;
case 'u':
- string = dlv->rcpt.user;
+ string = ep->dest.user;
break;
case 'd':
- string = dlv->rcpt.domain;
+ string = ep->dest.domain;
break;
default:
goto copy;
@@ -604,7 +605,7 @@ lka_session_rcpt_action(struct envelope *ep)
r = ruleset_match(ep);
if (r == NULL) {
- ep->delivery.type = D_MTA;
+ ep->type = D_MTA;
return 0;
}
@@ -614,10 +615,10 @@ lka_session_rcpt_action(struct envelope *ep)
case A_MAILDIR:
case A_FILENAME:
case A_EXT:
- ep->delivery.type = D_MDA;
+ ep->type = D_MDA;
break;
default:
- ep->delivery.type = D_MTA;
+ ep->type = D_MTA;
}
return 1;
diff --git a/usr.sbin/smtpd/mda.c b/usr.sbin/smtpd/mda.c
index eaef4e7bd62..a2a783a2566 100644
--- a/usr.sbin/smtpd/mda.c
+++ b/usr.sbin/smtpd/mda.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: mda.c,v 1.60 2011/10/09 18:39:53 eric Exp $ */
+/* $OpenBSD: mda.c,v 1.61 2011/10/23 09:30:07 gilles Exp $ */
/*
* Copyright (c) 2008 Gilles Chehade <gilles@openbsd.org>
@@ -53,9 +53,9 @@ mda_imsg(struct imsgev *iev, struct imsg *imsg)
char output[128], *error, *parent_error;
struct deliver deliver;
struct mda_session *s;
- struct delivery *d;
struct delivery_mda *d_mda;
struct mailaddr *maddr;
+ struct envelope *ep;
log_imsg(PROC_MDA, iev->proc, imsg);
@@ -68,7 +68,7 @@ mda_imsg(struct imsgev *iev, struct imsg *imsg)
fatal(NULL);
msgbuf_init(&s->w);
s->msg = *(struct envelope *)imsg->data;
- s->msg.delivery.status = DS_TEMPFAILURE;
+ s->msg.status = DS_TEMPFAILURE;
s->id = mda_id++;
s->datafp = fdopen(imsg->fd, "r");
if (s->datafp == NULL)
@@ -76,8 +76,8 @@ mda_imsg(struct imsgev *iev, struct imsg *imsg)
LIST_INSERT_HEAD(&env->mda_sessions, s, entry);
/* request parent to fork a helper process */
- d = &s->msg.delivery;
- d_mda = &s->msg.delivery.agent.mda;
+ ep = &s->msg;
+ d_mda = &s->msg.agent.mda;
switch (d_mda->method) {
case A_EXT:
deliver.mode = A_EXT;
@@ -93,8 +93,8 @@ mda_imsg(struct imsgev *iev, struct imsg *imsg)
sizeof (deliver.user));
snprintf(deliver.to, sizeof (deliver.to),
"%s -f %s@%s %s", PATH_MAILLOCAL,
- d->from.user,
- d->from.domain,
+ ep->sender.user,
+ ep->sender.domain,
d_mda->to.user);
break;
@@ -197,10 +197,10 @@ mda_imsg(struct imsgev *iev, struct imsg *imsg)
/* update queue entry */
if (error == NULL)
- s->msg.delivery.status = DS_ACCEPTED;
+ s->msg.status = DS_ACCEPTED;
else
- strlcpy(s->msg.delivery.errorline, error,
- sizeof s->msg.delivery.errorline);
+ strlcpy(s->msg.errorline, error,
+ sizeof s->msg.errorline);
imsg_compose_event(env->sc_ievs[PROC_QUEUE],
IMSG_QUEUE_MESSAGE_UPDATE, 0, 0, -1, &s->msg,
sizeof s->msg);
@@ -213,16 +213,16 @@ mda_imsg(struct imsgev *iev, struct imsg *imsg)
*/
if (s->msg.rule.r_action == A_MAILDIR ||
s->msg.rule.r_action == A_MBOX)
- maddr = &s->msg.delivery.rcpt;
+ maddr = &s->msg.dest;
else
- maddr = &s->msg.delivery.rcpt_orig;
+ maddr = &s->msg.rcpt;
/* log status */
if (error && asprintf(&error, "Error (%s)", error) < 0)
fatal("mda: asprintf");
log_info("%016llx: to=<%s@%s>, delay=%lld, stat=%s",
- s->msg.delivery.id, maddr->user, maddr->domain,
- (long long int) (time(NULL) - s->msg.delivery.creation),
+ s->msg.id, maddr->user, maddr->domain,
+ (long long int) (time(NULL) - s->msg.creation),
error ? error : "Sent");
free(error);
@@ -339,16 +339,16 @@ mda_store(struct mda_session *s)
struct ibuf *buf;
int len;
- if (s->msg.delivery.from.user[0] && s->msg.delivery.from.domain[0])
+ 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.delivery.from.user, s->msg.delivery.from.domain,
- s->msg.delivery.rcpt_orig.user,
- s->msg.delivery.rcpt_orig.domain);
+ s->msg.sender.user, s->msg.sender.domain,
+ s->msg.rcpt.user,
+ s->msg.rcpt.domain);
else
len = asprintf(&p, "Delivered-To: %s@%s\n",
- s->msg.delivery.rcpt_orig.user,
- s->msg.delivery.rcpt_orig.domain);
+ s->msg.rcpt.user,
+ s->msg.rcpt.domain);
if (len == -1)
fatal("mda_store: asprintf");
diff --git a/usr.sbin/smtpd/mfa.c b/usr.sbin/smtpd/mfa.c
index b2c02918ee9..d1736b72eec 100644
--- a/usr.sbin/smtpd/mfa.c
+++ b/usr.sbin/smtpd/mfa.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: mfa.c,v 1.63 2011/10/09 18:39:53 eric Exp $ */
+/* $OpenBSD: mfa.c,v 1.64 2011/10/23 09:30:07 gilles Exp $ */
/*
* Copyright (c) 2008 Gilles Chehade <gilles@openbsd.org>
@@ -245,7 +245,7 @@ mfa_test_mail(struct envelope *e)
ss.id = e->session_id;
ss.code = 530;
- ss.u.maddr = e->delivery.from;
+ ss.u.maddr = e->sender;
if (mfa_strip_source_route(ss.u.maddr.user, sizeof(ss.u.maddr.user)))
goto refuse;
@@ -275,11 +275,11 @@ mfa_test_rcpt(struct envelope *e)
ss.id = e->session_id;
ss.code = 530;
- ss.u.maddr = e->delivery.rcpt_orig;
- ss.ss = e->delivery.ss;
+ ss.u.maddr = e->rcpt;
+ ss.ss = e->ss;
ss.envelope = *e;
- ss.envelope.delivery.rcpt = e->delivery.rcpt_orig;
- ss.flags = e->delivery.flags;
+ ss.envelope.dest = e->rcpt;
+ ss.flags = e->flags;
mfa_strip_source_route(ss.u.maddr.user, sizeof(ss.u.maddr.user));
@@ -303,8 +303,8 @@ mfa_test_rcpt_resume(struct submit_status *ss) {
return;
}
- ss->envelope.delivery.rcpt = ss->u.maddr;
- ss->envelope.delivery.expire = ss->envelope.rule.r_qexpire;
+ ss->envelope.dest = ss->u.maddr;
+ ss->envelope.expire = ss->envelope.rule.r_qexpire;
imsg_compose_event(env->sc_ievs[PROC_LKA], IMSG_LKA_RCPT, 0, 0, -1,
ss, sizeof(*ss));
}
diff --git a/usr.sbin/smtpd/mfa_session.c b/usr.sbin/smtpd/mfa_session.c
index c7158085a32..4d92262a181 100644
--- a/usr.sbin/smtpd/mfa_session.c
+++ b/usr.sbin/smtpd/mfa_session.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: mfa_session.c,v 1.4 2011/09/01 09:42:15 chl Exp $ */
+/* $OpenBSD: mfa_session.c,v 1.5 2011/10/23 09:30:07 gilles Exp $ */
/*
* Copyright (c) 2011 Gilles Chehade <gilles@openbsd.org>
@@ -98,7 +98,7 @@ mfa_session_proceed(struct mfa_session *ms)
switch (ms->state) {
case S_HELO:
fm.type = FILTER_HELO;
- if (strlcpy(fm.u.helo.buffer, ms->ss.envelope.delivery.helo,
+ if (strlcpy(fm.u.helo.buffer, ms->ss.envelope.helo,
sizeof(fm.u.helo.buffer)) >= sizeof(fm.u.helo.buffer))
fatalx("mfa_session_proceed: HELO: truncation");
break;
diff --git a/usr.sbin/smtpd/mta.c b/usr.sbin/smtpd/mta.c
index c727307ecd6..26d83c3833e 100644
--- a/usr.sbin/smtpd/mta.c
+++ b/usr.sbin/smtpd/mta.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: mta.c,v 1.114 2011/10/09 18:39:53 eric Exp $ */
+/* $OpenBSD: mta.c,v 1.115 2011/10/23 09:30:07 gilles Exp $ */
/*
* Copyright (c) 2008 Pierre-Yves Ritschard <pyr@openbsd.org>
@@ -136,11 +136,11 @@ mta_imsg(struct imsgev *iev, struct imsg *imsg)
if (e == NULL)
fatal(NULL);
*e = *(struct envelope *)imsg->data;
- strlcpy(e->delivery.errorline, "000 init",
- sizeof(e->delivery.errorline));
+ strlcpy(e->errorline, "000 init",
+ sizeof(e->errorline));
if (s->host == NULL) {
- s->host = strdup(e->delivery.rcpt.domain);
+ s->host = strdup(e->dest.domain);
if (s->host == NULL)
fatal("strdup");
}
@@ -480,16 +480,16 @@ mta_enter_state(struct mta_session *s, int newstate, void *p)
/* set envelope sender */
e = TAILQ_FIRST(&s->recipients);
- if (e->delivery.from.user[0] && e->delivery.from.domain[0])
- client_sender(pcb, "%s@%s", e->delivery.from.user,
- e->delivery.from.domain);
+ if (e->sender.user[0] && e->sender.domain[0])
+ client_sender(pcb, "%s@%s", e->sender.user,
+ e->sender.domain);
else
client_sender(pcb, "");
/* set envelope recipients */
TAILQ_FOREACH(e, &s->recipients, entry)
- client_rcpt(pcb, e, "%s@%s", e->delivery.rcpt.user,
- e->delivery.rcpt.domain);
+ client_rcpt(pcb, e, "%s@%s", e->dest.user,
+ e->dest.domain);
s->pcb = pcb;
event_set(&s->ev, s->fd, EV_READ|EV_WRITE, mta_event, s);
@@ -684,25 +684,25 @@ mta_message_status(struct envelope *e, char *status)
* higher status (eg. 5yz is of higher status than 4yz), so check
* this before deciding to overwrite existing status with a new one.
*/
- if (*status != '2' && strncmp(e->delivery.errorline, status, 3) > 0)
+ if (*status != '2' && strncmp(e->errorline, status, 3) > 0)
return;
/* change status */
- log_debug("mta: new status for %s@%s: %s", e->delivery.rcpt.user,
- e->delivery.rcpt.domain, status);
- strlcpy(e->delivery.errorline, status, sizeof(e->delivery.errorline));
+ log_debug("mta: new status for %s@%s: %s", e->dest.user,
+ e->dest.domain, status);
+ strlcpy(e->errorline, status, sizeof(e->errorline));
}
static void
mta_message_log(struct mta_session *s, struct envelope *e)
{
struct mta_relay *relay = TAILQ_FIRST(&s->relays);
- char *status = e->delivery.errorline;
+ char *status = e->errorline;
log_info("%016llx: to=<%s@%s>, delay=%lld, relay=%s [%s], stat=%s (%s)",
- e->delivery.id, e->delivery.rcpt.user,
- e->delivery.rcpt.domain,
- (long long int) (time(NULL) - e->delivery.creation),
+ e->id, e->dest.user,
+ e->dest.domain,
+ (long long int) (time(NULL) - e->creation),
relay ? relay->fqdn : "(none)",
relay ? ss_to_text(&relay->sa) : "",
*status == '2' ? "Sent" :
@@ -714,16 +714,16 @@ mta_message_log(struct mta_session *s, struct envelope *e)
static void
mta_message_done(struct mta_session *s, struct envelope *e)
{
- switch (e->delivery.errorline[0]) {
+ switch (e->errorline[0]) {
case '6':
case '5':
- e->delivery.status = DS_PERMFAILURE;
+ e->status = DS_PERMFAILURE;
break;
case '2':
- e->delivery.status = DS_ACCEPTED;
+ e->status = DS_ACCEPTED;
break;
default:
- e->delivery.status = DS_TEMPFAILURE;
+ e->status = DS_TEMPFAILURE;
break;
}
imsg_compose_event(env->sc_ievs[PROC_QUEUE],
@@ -747,7 +747,7 @@ mta_request_datafd(struct mta_session *s)
e = TAILQ_FIRST(&s->recipients);
rq_batch.b_id = s->id;
- rq_batch.msgid = evpid_to_msgid(e->delivery.id);
+ rq_batch.msgid = evpid_to_msgid(e->id);
imsg_compose_event(env->sc_ievs[PROC_QUEUE], IMSG_QUEUE_MESSAGE_FD,
0, 0, -1, &rq_batch, sizeof(rq_batch));
}
diff --git a/usr.sbin/smtpd/queue.c b/usr.sbin/smtpd/queue.c
index 12ea1bd0d8a..2d19a2698b6 100644
--- a/usr.sbin/smtpd/queue.c
+++ b/usr.sbin/smtpd/queue.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: queue.c,v 1.107 2011/10/09 18:39:53 eric Exp $ */
+/* $OpenBSD: queue.c,v 1.108 2011/10/23 09:30:07 gilles Exp $ */
/*
* Copyright (c) 2008 Gilles Chehade <gilles@openbsd.org>
@@ -61,7 +61,7 @@ queue_imsg(struct imsgev *iev, struct imsg *imsg)
ss.id = e->session_id;
ss.code = 250;
ss.u.msgid = 0;
- if (e->delivery.flags & DF_ENQUEUED)
+ if (e->flags & DF_ENQUEUED)
ret = queue_message_create(Q_ENQUEUE, &ss.u.msgid);
else
ret = queue_message_create(Q_INCOMING, &ss.u.msgid);
@@ -72,21 +72,21 @@ queue_imsg(struct imsgev *iev, struct imsg *imsg)
return;
case IMSG_QUEUE_REMOVE_MESSAGE:
- if (e->delivery.flags & DF_ENQUEUED)
- queue_message_purge(Q_ENQUEUE, evpid_to_msgid(e->delivery.id));
+ if (e->flags & DF_ENQUEUED)
+ queue_message_purge(Q_ENQUEUE, evpid_to_msgid(e->id));
else
- queue_message_purge(Q_INCOMING, evpid_to_msgid(e->delivery.id));
+ queue_message_purge(Q_INCOMING, evpid_to_msgid(e->id));
return;
case IMSG_QUEUE_COMMIT_MESSAGE:
ss.id = e->session_id;
- if (e->delivery.flags & DF_ENQUEUED) {
- if (queue_message_commit(Q_ENQUEUE, evpid_to_msgid(e->delivery.id)))
+ if (e->flags & DF_ENQUEUED) {
+ if (queue_message_commit(Q_ENQUEUE, evpid_to_msgid(e->id)))
stat_increment(STATS_QUEUE_LOCAL);
else
ss.code = 421;
} else {
- if (queue_message_commit(Q_INCOMING, evpid_to_msgid(e->delivery.id)))
+ if (queue_message_commit(Q_INCOMING, evpid_to_msgid(e->id)))
stat_increment(STATS_QUEUE_REMOTE);
else
ss.code = 421;
@@ -101,10 +101,10 @@ queue_imsg(struct imsgev *iev, struct imsg *imsg)
case IMSG_QUEUE_MESSAGE_FILE:
ss.id = e->session_id;
- if (e->delivery.flags & DF_ENQUEUED)
- fd = queue_message_fd_rw(Q_ENQUEUE, evpid_to_msgid(e->delivery.id));
+ if (e->flags & DF_ENQUEUED)
+ fd = queue_message_fd_rw(Q_ENQUEUE, evpid_to_msgid(e->id));
else
- fd = queue_message_fd_rw(Q_INCOMING, evpid_to_msgid(e->delivery.id));
+ fd = queue_message_fd_rw(Q_INCOMING, evpid_to_msgid(e->id));
if (fd == -1)
ss.code = 421;
imsg_compose_event(iev, IMSG_QUEUE_MESSAGE_FILE, 0, 0, fd,
@@ -125,7 +125,7 @@ queue_imsg(struct imsgev *iev, struct imsg *imsg)
ss.id = e->session_id;
/* Write to disk */
- if (e->delivery.flags & DF_ENQUEUED)
+ if (e->flags & DF_ENQUEUED)
ret = queue_envelope_create(Q_ENQUEUE, e);
else
ret = queue_envelope_create(Q_INCOMING, e);
diff --git a/usr.sbin/smtpd/queue_backend.c b/usr.sbin/smtpd/queue_backend.c
index d86033126ff..1095a591fe3 100644
--- a/usr.sbin/smtpd/queue_backend.c
+++ b/usr.sbin/smtpd/queue_backend.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: queue_backend.c,v 1.11 2011/05/16 21:05:52 gilles Exp $ */
+/* $OpenBSD: queue_backend.c,v 1.12 2011/10/23 09:30:07 gilles Exp $ */
/*
* Copyright (c) 2011 Gilles Chehade <gilles@openbsd.org>
@@ -23,6 +23,7 @@
#include <sys/socket.h>
#include <sys/stat.h>
+#include <ctype.h>
#include <event.h>
#include <imsg.h>
#include <libgen.h>
@@ -35,12 +36,13 @@
#include "smtpd.h"
#include "log.h"
+static int envelope_validate(struct envelope *);
+
/* fsqueue backend */
int fsqueue_init(void);
int fsqueue_message(enum queue_kind, enum queue_op, u_int32_t *);
int fsqueue_envelope(enum queue_kind, enum queue_op , struct envelope *);
-
struct queue_backend queue_backends[] = {
{ QT_FS,
fsqueue_init,
@@ -114,8 +116,10 @@ queue_envelope_delete(enum queue_kind qkind, struct envelope *ep)
int
queue_envelope_load(enum queue_kind qkind, u_int64_t evpid, struct envelope *ep)
{
- ep->delivery.id = evpid;
- return env->sc_queue->envelope(qkind, QOP_LOAD, ep);
+ ep->id = evpid;
+ if (env->sc_queue->envelope(qkind, QOP_LOAD, ep))
+ return envelope_validate(ep);
+ return 0;
}
int
@@ -123,3 +127,30 @@ queue_envelope_update(enum queue_kind qkind, struct envelope *ep)
{
return env->sc_queue->envelope(qkind, QOP_UPDATE, ep);
}
+
+static int
+envelope_validate(struct envelope *ep)
+{
+ if (ep->version != SMTPD_ENVELOPE_VERSION)
+ return 0;
+
+ if ((ep->id & 0xffffffff) == 0 ||
+ ((ep->id >> 32) & 0xffffffff) == 0)
+ return 0;
+
+ if (ep->helo[0] == '\0')
+ return 0;
+
+ if (ep->hostname[0] == '\0')
+ return 0;
+
+ if (ep->errorline[0] != '\0') {
+ if (! isdigit(ep->errorline[0]) ||
+ ! isdigit(ep->errorline[1]) ||
+ ! isdigit(ep->errorline[2]) ||
+ ep->errorline[3] != ' ')
+ return 0;
+ }
+
+ return 1;
+}
diff --git a/usr.sbin/smtpd/queue_fsqueue.c b/usr.sbin/smtpd/queue_fsqueue.c
index e1e5e5f0b2b..f0c7361d7ce 100644
--- a/usr.sbin/smtpd/queue_fsqueue.c
+++ b/usr.sbin/smtpd/queue_fsqueue.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: queue_fsqueue.c,v 1.13 2011/08/26 14:39:47 chl Exp $ */
+/* $OpenBSD: queue_fsqueue.c,v 1.14 2011/10/23 09:30:07 gilles Exp $ */
/*
* Copyright (c) 2011 Gilles Chehade <gilles@openbsd.org>
@@ -40,7 +40,6 @@
#include "log.h"
static char *fsqueue_getpath(enum queue_kind);
-/*static*/ u_int16_t fsqueue_hash(u_int32_t);
static int fsqueue_envelope_load(enum queue_kind, struct envelope *);
static int fsqueue_envelope_update(enum queue_kind, struct envelope *);
@@ -57,6 +56,9 @@ int fsqueue_init(void);
int fsqueue_message(enum queue_kind, enum queue_op, u_int32_t *);
int fsqueue_envelope(enum queue_kind, enum queue_op , struct envelope *);
+int fsqueue_load_envelope_ascii(FILE *, struct envelope *);
+int fsqueue_dump_envelope_ascii(FILE *, struct envelope *);
+
static char *
fsqueue_getpath(enum queue_kind kind)
{
@@ -85,12 +87,6 @@ fsqueue_getpath(enum queue_kind kind)
return NULL;
}
-/*static*/ u_int16_t
-fsqueue_hash(u_int32_t h)
-{
- return (h % DIRHASH_BUCKETS);
-}
-
static int
fsqueue_envelope_create(enum queue_kind qkind, struct envelope *ep)
{
@@ -106,8 +102,7 @@ again:
rnd = (u_int32_t)arc4random();
if (rnd == 0)
goto again;
- evpid = ep->delivery.id | rnd;
-
+ evpid = ep->id | rnd;
if (! bsnprintf(evpname, sizeof(evpname), "%s/%08x%s/%016llx",
fsqueue_getpath(qkind),
@@ -127,19 +122,19 @@ again:
fp = fdopen(fd, "w");
if (fp == NULL)
fatal("fsqueue_envelope_create: fdopen");
-
- ep->delivery.creation = time(NULL);
- ep->delivery.id = evpid;
+
+ ep->creation = time(NULL);
+ ep->id = evpid;
if (qkind == Q_BOUNCE) {
- ep->delivery.lasttry = 0;
- ep->delivery.retry = 0;
+ ep->lasttry = 0;
+ ep->retry = 0;
}
- if (fwrite(ep, sizeof (*ep), 1, fp) != 1) {
+ if (! fsqueue_dump_envelope_ascii(fp, ep)) {
if (errno == ENOSPC)
goto tempfail;
- fatal("fsqueue_envelope_create: write");
+ fatal("fsqueue_dump_envelope_ascii: write");
}
if (! safe_fclose(fp)) {
@@ -156,8 +151,8 @@ tempfail:
fclose(fp);
else if (fd != -1)
close(fd);
- ep->delivery.creation = 0;
- ep->delivery.id = 0;
+ ep->creation = 0;
+ ep->id = 0;
return 0;
}
@@ -168,11 +163,11 @@ fsqueue_envelope_load(enum queue_kind qkind, struct envelope *ep)
char pathname[MAXPATHLEN];
FILE *fp;
- if (! bsnprintf(pathname, sizeof(pathname), "%s/%04x/%08x%s/%016llx",
+ if (! bsnprintf(pathname, sizeof(pathname), "%s/%03x/%08x%s/%016llx",
fsqueue_getpath(qkind),
- fsqueue_hash(evpid_to_msgid(ep->delivery.id)),
- evpid_to_msgid(ep->delivery.id),
- PATH_ENVELOPES, ep->delivery.id))
+ evpid_to_msgid(ep->id) & 0xfff,
+ evpid_to_msgid(ep->id),
+ PATH_ENVELOPES, ep->id))
fatalx("fsqueue_envelope_load: snprintf");
fp = fopen(pathname, "r");
@@ -181,8 +176,8 @@ fsqueue_envelope_load(enum queue_kind qkind, struct envelope *ep)
return 0;
fatal("fsqueue_envelope_load: fopen");
}
- if (fread(ep, sizeof (*ep), 1, fp) != 1)
- fatal("fsqueue_envelope_load: fread");
+ if (! fsqueue_load_envelope_ascii(fp, ep))
+ fatal("fsqueue_load_envelope_ascii: fread");
fclose(fp);
return 1;
}
@@ -201,11 +196,11 @@ fsqueue_envelope_update(enum queue_kind qkind, struct envelope *ep)
if (! bsnprintf(temp, sizeof(temp), "%s/envelope.tmp", PATH_QUEUE))
fatalx("fsqueue_envelope_update");
- if (! bsnprintf(dest, sizeof(dest), "%s/%04x/%08x%s/%016llx",
+ if (! bsnprintf(dest, sizeof(dest), "%s/%03x/%08x%s/%016llx",
fsqueue_getpath(qkind),
- fsqueue_hash(evpid_to_msgid(ep->delivery.id)),
- evpid_to_msgid(ep->delivery.id),
- PATH_ENVELOPES, ep->delivery.id))
+ evpid_to_msgid(ep->id) & 0xfff,
+ evpid_to_msgid(ep->id),
+ PATH_ENVELOPES, ep->id))
fatal("fsqueue_envelope_update: snprintf");
fp = fopen(temp, "w");
@@ -214,10 +209,10 @@ fsqueue_envelope_update(enum queue_kind qkind, struct envelope *ep)
goto tempfail;
fatal("fsqueue_envelope_update: open");
}
- if (fwrite(ep, sizeof (*ep), 1, fp) != 1) {
+ if (! fsqueue_dump_envelope_ascii(fp, ep)) {
if (errno == ENOSPC)
goto tempfail;
- fatal("fsqueue_envelope_update: fwrite");
+ fatal("fsqueue_dump_envelope_ascii: fwrite");
}
if (! safe_fclose(fp))
goto tempfail;
@@ -245,27 +240,27 @@ static int
fsqueue_envelope_delete(enum queue_kind qkind, struct envelope *ep)
{
char pathname[MAXPATHLEN];
- u_int16_t hval;
-
- hval = fsqueue_hash(evpid_to_msgid(ep->delivery.id));
- if (! bsnprintf(pathname, sizeof(pathname), "%s/%04x/%08x%s/%016llx",
+ if (! bsnprintf(pathname, sizeof(pathname), "%s/%03x/%08x%s/%016llx",
fsqueue_getpath(qkind),
- hval,
- evpid_to_msgid(ep->delivery.id),
+ evpid_to_msgid(ep->id) & 0xfff,
+ evpid_to_msgid(ep->id),
PATH_ENVELOPES,
- ep->delivery.id))
+ ep->id))
fatal("fsqueue_envelope_delete: snprintf");
- if (unlink(pathname) == -1)
+ if (unlink(pathname) == -1) {
+ log_debug("######: %s [errno: %d]", pathname, errno);
fatal("fsqueue_envelope_delete: unlink");
+ }
- if (! bsnprintf(pathname, sizeof(pathname), "%s/%04x/%08x%s", PATH_QUEUE,
- hval, evpid_to_msgid(ep->delivery.id), PATH_ENVELOPES))
+ if (! bsnprintf(pathname, sizeof(pathname), "%s/%03x/%08x%s", PATH_QUEUE,
+ evpid_to_msgid(ep->id) & 0xfff,
+ evpid_to_msgid(ep->id), PATH_ENVELOPES))
fatal("fsqueue_envelope_delete: snprintf");
if (rmdir(pathname) != -1)
- fsqueue_message_delete(qkind, evpid_to_msgid(ep->delivery.id));
+ fsqueue_message_delete(qkind, evpid_to_msgid(ep->id));
return 1;
}
@@ -313,9 +308,9 @@ again:
}
if (qkind == Q_BOUNCE) {
- if (! bsnprintf(msgpath, sizeof(msgpath), "%s/%04x/%08x/message",
+ if (! bsnprintf(msgpath, sizeof(msgpath), "%s/%03x/%08x/message",
fsqueue_getpath(Q_QUEUE),
- fsqueue_hash(msgid_save),
+ msgid_save & 0xfff,
msgid_save))
return 0;
@@ -341,10 +336,10 @@ fsqueue_message_commit(enum queue_kind qkind, u_int32_t msgid)
fsqueue_getpath(qkind), msgid))
fatal("fsqueue_message_commit: snprintf");
- if (! bsnprintf(queuedir, sizeof(queuedir), "%s/%04x",
- fsqueue_getpath(Q_QUEUE), fsqueue_hash(msgid)))
+ if (! bsnprintf(queuedir, sizeof(queuedir), "%s/%03x",
+ fsqueue_getpath(Q_QUEUE), msgid & 0xfff))
fatal("fsqueue_message_commit: snprintf");
-
+
if (mkdir(queuedir, 0700) == -1) {
if (errno == ENOSPC)
return 0;
@@ -370,7 +365,6 @@ fsqueue_message_fd_r(enum queue_kind qkind, u_int32_t msgid)
{
int fd;
char pathname[MAXPATHLEN];
- u_int16_t hval;
if (qkind == Q_ENQUEUE || qkind == Q_INCOMING) {
if (! bsnprintf(pathname, sizeof(pathname), "%s/%08x/message",
@@ -378,9 +372,8 @@ fsqueue_message_fd_r(enum queue_kind qkind, u_int32_t msgid)
fatal("fsqueue_message_fd_r: snprintf");
}
else {
- hval = fsqueue_hash(msgid);
- if (! bsnprintf(pathname, sizeof(pathname), "%s/%04x/%08x/message",
- fsqueue_getpath(qkind), hval, msgid))
+ if (! bsnprintf(pathname, sizeof(pathname), "%s/%03x/%08x/message",
+ fsqueue_getpath(qkind), msgid & 0xfff, msgid))
fatal("fsqueue_message_fd_r: snprintf");
}
@@ -409,11 +402,9 @@ fsqueue_message_delete(enum queue_kind qkind, u_int32_t msgid)
char rootdir[MAXPATHLEN];
char evpdir[MAXPATHLEN];
char msgpath[MAXPATHLEN];
- u_int16_t hval;
- hval = fsqueue_hash(msgid);
- if (! bsnprintf(rootdir, sizeof(rootdir), "%s/%04x/%08x", PATH_QUEUE,
- hval, msgid))
+ if (! bsnprintf(rootdir, sizeof(rootdir), "%s/%03x/%08x", PATH_QUEUE,
+ msgid & 0xfff, msgid))
fatal("queue_delete_message: snprintf");
if (! bsnprintf(evpdir, sizeof(evpdir), "%s%s", rootdir,
@@ -438,7 +429,7 @@ fsqueue_message_delete(enum queue_kind qkind, u_int32_t msgid)
if (rmdir(rootdir) == -1)
fatal("#2 queue_delete_message: rmdir");
- if (! bsnprintf(rootdir, sizeof(rootdir), "%s/%04x", PATH_QUEUE, hval))
+ if (! bsnprintf(rootdir, sizeof(rootdir), "%s/%03x", PATH_QUEUE, msgid & 0xffff))
fatal("queue_delete_message: snprintf");
rmdir(rootdir);
diff --git a/usr.sbin/smtpd/queue_fsqueue_ascii.c b/usr.sbin/smtpd/queue_fsqueue_ascii.c
new file mode 100644
index 00000000000..1c7c78ddd5e
--- /dev/null
+++ b/usr.sbin/smtpd/queue_fsqueue_ascii.c
@@ -0,0 +1,783 @@
+/* $OpenBSD: queue_fsqueue_ascii.c,v 1.1 2011/10/23 09:30:07 gilles Exp $ */
+
+/*
+ * Copyright (c) 2011 Gilles Chehade <gilles@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/tree.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <ctype.h>
+#include <err.h>
+#include <errno.h>
+#include <event.h>
+#include <fcntl.h>
+#include <imsg.h>
+#include <libgen.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+#include "smtpd.h"
+#include "log.h"
+
+
+#define KW_VERSION "version"
+#define KW_EVPID "evpid"
+#define KW_TYPE "type"
+#define KW_HELO "helo"
+#define KW_HOSTNAME "hostname"
+#define KW_ERRORLINE "errorline"
+#define KW_SOCKADDR "sockaddr"
+#define KW_SENDER "sender"
+#define KW_RCPT "rcpt"
+#define KW_DEST "dest"
+#define KW_CTIME "ctime"
+#define KW_EXPIRE "expire"
+#define KW_RETRY "retry"
+#define KW_LAST_TRY "last-try"
+#define KW_FLAGS "flags"
+#define KW_STATUS "status"
+
+#define KW_MDA_METHOD "mda-method"
+#define KW_MDA_BUFFER "mda-buffer"
+#define KW_MDA_USER "mda-user"
+
+#define KW_MTA_RELAY_HOST "mta-relay-hostname"
+#define KW_MTA_RELAY_PORT "mta-relay-port"
+#define KW_MTA_RELAY_FLAGS "mta-relay-flags"
+#define KW_MTA_RELAY_CERT "mta-relay-cert"
+#define KW_MTA_RELAY_AS "mta-relay-as"
+
+int fsqueue_load_envelope_ascii(FILE *, struct envelope *);
+int fsqueue_dump_envelope_ascii(FILE *, struct envelope *);
+
+static int
+ascii_load_version(struct envelope *ep, char *buf)
+{
+ const char *errstr;
+
+ ep->version = strtonum(buf, 0, 0xffffffff, &errstr);
+ if (errstr)
+ return 0;
+ return 1;
+}
+
+static int
+ascii_dump_version(struct envelope *ep, FILE *fp)
+{
+ fprintf(fp, "%s: %d\n", KW_VERSION, SMTPD_ENVELOPE_VERSION);
+ return 1;
+}
+
+
+static int
+ascii_load_evpid(struct envelope *ep, char *buf)
+{
+ char *endptr;
+
+ ep->id = strtoull(buf, &endptr, 16);
+ if (buf[0] == '\0' || *endptr != '\0')
+ return 0;
+ if (errno == ERANGE && ep->id == ULLONG_MAX)
+ return 0;
+ return 1;
+}
+
+static int
+ascii_dump_evpid(struct envelope *ep, FILE *fp)
+{
+ fprintf(fp, "%s: %016llx\n", KW_EVPID, ep->id);
+ return 1;
+}
+
+
+static int
+ascii_load_type(struct envelope *ep, char *buf)
+{
+ if (strcasecmp(buf, "mda") == 0)
+ ep->type = D_MDA;
+ else if (strcasecmp(buf, "mta") == 0)
+ ep->type = D_MTA;
+ else if (strcasecmp(buf, "bounce") == 0)
+ ep->type = D_BOUNCE;
+ else
+ return 0;
+ return 1;
+}
+
+static int
+ascii_dump_type(struct envelope *ep, FILE *fp)
+{
+ fprintf(fp, "%s: ", KW_TYPE);
+ switch (ep->type) {
+ case D_MDA:
+ fprintf(fp, "mda\n");
+ break;
+ case D_MTA:
+ fprintf(fp, "mta\n");
+ break;
+ case D_BOUNCE:
+ fprintf(fp, "bounce\n");
+ break;
+ default:
+ return 0;
+ }
+ return 1;
+}
+
+
+static int
+ascii_load_mda_method(struct envelope *ep, char *buf)
+{
+ if (strcasecmp(buf, "mbox") == 0)
+ ep->agent.mda.method = A_MBOX;
+ else if (strcasecmp(buf, "maildir") == 0)
+ ep->agent.mda.method = A_MAILDIR;
+ else if (strcasecmp(buf, "filename") == 0)
+ ep->agent.mda.method = A_FILENAME;
+ else if (strcasecmp(buf, "external") == 0)
+ ep->agent.mda.method = A_EXT;
+ else
+ return 0;
+ return 1;
+}
+
+static int
+ascii_dump_mda_method(struct envelope *ep, FILE *fp)
+{
+ fprintf(fp, "%s: ", KW_MDA_METHOD);
+ switch (ep->agent.mda.method) {
+ case A_MAILDIR:
+ fprintf(fp, "maildir\n");
+ break;
+ case A_MBOX:
+ fprintf(fp, "mbox\n");
+ break;
+ case A_FILENAME:
+ fprintf(fp, "filename\n");
+ break;
+ case A_EXT:
+ fprintf(fp, "external\n");
+ break;
+ default:
+ return 0;
+ }
+ return 1;
+}
+
+static int
+ascii_load_mda_buffer(struct envelope *ep, char *buf)
+{
+ if (strlcpy(ep->agent.mda.to.buffer, buf,
+ sizeof (ep->agent.mda.to.buffer))
+ >= sizeof (ep->agent.mda.to.buffer))
+ return 0;
+ return 1;
+}
+
+static int
+ascii_dump_mda_buffer(struct envelope *ep, FILE *fp)
+{
+ fprintf(fp, "%s: %s\n", KW_MDA_BUFFER,
+ ep->agent.mda.to.buffer);
+ return 1;
+}
+
+
+static int
+ascii_load_mda_user(struct envelope *ep, char *buf)
+{
+ if (strlcpy(ep->agent.mda.as_user, buf,
+ sizeof (ep->agent.mda.as_user))
+ >= sizeof (ep->agent.mda.as_user))
+ return 0;
+ return 1;
+}
+
+static int
+ascii_dump_mda_user(struct envelope *ep, FILE *fp)
+{
+ fprintf(fp, "%s: %s\n", KW_MDA_USER,
+ ep->agent.mda.as_user);
+ return 1;
+}
+
+
+static int
+ascii_load_helo(struct envelope *ep, char *buf)
+{
+ if (strlcpy(ep->helo, buf,
+ sizeof (ep->helo))
+ >= sizeof (ep->helo))
+ return 0;
+ return 1;
+}
+
+static int
+ascii_dump_helo(struct envelope *ep, FILE *fp)
+{
+ fprintf(fp, "%s: %s\n", KW_HELO, ep->helo);
+ return 1;
+}
+
+
+static int
+ascii_load_hostname(struct envelope *ep, char *buf)
+{
+ if (strlcpy(ep->hostname, buf,
+ sizeof (ep->hostname))
+ >= sizeof (ep->hostname))
+ return 0;
+ return 1;
+}
+
+static int
+ascii_dump_hostname(struct envelope *ep, FILE *fp)
+{
+ fprintf(fp, "%s: %s\n", KW_HOSTNAME, ep->hostname);
+ return 1;
+}
+
+static int
+ascii_load_errorline(struct envelope *ep, char *buf)
+{
+ if (strlcpy(ep->errorline, buf,
+ sizeof(ep->errorline)) >=
+ sizeof(ep->errorline))
+ return 0;
+
+ return 1;
+}
+
+static int
+ascii_dump_errorline(struct envelope *ep, FILE *fp)
+{
+ if (ep->errorline[0])
+ fprintf(fp, "%s: %s\n", KW_ERRORLINE,
+ ep->errorline);
+ return 1;
+}
+
+
+static int
+ascii_load_sockaddr(struct envelope *ep, char *buf)
+{
+ struct sockaddr_in6 ssin6;
+ struct sockaddr_in ssin;
+
+ if (strncasecmp("IPv6:", buf, 5) == 0) {
+ if (inet_pton(AF_INET6, buf + 5, &ssin6.sin6_addr) != 1)
+ return 0;
+ ssin6.sin6_family = AF_INET6;
+ memcpy(&ep->ss, &ssin6, sizeof(ssin6));
+ ep->ss.ss_len = sizeof(struct sockaddr_in6);
+ }
+ else {
+ if (inet_pton(AF_INET, buf, &ssin.sin_addr) != 1)
+ return 0;
+ ssin.sin_family = AF_INET;
+ memcpy(&ep->ss, &ssin6, sizeof(ssin));
+ ep->ss.ss_len = sizeof(struct sockaddr_in);
+ }
+ return 1;
+}
+
+static int
+ascii_dump_sockaddr(struct envelope *ep, FILE *fp)
+{
+ fprintf(fp, "%s: %s\n", KW_SOCKADDR, ss_to_text(&ep->ss));
+ return 1;
+}
+
+
+static int
+ascii_load_sender(struct envelope *ep, char *buf)
+{
+ if (! email_to_mailaddr(&ep->sender, buf))
+ return 0;
+ return 1;
+}
+
+static int
+ascii_dump_sender(struct envelope *ep, FILE *fp)
+{
+ fprintf(fp, "%s: %s@%s\n", KW_SENDER,
+ ep->sender.user, ep->sender.domain);
+ return 1;
+}
+
+
+static int
+ascii_load_rcpt(struct envelope *ep, char *buf)
+{
+ if (! email_to_mailaddr(&ep->rcpt, buf))
+ return 0;
+ ep->dest = ep->rcpt;
+ return 1;
+}
+
+static int
+ascii_dump_rcpt(struct envelope *ep, FILE *fp)
+{
+ fprintf(fp, "%s: %s@%s\n", KW_RCPT,
+ ep->dest.user, ep->dest.domain);
+ return 1;
+}
+
+
+static int
+ascii_load_dest(struct envelope *ep, char *buf)
+{
+ if (! email_to_mailaddr(&ep->dest, buf))
+ return 0;
+ return 1;
+}
+
+static int
+ascii_dump_dest(struct envelope *ep, FILE *fp)
+{
+ if (strcmp(ep->dest.user, ep->dest.user) != 0 ||
+ strcmp(ep->dest.domain, ep->dest.domain) != 0)
+ fprintf(fp, "%s: %s@%s\n", KW_DEST,
+ ep->dest.user,
+ ep->dest.domain);
+ return 1;
+}
+
+
+static int
+ascii_load_mta_relay_host(struct envelope *ep, char *buf)
+{
+ if (strlcpy(ep->agent.mta.relay.hostname, buf,
+ sizeof(ep->agent.mta.relay.hostname))
+ >= sizeof(ep->agent.mta.relay.hostname))
+ return 0;
+ return 1;
+}
+
+static int
+ascii_dump_mta_relay_host(struct envelope *ep, FILE *fp)
+{
+ if (ep->agent.mta.relay.hostname[0])
+ fprintf(fp, "%s: %s\n", KW_MTA_RELAY_HOST,
+ ep->agent.mta.relay.hostname);
+ return 1;
+}
+
+static int
+ascii_load_mta_relay_port(struct envelope *ep, char *buf)
+{
+ const char *errstr;
+
+ ep->agent.mta.relay.port = strtonum(buf, 0, 0xffff, &errstr);
+ if (errstr)
+ return 0;
+ return 1;
+}
+
+static int
+ascii_dump_mta_relay_port(struct envelope *ep, FILE *fp)
+{
+ if (ep->agent.mta.relay.port)
+ fprintf(fp, "%s: %d\n", KW_MTA_RELAY_PORT,
+ ep->agent.mta.relay.port);
+ return 1;
+}
+
+static int
+ascii_load_mta_relay_cert(struct envelope *ep, char *buf)
+{
+ if (strlcpy(ep->agent.mta.relay.cert, buf,
+ sizeof(ep->agent.mta.relay.cert))
+ >= sizeof(ep->agent.mta.relay.cert))
+ return 0;
+ return 1;
+}
+
+static int
+ascii_dump_mta_relay_cert(struct envelope *ep, FILE *fp)
+{
+ if (ep->agent.mta.relay.cert[0])
+ fprintf(fp, "%s: %s\n", KW_MTA_RELAY_CERT,
+ ep->agent.mta.relay.cert);
+ return 1;
+}
+
+static int
+ascii_load_mta_relay_flags(struct envelope *ep, char *buf)
+{
+ char *flag;
+
+ while ((flag = strsep(&buf, " ,|")) != NULL) {
+ if (strcasecmp(flag, "force-anyssl") == 0)
+ ep->agent.mta.relay.flags |= MTA_FORCE_ANYSSL;
+ else if (strcasecmp(flag, "force-smtps") == 0)
+ ep->agent.mta.relay.flags |= MTA_FORCE_SMTPS;
+ else if (strcasecmp(flag, "allow-plain") == 0)
+ ep->agent.mta.relay.flags |= MTA_ALLOW_PLAIN;
+ else if (strcasecmp(flag, "use-auth") == 0)
+ ep->agent.mta.relay.flags |= MTA_USE_AUTH;
+ else if (strcasecmp(flag, "force-mx") == 0)
+ ep->agent.mta.relay.flags |= MTA_FORCE_MX;
+ else
+ return 0;
+ }
+
+ return 1;
+}
+
+static int
+ascii_dump_mta_relay_flags(struct envelope *ep, FILE *fp)
+{
+ if (ep->agent.mta.relay.flags) {
+ fprintf(fp, "%s:", KW_MTA_RELAY_FLAGS);
+ if (ep->agent.mta.relay.flags & MTA_FORCE_ANYSSL)
+ fprintf(fp, " force-anyssl");
+ if (ep->agent.mta.relay.flags & MTA_FORCE_SMTPS)
+ fprintf(fp, " force-smtps");
+ if (ep->agent.mta.relay.flags & MTA_ALLOW_PLAIN)
+ fprintf(fp, " allow-plain");
+ if (ep->agent.mta.relay.flags & MTA_USE_AUTH)
+ fprintf(fp, " use-auth");
+ if (ep->agent.mta.relay.flags & MTA_FORCE_MX)
+ fprintf(fp, " force-mx");
+ fprintf(fp, "\n");
+ }
+ return 1;
+}
+
+static int
+ascii_dump_mta_relay_as(struct envelope *ep, FILE *fp)
+{
+ if (ep->agent.mta.relay_as.user[0] ||
+ ep->agent.mta.relay_as.domain[0])
+ fprintf(fp, "%s: %s@%s\n", KW_MTA_RELAY_AS,
+ ep->agent.mta.relay_as.user,
+ ep->agent.mta.relay_as.domain);
+ return 1;
+}
+
+
+static int
+ascii_load_ctime(struct envelope *ep, char *buf)
+{
+ const char *errstr;
+
+ ep->creation = strtonum(buf, 0, 0xffffffff, &errstr);
+ if (errstr)
+ return 0;
+ return 1;
+}
+
+static int
+ascii_dump_ctime(struct envelope *ep, FILE *fp)
+{
+ if (ep->creation)
+ fprintf(fp, "%s: %qd\n", KW_CTIME,
+ (u_int64_t)ep->creation);
+ return 1;
+}
+
+
+static int
+ascii_load_expire(struct envelope *ep, char *buf)
+{
+ const char *errstr;
+
+ ep->expire = strtonum(buf, 0, 0xffffffff, &errstr);
+ if (errstr)
+ return 0;
+ return 1;
+}
+
+static int
+ascii_dump_expire(struct envelope *ep, FILE *fp)
+{
+ if (ep->expire)
+ fprintf(fp, "%s: %qd\n", KW_EXPIRE,
+ (u_int64_t)ep->expire);
+ return 1;
+}
+
+static int
+ascii_load_retry(struct envelope *ep, char *buf)
+{
+ const char *errstr;
+
+ ep->retry = strtonum(buf, 0, 0xffffffff, &errstr);
+ if (errstr)
+ return 0;
+ return 1;
+}
+
+static int
+ascii_dump_retry(struct envelope *ep, FILE *fp)
+{
+ if (ep->retry)
+ fprintf(fp, "%s: %d\n", KW_RETRY,
+ ep->retry);
+ return 1;
+}
+
+static int
+ascii_load_lasttry(struct envelope *ep, char *buf)
+{
+ const char *errstr;
+
+ ep->lasttry = strtonum(buf, 0, 0xffffffff, &errstr);
+ if (errstr)
+ return 0;
+ return 1;
+}
+
+static int
+ascii_dump_lasttry(struct envelope *ep, FILE *fp)
+{
+ if (ep->lasttry)
+ fprintf(fp, "%s: %qd\n", KW_LAST_TRY,
+ (u_int64_t)ep->lasttry);
+ return 1;
+}
+
+static int
+ascii_dump_flags(struct envelope *ep, FILE *fp)
+{
+ if (ep->flags) {
+ fprintf(fp, "%s:", KW_FLAGS);
+ if (ep->flags & DF_AUTHENTICATED)
+ fprintf(fp, " authenticated");
+ if (ep->flags & DF_ENQUEUED)
+ fprintf(fp, " enqueued");
+ if (ep->flags & DF_BOUNCE)
+ fprintf(fp, " bounce");
+ if (ep->flags & DF_INTERNAL)
+ fprintf(fp, " internal");
+ fprintf(fp, "\n");
+ }
+ return 1;
+}
+
+static int
+ascii_load_flags(struct envelope *ep, char *buf)
+{
+ char *flag;
+
+ while ((flag = strsep(&buf, " ,|")) != NULL) {
+ if (strcasecmp(flag, "authenticated") == 0)
+ ep->flags |= DF_AUTHENTICATED;
+ else if (strcasecmp(flag, "enqueued") == 0)
+ ep->flags |= DF_ENQUEUED;
+ else if (strcasecmp(flag, "bounce") == 0)
+ ep->flags |= DF_BOUNCE;
+ else if (strcasecmp(flag, "internal") == 0)
+ ep->flags |= DF_INTERNAL;
+ else
+ return 0;
+ }
+ return 1;
+}
+
+static int
+ascii_dump_status(struct envelope *ep, FILE *fp)
+{
+ if (ep->status) {
+ fprintf(fp, "%s ", KW_STATUS);
+ if (ep->status & DS_PERMFAILURE)
+ fprintf(fp, " permfail");
+ if (ep->status & DS_TEMPFAILURE)
+ fprintf(fp, " tempfail");
+ if (ep->status & DS_REJECTED)
+ fprintf(fp, " rejected");
+ if (ep->status & DS_ACCEPTED)
+ fprintf(fp, " accepted");
+ fprintf(fp, "\n");
+ }
+ return 1;
+}
+
+static int
+ascii_dump_agent(struct envelope *ep, FILE *fp)
+{
+ if (! ascii_dump_type(ep, fp))
+ return 0;
+
+ switch (ep->type) {
+ case D_MDA:
+ if (! ascii_dump_mda_method(ep, fp) ||
+ ! ascii_dump_mda_buffer(ep, fp) ||
+ ! ascii_dump_mda_user(ep, fp))
+ return 0;
+ break;
+
+ case D_MTA:
+ if (! ascii_dump_mta_relay_host(ep, fp) ||
+ ! ascii_dump_mta_relay_port(ep, fp) ||
+ ! ascii_dump_mta_relay_cert(ep, fp) ||
+ ! ascii_dump_mta_relay_flags(ep, fp) ||
+ ! ascii_dump_mta_relay_as(ep, fp))
+ return 0;
+ break;
+
+ case D_BOUNCE:
+ /* nothing ! */
+ break;
+
+ default:
+ return 0;
+ }
+
+ return 1;
+}
+
+int
+fsqueue_load_envelope_ascii(FILE *fp, struct envelope *ep)
+{
+ char *buf, *lbuf;
+ size_t len;
+ struct ascii_load_handler {
+ char *kw;
+ int (*hdl)(struct envelope *, char *);
+ } ascii_load_handlers[] = {
+ { KW_VERSION, ascii_load_version },
+ { KW_EVPID, ascii_load_evpid },
+
+ { KW_HOSTNAME, ascii_load_hostname },
+ { KW_SOCKADDR, ascii_load_sockaddr },
+
+ { KW_HELO, ascii_load_helo },
+ { KW_SENDER, ascii_load_sender },
+ { KW_RCPT, ascii_load_rcpt },
+
+ { KW_TYPE, ascii_load_type },
+ { KW_DEST, ascii_load_dest },
+
+ { KW_CTIME, ascii_load_ctime },
+ { KW_EXPIRE, ascii_load_expire },
+ { KW_RETRY, ascii_load_retry },
+ { KW_LAST_TRY, ascii_load_lasttry },
+
+ { KW_FLAGS, ascii_load_flags },
+
+ { KW_ERRORLINE, ascii_load_errorline },
+
+ { KW_MDA_METHOD, ascii_load_mda_method },
+ { KW_MDA_BUFFER, ascii_load_mda_buffer },
+ { KW_MDA_USER, ascii_load_mda_user },
+
+ { KW_MTA_RELAY_HOST, ascii_load_mta_relay_host },
+ { KW_MTA_RELAY_PORT, ascii_load_mta_relay_port },
+ { KW_MTA_RELAY_FLAGS, ascii_load_mta_relay_flags },
+ { KW_MTA_RELAY_CERT, ascii_load_mta_relay_cert },
+ };
+ int i;
+ int n;
+ int ret;
+
+ n = sizeof(ascii_load_handlers) / sizeof(struct ascii_load_handler);
+
+ bzero(ep, sizeof (*ep));
+ lbuf = NULL;
+ while ((buf = fgetln(fp, &len))) {
+ if (buf[len - 1] == '\n')
+ buf[len - 1] = '\0';
+ else {
+ if ((lbuf = malloc(len + 1)) == NULL)
+ err(1, NULL);
+ memcpy(lbuf, buf, len);
+ lbuf[len] = '\0';
+ buf = lbuf;
+ }
+
+ for (i = 0; i < n; ++i) {
+ len = strlen(ascii_load_handlers[i].kw);
+ if (! strncasecmp(ascii_load_handlers[i].kw, buf, len)) {
+ /* skip kw and tailing whitespaces */
+ buf += len;
+ while (*buf && isspace(*buf))
+ buf++;
+
+ /* we *want* ':' */
+ if (*buf != ':')
+ continue;
+ buf++;
+
+ /* skip whitespaces after separator */
+ while (*buf && isspace(*buf))
+ buf++;
+
+ ret = ascii_load_handlers[i].hdl(ep, buf);
+ if (ret == 0) {
+ log_debug("### CHOKED ON: %s", buf);
+ goto err;
+ }
+ break;
+ }
+ }
+
+ /* unknown keyword */
+ if (i == n) {
+ log_debug("### CHOKED ON: %s", buf);
+ goto err;
+ }
+ }
+ free(lbuf);
+
+ return 1;
+
+err:
+ free(lbuf);
+ return 0;
+}
+
+int
+fsqueue_dump_envelope_ascii(FILE *fp, struct envelope *ep)
+{
+ if (! ascii_dump_version(ep, fp) ||
+ ! ascii_dump_evpid(ep, fp) ||
+ ! ascii_dump_agent(ep, fp) ||
+ ! ascii_dump_helo(ep, fp) ||
+ ! ascii_dump_hostname(ep, fp) ||
+ ! ascii_dump_errorline(ep, fp) ||
+ ! ascii_dump_sockaddr(ep, fp) ||
+ ! ascii_dump_sender(ep, fp) ||
+ ! ascii_dump_rcpt(ep, fp) ||
+ ! ascii_dump_dest(ep, fp) ||
+ ! ascii_dump_ctime(ep, fp) ||
+ ! ascii_dump_lasttry(ep, fp) ||
+ ! ascii_dump_expire(ep, fp) ||
+ ! ascii_dump_retry(ep, fp) ||
+ ! ascii_dump_flags(ep, fp) ||
+ ! ascii_dump_status(ep, fp))
+ goto err;
+
+ if (fflush(fp) != 0)
+ goto err;
+
+ return 1;
+
+err:
+ return 0;
+}
diff --git a/usr.sbin/smtpd/queue_shared.c b/usr.sbin/smtpd/queue_shared.c
index 726a63f6359..9b7a4b8e2ce 100644
--- a/usr.sbin/smtpd/queue_shared.c
+++ b/usr.sbin/smtpd/queue_shared.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: queue_shared.c,v 1.51 2011/08/29 21:43:09 chl Exp $ */
+/* $OpenBSD: queue_shared.c,v 1.52 2011/10/23 09:30:07 gilles Exp $ */
/*
* Copyright (c) 2008 Gilles Chehade <gilles@openbsd.org>
@@ -43,6 +43,8 @@
#define QWALK_RECURSE 0x2
#define QWALK_RETURN 0x3
+int fsqueue_load_envelope_ascii(FILE *, struct envelope *);
+
struct qwalk {
char path[MAXPATHLEN];
DIR *dirs[3];
@@ -65,20 +67,20 @@ bounce_record_message(struct envelope *e, struct envelope *bounce)
bzero(bounce, sizeof(*bounce));
- if (e->delivery.type == D_BOUNCE) {
+ if (e->type == D_BOUNCE) {
log_debug("mailer daemons loop detected !");
return 0;
}
*bounce = *e;
- bounce->delivery.type = D_BOUNCE;
- bounce->delivery.status &= ~DS_PERMFAILURE;
+ bounce->type = D_BOUNCE;
+ bounce->status &= ~DS_PERMFAILURE;
- msgid = evpid_to_msgid(e->delivery.id);
+ msgid = evpid_to_msgid(e->id);
if (! queue_message_create(Q_BOUNCE, &msgid))
return 0;
- bounce->delivery.id = msgid_to_evpid(msgid);
+ bounce->id = msgid_to_evpid(msgid);
if (! queue_envelope_create(Q_BOUNCE, bounce))
return 0;
@@ -89,14 +91,13 @@ void
queue_message_update(struct envelope *e)
{
e->batch_id = 0;
- e->delivery.flags &= ~DF_PROCESSING;
- e->delivery.status &= ~(DS_ACCEPTED|DS_REJECTED);
- e->delivery.retry++;
+ e->status &= ~(DS_ACCEPTED|DS_REJECTED);
+ e->retry++;
- if (e->delivery.status & DS_PERMFAILURE) {
- if (e->delivery.type != D_BOUNCE &&
- e->delivery.from.user[0] != '\0') {
+ if (e->status & DS_PERMFAILURE) {
+ if (e->type != D_BOUNCE &&
+ e->sender.user[0] != '\0') {
struct envelope bounce;
bounce_record_message(e, &bounce);
@@ -105,8 +106,8 @@ queue_message_update(struct envelope *e)
return;
}
- if (e->delivery.status & DS_TEMPFAILURE) {
- e->delivery.status &= ~DS_TEMPFAILURE;
+ if (e->status & DS_TEMPFAILURE) {
+ e->status &= ~DS_TEMPFAILURE;
queue_envelope_update(Q_QUEUE, e);
return;
}
@@ -230,13 +231,13 @@ walk_queue(struct qwalk *q, char *fname)
log_warnx("walk_queue: invalid bucket: %s", fname);
return (QWALK_AGAIN);
}
- if (! bsnprintf(q->path, sizeof(q->path), "%s/%04x", PATH_QUEUE,
- q->bucket))
+ if (! bsnprintf(q->path, sizeof(q->path), "%s/%03x", PATH_QUEUE,
+ q->bucket & 0xfff))
fatalx("walk_queue: snprintf");
return (QWALK_RECURSE);
case 1:
- if (! bsnprintf(q->path, sizeof(q->path), "%s/%04x/%s%s",
- PATH_QUEUE, q->bucket, fname, PATH_ENVELOPES))
+ if (! bsnprintf(q->path, sizeof(q->path), "%s/%03x/%s%s",
+ PATH_QUEUE, q->bucket & 0xfff, fname, PATH_ENVELOPES))
fatalx("walk_queue: snprintf");
return (QWALK_RECURSE);
case 2:
@@ -270,7 +271,7 @@ show_queue(char *queuepath, int flags)
}
errno = 0;
- if (fread(&message, sizeof(message), 1, fp) != 1)
+ if (! fsqueue_load_envelope_ascii(fp, &message))
err(1, "%s", path);
fclose(fp);
@@ -287,36 +288,32 @@ display_envelope(struct envelope *e, int flags)
status[0] = '\0';
- getflag(&e->delivery.status, DS_TEMPFAILURE, "TEMPFAIL",
+ getflag(&e->status, DS_TEMPFAILURE, "TEMPFAIL",
status, sizeof(status));
- if (e->delivery.status)
- errx(1, "%016llx: unexpected status 0x%04x", e->delivery.id,
- e->delivery.status);
+ if (e->status)
+ errx(1, "%016llx: unexpected status 0x%04x", e->id,
+ e->status);
- getflag(&e->delivery.flags, DF_BOUNCE, "BOUNCE",
- status, sizeof(status));
- getflag(&e->delivery.flags, DF_AUTHENTICATED, "AUTH",
- status, sizeof(status));
- getflag(&e->delivery.flags, DF_PROCESSING, "PROCESSING",
+ getflag(&e->flags, DF_BOUNCE, "BOUNCE",
status, sizeof(status));
- getflag(&e->delivery.flags, DF_SCHEDULED, "SCHEDULED",
+ getflag(&e->flags, DF_AUTHENTICATED, "AUTH",
status, sizeof(status));
- getflag(&e->delivery.flags, DF_ENQUEUED, "ENQUEUED",
+ getflag(&e->flags, DF_ENQUEUED, "ENQUEUED",
status, sizeof(status));
- getflag(&e->delivery.flags, DF_FORCESCHEDULE, "SCHEDULED_MANUAL",
+ getflag(&e->flags, DF_INTERNAL, "INTERNAL",
status, sizeof(status));
- if (e->delivery.flags)
- errx(1, "%016llx: unexpected flags 0x%04x", e->delivery.id,
- e->delivery.flags);
+ if (e->flags)
+ errx(1, "%016llx: unexpected flags 0x%04x", e->id,
+ e->flags);
if (status[0])
status[strlen(status) - 1] = '\0';
else
strlcpy(status, "-", sizeof(status));
- switch (e->delivery.type) {
+ switch (e->type) {
case D_MDA:
printf("MDA");
break;
@@ -331,16 +328,16 @@ display_envelope(struct envelope *e, int flags)
}
printf("|%016llx|%s|%s@%s|%s@%s|%lld|%lld|%u",
- e->delivery.id,
+ e->id,
status,
- e->delivery.from.user, e->delivery.from.domain,
- e->delivery.rcpt.user, e->delivery.rcpt.domain,
- (long long int) e->delivery.lasttry,
- (long long int) e->delivery.expire,
- e->delivery.retry);
+ e->sender.user, e->sender.domain,
+ e->dest.user, e->dest.domain,
+ (long long int) e->lasttry,
+ (long long int) e->expire,
+ e->retry);
- if (e->delivery.errorline[0] != '\0')
- printf("|%s", e->delivery.errorline);
+ if (e->errorline[0] != '\0')
+ printf("|%s", e->errorline);
printf("\n");
}
diff --git a/usr.sbin/smtpd/ramqueue.c b/usr.sbin/smtpd/ramqueue.c
index 2762df5ff36..aba38b5560f 100644
--- a/usr.sbin/smtpd/ramqueue.c
+++ b/usr.sbin/smtpd/ramqueue.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ramqueue.c,v 1.19 2011/09/18 21:37:53 gilles Exp $ */
+/* $OpenBSD: ramqueue.c,v 1.20 2011/10/23 09:30:07 gilles Exp $ */
/*
* Copyright (c) 2011 Gilles Chehade <gilles@openbsd.org>
@@ -181,7 +181,7 @@ ramqueue_insert(struct ramqueue *rqueue, struct envelope *envelope, time_t curtm
struct ramqueue_envelope *evp;
struct ramqueue_message *rq_msg, msgkey;
- msgkey.msgid = evpid_to_msgid(envelope->delivery.id);
+ msgkey.msgid = evpid_to_msgid(envelope->id);
rq_msg = RB_FIND(msgtree, &rqueue->msgtree, &msgkey);
if (rq_msg == NULL) {
rq_msg = calloc(1, sizeof (*rq_msg));
@@ -196,9 +196,9 @@ ramqueue_insert(struct ramqueue *rqueue, struct envelope *envelope, time_t curtm
rq_evp = calloc(1, sizeof (*rq_evp));
if (rq_evp == NULL)
fatal("calloc");
- rq_evp->evpid = envelope->delivery.id;
+ rq_evp->evpid = envelope->id;
rq_evp->sched = ramqueue_next_schedule(envelope, curtm);
- rq_evp->rq_host = ramqueue_get_host(rqueue, envelope->delivery.rcpt.domain);
+ rq_evp->rq_host = ramqueue_get_host(rqueue, envelope->dest.domain);
rq_evp->rq_batch = ramqueue_get_batch(rqueue, rq_evp->rq_host, envelope);
RB_INSERT(evptree, &rq_msg->evptree, rq_evp);
rq_evp->rq_msg = rq_msg;
@@ -224,12 +224,14 @@ ramqueue_expire(struct envelope *envelope, time_t curtm)
{
struct envelope bounce;
- if (curtm - envelope->delivery.creation >= envelope->delivery.expire) {
+ if (curtm - envelope->creation >= envelope->expire) {
envelope_set_errormsg(envelope,
"message expired after sitting in queue for %d days",
- envelope->delivery.expire / 60 / 60 / 24);
+ envelope->expire / 60 / 60 / 24);
bounce_record_message(envelope, &bounce);
ramqueue_insert(&env->sc_rqueue, &bounce, time(NULL));
+ log_debug("#### %s: queue_envelope_delete: %016llx",
+ __func__, envelope->id);
queue_envelope_delete(Q_QUEUE, envelope);
return 1;
}
@@ -241,31 +243,31 @@ ramqueue_next_schedule(struct envelope *envelope, time_t curtm)
{
time_t delay;
- if (envelope->delivery.lasttry == 0)
+ if (envelope->lasttry == 0)
return curtm;
delay = SMTPD_QUEUE_MAXINTERVAL;
- if (envelope->delivery.type == D_MDA ||
- envelope->delivery.type == D_BOUNCE) {
- if (envelope->delivery.retry < 5)
+ if (envelope->type == D_MDA ||
+ envelope->type == D_BOUNCE) {
+ if (envelope->retry < 5)
return curtm;
- if (envelope->delivery.retry < 15)
- delay = (envelope->delivery.retry * 60) + arc4random_uniform(60);
+ if (envelope->retry < 15)
+ delay = (envelope->retry * 60) + arc4random_uniform(60);
}
- if (envelope->delivery.type == D_MTA) {
- if (envelope->delivery.retry < 3)
+ if (envelope->type == D_MTA) {
+ if (envelope->retry < 3)
delay = SMTPD_QUEUE_INTERVAL;
- else if (envelope->delivery.retry <= 7) {
- delay = SMTPD_QUEUE_INTERVAL * (1 << (envelope->delivery.retry - 3));
+ else if (envelope->retry <= 7) {
+ delay = SMTPD_QUEUE_INTERVAL * (1 << (envelope->retry - 3));
if (delay > SMTPD_QUEUE_MAXINTERVAL)
delay = SMTPD_QUEUE_MAXINTERVAL;
}
}
- if (curtm >= envelope->delivery.lasttry + delay)
+ if (curtm >= envelope->lasttry + delay)
return curtm;
return curtm + delay;
@@ -306,7 +308,7 @@ ramqueue_get_batch(struct ramqueue *rqueue, struct ramqueue_host *host,
struct ramqueue_batch *rq_batch;
TAILQ_FOREACH(rq_batch, &host->batch_queue, batch_entry) {
- if (rq_batch->msgid == (u_int32_t)(envelope->delivery.id >> 32))
+ if (rq_batch->msgid == evpid_to_msgid(envelope->id))
return rq_batch;
}
@@ -315,8 +317,8 @@ ramqueue_get_batch(struct ramqueue *rqueue, struct ramqueue_host *host,
fatal("calloc");
rq_batch->b_id = generate_uid();
rq_batch->rule = envelope->rule;
- rq_batch->type = envelope->delivery.type;
- rq_batch->msgid = envelope->delivery.id >> 32;
+ rq_batch->type = envelope->type;
+ rq_batch->msgid = evpid_to_msgid(envelope->id);
TAILQ_INIT(&rq_batch->envelope_queue);
TAILQ_INSERT_TAIL(&host->batch_queue, rq_batch, batch_entry);
diff --git a/usr.sbin/smtpd/ruleset.c b/usr.sbin/smtpd/ruleset.c
index b8a214085e6..c5a9b68cff0 100644
--- a/usr.sbin/smtpd/ruleset.c
+++ b/usr.sbin/smtpd/ruleset.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ruleset.c,v 1.19 2011/05/21 18:39:03 gilles Exp $ */
+/* $OpenBSD: ruleset.c,v 1.20 2011/10/23 09:30:07 gilles Exp $ */
/*
* Copyright (c) 2009 Gilles Chehade <gilles@openbsd.org>
@@ -47,10 +47,10 @@ ruleset_match(struct envelope *evp)
struct rule *r;
struct map *map;
struct mapel *me;
- struct mailaddr *maddr = &evp->delivery.rcpt;
- struct sockaddr_storage *ss = &evp->delivery.ss;
+ struct mailaddr *maddr = &evp->dest;
+ struct sockaddr_storage *ss = &evp->ss;
- if (evp->delivery.flags & DF_INTERNAL)
+ if (evp->flags & DF_INTERNAL)
ss = NULL;
TAILQ_FOREACH(r, env->sc_rules, r_entry) {
@@ -59,7 +59,7 @@ ruleset_match(struct envelope *evp)
continue;
if (ss != NULL &&
- (!(evp->delivery.flags & DF_AUTHENTICATED) &&
+ (!(evp->flags & DF_AUTHENTICATED) &&
! ruleset_check_source(r->r_sources, ss)))
continue;
diff --git a/usr.sbin/smtpd/runner.c b/usr.sbin/smtpd/runner.c
index 33f9b7f6af9..6c7d5c70717 100644
--- a/usr.sbin/smtpd/runner.c
+++ b/usr.sbin/smtpd/runner.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: runner.c,v 1.119 2011/10/09 18:39:53 eric Exp $ */
+/* $OpenBSD: runner.c,v 1.120 2011/10/23 09:30:07 gilles Exp $ */
/*
* Copyright (c) 2008 Gilles Chehade <gilles@openbsd.org>
@@ -60,7 +60,6 @@ static int runner_force_message_to_ramqueue(struct ramqueue *, u_int32_t);
/*temporary*/
-u_int16_t fsqueue_hash(u_int32_t);
u_int64_t filename_to_evpid(char *);
u_int32_t filename_to_msgid(char *);
@@ -75,20 +74,22 @@ runner_imsg(struct imsgev *iev, struct imsg *imsg)
switch (imsg->hdr.type) {
case IMSG_QUEUE_COMMIT_MESSAGE:
e = imsg->data;
- runner_force_message_to_ramqueue(&env->sc_rqueue, e->delivery.id>>32);
+ runner_force_message_to_ramqueue(&env->sc_rqueue,
+ evpid_to_msgid(e->id));
runner_reset_events();
return;
case IMSG_QUEUE_MESSAGE_UPDATE:
e = imsg->data;
- e->delivery.retry++;
+ e->retry++;
stat_decrement(STATS_RUNNER);
/* temporary failure, message remains in queue,
* gets reinserted in ramqueue
*/
- if (e->delivery.status & DS_TEMPFAILURE) {
- e->delivery.status &= ~DS_TEMPFAILURE;
+ if (e->status & DS_TEMPFAILURE) {
+ log_debug("TEMPFAIL: %016llx", e->id);
+ e->status &= ~DS_TEMPFAILURE;
queue_envelope_update(Q_QUEUE, e);
ramqueue_insert(&env->sc_rqueue, e, time(NULL));
runner_reset_events();
@@ -98,11 +99,12 @@ runner_imsg(struct imsgev *iev, struct imsg *imsg)
/* permanent failure, eventually generate a
* bounce (and insert bounce in ramqueue).
*/
- if (e->delivery.status & DS_PERMFAILURE) {
+ if (e->status & DS_PERMFAILURE) {
struct envelope bounce;
-
- if (e->delivery.type != D_BOUNCE &&
- e->delivery.from.user[0] != '\0') {
+ log_debug("PERMFAIL: %016llx", e->id);
+ if (e->type != D_BOUNCE &&
+ e->sender.user[0] != '\0') {
+ log_debug("PERMFAIL #2: %016llx", e->id);
bounce_record_message(e, &bounce);
ramqueue_insert(&env->sc_rqueue, &bounce, time(NULL));
runner_reset_events();
@@ -112,6 +114,8 @@ runner_imsg(struct imsgev *iev, struct imsg *imsg)
/* successful delivery or permanent failure,
* remove envelope from queue.
*/
+ log_debug("#### %s: queue_envelope_delete: %016llx",
+ __func__, e->id);
queue_envelope_delete(Q_QUEUE, e);
return;
@@ -130,7 +134,7 @@ runner_imsg(struct imsgev *iev, struct imsg *imsg)
case IMSG_SMTP_ENQUEUE:
e = imsg->data;
if (imsg->fd < 0 || !bounce_session(imsg->fd, e)) {
- e->delivery.status = 0;
+ e->status = 0;
queue_envelope_update(Q_QUEUE, e);
ramqueue_insert(&env->sc_rqueue, e, time(NULL));
runner_reset_events();
@@ -371,21 +375,21 @@ runner_process_envelope(struct ramqueue_envelope *rq_evp, time_t curtm)
if (! queue_envelope_load(Q_QUEUE, rq_evp->evpid, &envelope))
return 0;
- if (envelope.delivery.type & D_MDA) {
+ if (envelope.type & D_MDA) {
if (env->sc_opts & SMTPD_MDA_PAUSED)
return 0;
if (mda_av == 0)
return 0;
}
- if (envelope.delivery.type & D_MTA) {
+ if (envelope.type & D_MTA) {
if (env->sc_opts & SMTPD_MTA_PAUSED)
return 0;
if (mta_av == 0)
return 0;
}
- if (envelope.delivery.type & D_BOUNCE) {
+ if (envelope.type & D_BOUNCE) {
if (env->sc_opts & (SMTPD_MDA_PAUSED|SMTPD_MTA_PAUSED))
return 0;
if (bnc_av == 0)
@@ -399,6 +403,8 @@ runner_process_envelope(struct ramqueue_envelope *rq_evp, time_t curtm)
bounce_record_message(&envelope, &bounce);
ramqueue_insert(&env->sc_rqueue, &bounce, time(NULL));
runner_setup_events();
+ log_debug("#### %s: queue_envelope_delete: %016llx",
+ __func__, envelope.id);
queue_envelope_delete(Q_QUEUE, &envelope);
return 0;
}
@@ -428,7 +434,7 @@ runner_process_batch(struct ramqueue_envelope *rq_evp, time_t curtm)
if (! queue_envelope_load(Q_QUEUE, rq_evp->evpid,
&evp))
return;
- evp.delivery.lasttry = curtm;
+ evp.lasttry = curtm;
imsg_compose_event(env->sc_ievs[PROC_QUEUE],
IMSG_SMTP_ENQUEUE, PROC_SMTP, 0, -1, &evp,
sizeof evp);
@@ -444,8 +450,9 @@ runner_process_batch(struct ramqueue_envelope *rq_evp, time_t curtm)
rq_evp = ramqueue_batch_first_envelope(rq_batch);
if (! queue_envelope_load(Q_QUEUE, rq_evp->evpid, &evp))
return;
- evp.delivery.lasttry = curtm;
- fd = queue_message_fd_r(Q_QUEUE, rq_evp->evpid>>32);
+ evp.lasttry = curtm;
+ fd = queue_message_fd_r(Q_QUEUE,
+ evpid_to_msgid(rq_evp->evpid));
imsg_compose_event(env->sc_ievs[PROC_QUEUE],
IMSG_MDA_SESS_NEW, PROC_MDA, 0, fd, &evp,
sizeof evp);
@@ -464,7 +471,7 @@ runner_process_batch(struct ramqueue_envelope *rq_evp, time_t curtm)
if (! queue_envelope_load(Q_QUEUE, rq_evp->evpid,
&evp))
return;
- evp.delivery.lasttry = curtm;
+ evp.lasttry = curtm;
evp.batch_id = rq_batch->b_id;
imsg_compose_event(env->sc_ievs[PROC_QUEUE],
IMSG_BATCH_APPEND, PROC_MTA, 0, -1, &evp,
@@ -503,8 +510,8 @@ runner_force_message_to_ramqueue(struct ramqueue *rqueue, u_int32_t msgid)
struct envelope envelope;
time_t curtm;
- if (! bsnprintf(path, MAXPATHLEN, "%s/%04x/%08x/envelopes",
- PATH_QUEUE, fsqueue_hash(msgid), msgid))
+ if (! bsnprintf(path, MAXPATHLEN, "%s/%03x/%08x/envelopes",
+ PATH_QUEUE, msgid & 0xfff, msgid))
return 0;
dirp = opendir(path);
@@ -624,7 +631,8 @@ runner_check_loop(struct envelope *ep)
int ret = 0;
int rcvcount = 0;
- fd = queue_message_fd_r(Q_QUEUE, ep->delivery.id>>32);
+ fd = queue_message_fd_r(Q_QUEUE,
+ evpid_to_msgid(ep->id));
if ((fp = fdopen(fd, "r")) == NULL)
fatal("fdopen");
@@ -653,18 +661,18 @@ runner_check_loop(struct envelope *ep)
}
else if (strncasecmp("Delivered-To: ", buf, 14) == 0) {
- struct mailaddr rcpt;
+ struct mailaddr dest;
bzero(&maddr, sizeof (struct mailaddr));
if (! email_to_mailaddr(&maddr, buf + 14))
continue;
+
+ dest = ep->dest;
+ if (ep->type == D_BOUNCE)
+ dest = ep->sender;
- rcpt = ep->delivery.rcpt;
- if (ep->delivery.type == D_BOUNCE)
- rcpt = ep->delivery.from;
-
- if (strcasecmp(maddr.user, rcpt.user) == 0 &&
- strcasecmp(maddr.domain, rcpt.domain) == 0) {
+ if (strcasecmp(maddr.user, dest.user) == 0 &&
+ strcasecmp(maddr.domain, dest.domain) == 0) {
ret = 1;
break;
}
@@ -713,8 +721,11 @@ runner_remove_envelope(struct ramqueue *rq, struct ramqueue_envelope *rq_evp)
{
struct envelope evp;
- if (queue_envelope_load(Q_QUEUE, rq_evp->evpid, &evp))
+ if (queue_envelope_load(Q_QUEUE, rq_evp->evpid, &evp)) {
+ log_debug("#### %s: queue_envelope_delete: %016llx",
+ __func__, evp.id);
queue_envelope_delete(Q_QUEUE, &evp);
+ }
ramqueue_remove_envelope(rq, rq_evp);
}
diff --git a/usr.sbin/smtpd/smtp.c b/usr.sbin/smtpd/smtp.c
index 8ea6d9465ec..b3d9e9a21e5 100644
--- a/usr.sbin/smtpd/smtp.c
+++ b/usr.sbin/smtpd/smtp.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: smtp.c,v 1.92 2011/10/09 18:39:54 eric Exp $ */
+/* $OpenBSD: smtp.c,v 1.93 2011/10/23 09:30:07 gilles Exp $ */
/*
* Copyright (c) 2008 Gilles Chehade <gilles@openbsd.org>
@@ -73,8 +73,8 @@ smtp_imsg(struct imsgev *iev, struct imsg *imsg)
strlcpy(s->s_hostname,
dns->error ? "<unknown>" : dns->host,
sizeof s->s_hostname);
- strlcpy(s->s_msg.delivery.hostname, s->s_hostname,
- sizeof s->s_msg.delivery.hostname);
+ strlcpy(s->s_msg.hostname, s->s_hostname,
+ sizeof s->s_msg.hostname);
session_init(s->s_l, s);
return;
}
@@ -103,7 +103,7 @@ smtp_imsg(struct imsgev *iev, struct imsg *imsg)
s = session_lookup(ss->id);
if (s == NULL)
return;
- s->s_msg.delivery.id = (u_int64_t)ss->u.msgid << 32;
+ s->s_msg.id = ((u_int64_t)ss->u.msgid) << 32;
session_pickup(s, ss);
return;
@@ -130,7 +130,7 @@ smtp_imsg(struct imsgev *iev, struct imsg *imsg)
fatalx("smtp: session is gone");
if (s->s_flags & F_WRITEONLY)
/* session is write-only, must not destroy it. */
- s->s_msg.delivery.status |= DS_TEMPFAILURE;
+ s->s_msg.status |= DS_TEMPFAILURE;
else
fatalx("smtp: corrupt session");
return;
@@ -167,7 +167,7 @@ smtp_imsg(struct imsgev *iev, struct imsg *imsg)
*/
SPLAY_FOREACH(s, sessiontree, &env->sc_sessions) {
s->s_l = NULL;
- s->s_msg.delivery.status |= DS_TEMPFAILURE;
+ s->s_msg.status |= DS_TEMPFAILURE;
}
if (env->sc_listeners)
smtp_disable_events();
@@ -247,10 +247,10 @@ smtp_imsg(struct imsgev *iev, struct imsg *imsg)
return;
if (auth->success) {
s->s_flags |= F_AUTHENTICATED;
- s->s_msg.delivery.flags |= DF_AUTHENTICATED;
+ s->s_msg.flags |= DF_AUTHENTICATED;
} else {
s->s_flags &= ~F_AUTHENTICATED;
- s->s_msg.delivery.flags &= ~DF_AUTHENTICATED;
+ s->s_msg.flags &= ~DF_AUTHENTICATED;
}
session_pickup(s, NULL);
return;
@@ -478,18 +478,18 @@ smtp_enqueue(uid_t *euid)
s->s_fd = fd[0];
s->s_ss = sa;
- s->s_msg.delivery.flags |= DF_ENQUEUED;
+ s->s_msg.flags |= DF_ENQUEUED;
if (euid)
bsnprintf(s->s_hostname, sizeof(s->s_hostname), "%d@localhost",
*euid);
else {
strlcpy(s->s_hostname, "localhost", sizeof(s->s_hostname));
- s->s_msg.delivery.flags |= DF_BOUNCE;
+ s->s_msg.flags |= DF_BOUNCE;
}
- strlcpy(s->s_msg.delivery.hostname, s->s_hostname,
- sizeof(s->s_msg.delivery.hostname));
+ strlcpy(s->s_msg.hostname, s->s_hostname,
+ sizeof(s->s_msg.hostname));
session_init(l, s);
diff --git a/usr.sbin/smtpd/smtp_session.c b/usr.sbin/smtpd/smtp_session.c
index 3c75142b8e2..a4386a11b3a 100644
--- a/usr.sbin/smtpd/smtp_session.c
+++ b/usr.sbin/smtpd/smtp_session.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: smtp_session.c,v 1.149 2011/10/03 19:20:51 gilles Exp $ */
+/* $OpenBSD: smtp_session.c,v 1.150 2011/10/23 09:30:07 gilles Exp $ */
/*
* Copyright (c) 2008 Gilles Chehade <gilles@openbsd.org>
@@ -323,8 +323,8 @@ session_rfc5321_helo_handler(struct session *s, char *args)
return 1;
}
- if (strlcpy(s->s_msg.delivery.helo, args, sizeof(s->s_msg.delivery.helo))
- >= sizeof(s->s_msg.delivery.helo)) {
+ if (strlcpy(s->s_msg.helo, args, sizeof(s->s_msg.helo))
+ >= sizeof(s->s_msg.helo)) {
session_respond(s, "501 Invalid domain name");
return 1;
}
@@ -346,8 +346,8 @@ session_rfc5321_ehlo_handler(struct session *s, char *args)
return 1;
}
- if (strlcpy(s->s_msg.delivery.helo, args, sizeof(s->s_msg.delivery.helo))
- >= sizeof(s->s_msg.delivery.helo)) {
+ if (strlcpy(s->s_msg.helo, args, sizeof(s->s_msg.helo))
+ >= sizeof(s->s_msg.helo)) {
session_respond(s, "501 Invalid domain name");
return 1;
}
@@ -393,7 +393,7 @@ session_rfc5321_mail_handler(struct session *s, char *args)
return 1;
}
- if (! session_set_mailaddr(&s->s_msg.delivery.from, args)) {
+ if (! session_set_mailaddr(&s->s_msg.sender, args)) {
/* No need to even transmit to MFA, path is invalid */
session_respond(s, "553 5.1.7 Sender address syntax error");
return 1;
@@ -401,8 +401,8 @@ session_rfc5321_mail_handler(struct session *s, char *args)
s->rcptcount = 0;
s->s_state = S_MAIL_MFA;
- s->s_msg.delivery.id = 0;
- s->s_msg.delivery.ss = s->s_ss;
+ s->s_msg.id = 0;
+ s->s_msg.ss = s->s_ss;
log_debug("session_rfc5321_mail_handler: sending notification to mfa");
@@ -424,7 +424,7 @@ session_rfc5321_rcpt_handler(struct session *s, char *args)
return 1;
}
- if (! session_set_mailaddr(&s->s_msg.delivery.rcpt_orig, args)) {
+ if (! session_set_mailaddr(&s->s_msg.rcpt, args)) {
/* No need to even transmit to MFA, path is invalid */
session_respond(s, "553 5.1.3 Recipient address syntax error");
return 1;
@@ -582,7 +582,7 @@ session_pickup(struct session *s, struct submit_status *ss)
fatal("session_pickup: desynchronized");
if ((ss != NULL && ss->code == 421) ||
- (s->s_msg.delivery.status & DS_TEMPFAILURE)) {
+ (s->s_msg.status & DS_TEMPFAILURE)) {
session_respond(s, "421 Service temporarily unavailable");
env->stats->smtp.tempfail++;
s->s_flags |= F_QUIT;
@@ -622,7 +622,7 @@ session_pickup(struct session *s, struct submit_status *ss)
session_respond(s, "250%c%s Hello %s [%s], pleased to meet you",
(s->s_flags & F_EHLO) ? '-' : ' ',
- env->sc_hostname, s->s_msg.delivery.helo, ss_to_text(&s->s_ss));
+ env->sc_hostname, s->s_msg.helo, ss_to_text(&s->s_ss));
if (s->s_flags & F_EHLO) {
/* unconditionnal extensions go first */
@@ -651,7 +651,7 @@ session_pickup(struct session *s, struct submit_status *ss)
}
s->s_state = S_MAIL_QUEUE;
- s->s_msg.delivery.from = ss->u.maddr;
+ s->s_msg.sender = ss->u.maddr;
session_imsg(s, PROC_QUEUE, IMSG_QUEUE_CREATE_MESSAGE, 0, 0, -1,
&s->s_msg, sizeof(s->s_msg));
@@ -675,14 +675,14 @@ session_pickup(struct session *s, struct submit_status *ss)
else
s->s_state = S_RCPT;
session_respond(s, "%d 5.0.0 Recipient rejected: %s@%s", ss->code,
- s->s_msg.delivery.rcpt_orig.user,
- s->s_msg.delivery.rcpt_orig.domain);
+ s->s_msg.rcpt.user,
+ s->s_msg.rcpt.domain);
return;
}
s->s_state = S_RCPT;
s->rcptcount++;
- s->s_msg.delivery.rcpt = ss->u.maddr;
+ s->s_msg.dest = ss->u.maddr;
session_respond(s, "%d 2.0.0 Recipient ok", ss->code);
break;
@@ -693,10 +693,10 @@ session_pickup(struct session *s, struct submit_status *ss)
" itself");
fprintf(s->datafp, "Received: from %s (%s [%s])\n",
- s->s_msg.delivery.helo, s->s_hostname, ss_to_text(&s->s_ss));
+ s->s_msg.helo, s->s_hostname, ss_to_text(&s->s_ss));
fprintf(s->datafp, "\tby %s (OpenSMTPD) with %sSMTP id %08x",
env->sc_hostname, s->s_flags & F_EHLO ? "E" : "",
- (u_int32_t)(s->s_msg.delivery.id >> 32));
+ evpid_to_msgid(s->s_msg.id));
if (s->s_flags & F_SECURE) {
fprintf(s->datafp, "\n\t(version=%s cipher=%s bits=%d)",
@@ -706,8 +706,8 @@ session_pickup(struct session *s, struct submit_status *ss)
}
if (s->rcptcount == 1)
fprintf(s->datafp, "\n\tfor <%s@%s>; ",
- s->s_msg.delivery.rcpt_orig.user,
- s->s_msg.delivery.rcpt_orig.domain);
+ s->s_msg.rcpt.user,
+ s->s_msg.rcpt.domain);
else
fprintf(s->datafp, ";\n\t");
@@ -716,19 +716,19 @@ session_pickup(struct session *s, struct submit_status *ss)
case S_DATACONTENT:
if (ss->code != 250)
- s->s_msg.delivery.status |= DS_PERMFAILURE;
+ s->s_msg.status |= DS_PERMFAILURE;
session_read_data(s, ss->u.dataline);
break;
case S_DONE:
session_respond(s, "250 2.0.0 %08x Message accepted for delivery",
- (u_int32_t)(s->s_msg.delivery.id >> 32));
+ evpid_to_msgid(s->s_msg.id));
log_info("%08x: from=<%s%s%s>, size=%ld, nrcpts=%zd, proto=%s, "
"relay=%s [%s]",
- (u_int32_t)(s->s_msg.delivery.id >> 32),
- s->s_msg.delivery.from.user,
- s->s_msg.delivery.from.user[0] == '\0' ? "" : "@",
- s->s_msg.delivery.from.domain,
+ evpid_to_msgid(s->s_msg.id),
+ s->s_msg.sender.user,
+ s->s_msg.sender.user[0] == '\0' ? "" : "@",
+ s->s_msg.sender.domain,
s->s_datalen,
s->rcptcount,
s->s_flags & F_EHLO ? "ESMTP" : "SMTP",
@@ -736,7 +736,7 @@ session_pickup(struct session *s, struct submit_status *ss)
ss_to_text(&s->s_ss));
s->s_state = S_HELO;
- s->s_msg.delivery.id = 0;
+ s->s_msg.id = 0;
bzero(&s->s_nresp, sizeof(s->s_nresp));
break;
@@ -791,14 +791,14 @@ session_read(struct bufferevent *bev, void *p)
switch (s->s_state) {
case S_AUTH_INIT:
- if (s->s_msg.delivery.status & DS_TEMPFAILURE)
+ if (s->s_msg.status & DS_TEMPFAILURE)
goto tempfail;
session_rfc4954_auth_plain(s, line);
break;
case S_AUTH_USERNAME:
case S_AUTH_PASSWORD:
- if (s->s_msg.delivery.status & DS_TEMPFAILURE)
+ if (s->s_msg.status & DS_TEMPFAILURE)
goto tempfail;
session_rfc4954_auth_login(s, line);
break;
@@ -807,7 +807,7 @@ session_read(struct bufferevent *bev, void *p)
case S_HELO:
case S_MAIL:
case S_RCPT:
- if (s->s_msg.delivery.status & DS_TEMPFAILURE)
+ if (s->s_msg.status & DS_TEMPFAILURE)
goto tempfail;
session_command(s, line);
break;
@@ -864,13 +864,13 @@ session_read_data(struct session *s, char *line)
if (strcmp(line, ".") == 0) {
s->s_datalen = ftell(s->datafp);
if (! safe_fclose(s->datafp))
- s->s_msg.delivery.status |= DS_TEMPFAILURE;
+ s->s_msg.status |= DS_TEMPFAILURE;
s->datafp = NULL;
- if (s->s_msg.delivery.status & DS_PERMFAILURE) {
+ if (s->s_msg.status & DS_PERMFAILURE) {
session_respond(s, "554 5.0.0 Transaction failed");
s->s_state = S_HELO;
- } else if (s->s_msg.delivery.status & DS_TEMPFAILURE) {
+ } else if (s->s_msg.status & DS_TEMPFAILURE) {
session_respond(s, "421 4.0.0 Temporary failure");
s->s_flags |= F_QUIT;
env->stats->smtp.tempfail++;
@@ -883,7 +883,7 @@ session_read_data(struct session *s, char *line)
}
/* Don't waste resources on message if it's going to bin anyway. */
- if (s->s_msg.delivery.status & (DS_PERMFAILURE|DS_TEMPFAILURE))
+ if (s->s_msg.status & (DS_PERMFAILURE|DS_TEMPFAILURE))
goto end;
/* "If the first character is a period and there are other characters
@@ -900,12 +900,12 @@ session_read_data(struct session *s, char *line)
datalen = ftell(s->datafp);
if (SIZE_MAX - datalen < len + 1 ||
datalen + len + 1 > env->sc_maxsize) {
- s->s_msg.delivery.status |= DS_PERMFAILURE;
+ s->s_msg.status |= DS_PERMFAILURE;
goto end;
}
if (fprintf(s->datafp, "%s\n", line) != (int)len + 1) {
- s->s_msg.delivery.status |= DS_TEMPFAILURE;
+ s->s_msg.status |= DS_TEMPFAILURE;
goto end;
}
@@ -1016,7 +1016,7 @@ session_destroy(struct session *s)
if (s->datafp != NULL)
fclose(s->datafp);
- if (s->s_msg.delivery.id != 0 && s->s_state != S_DONE)
+ if (s->s_msg.id != 0 && s->s_state != S_DONE)
imsg_compose_event(env->sc_ievs[PROC_QUEUE],
IMSG_QUEUE_REMOVE_MESSAGE, 0, 0, -1, &s->s_msg,
sizeof(s->s_msg));
@@ -1135,8 +1135,8 @@ session_respond(struct session *s, char *fmt, ...)
case '5':
case '4':
log_info("%08x: from=<%s@%s>, relay=%s [%s], stat=LocalError (%.*s)",
- (u_int32_t)(s->s_msg.delivery.id >> 32),
- s->s_msg.delivery.from.user, s->s_msg.delivery.from.domain,
+ evpid_to_msgid(s->s_msg.id),
+ s->s_msg.sender.user, s->s_msg.sender.domain,
s->s_hostname, ss_to_text(&s->s_ss),
(int)EVBUFFER_LENGTH(EVBUFFER_OUTPUT(s->s_bev)) - n - 2,
EVBUFFER_DATA(EVBUFFER_OUTPUT(s->s_bev)));
diff --git a/usr.sbin/smtpd/smtpctl.c b/usr.sbin/smtpd/smtpctl.c
index a417dfa6a47..3c97118d018 100644
--- a/usr.sbin/smtpd/smtpctl.c
+++ b/usr.sbin/smtpd/smtpctl.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: smtpctl.c,v 1.67 2011/09/01 19:56:49 eric Exp $ */
+/* $OpenBSD: smtpctl.c,v 1.68 2011/10/23 09:30:07 gilles Exp $ */
/*
* Copyright (c) 2006 Pierre-Yves Ritschard <pyr@openbsd.org>
@@ -285,7 +285,6 @@ show_sizes(void)
printf("struct ramqueue_envelope: %zu\n", sizeof (struct ramqueue_envelope));
printf("struct envelope: %zu\n", sizeof (struct envelope));
- printf("struct delivery: %zu\n", sizeof (struct delivery));
}
static void
diff --git a/usr.sbin/smtpd/smtpctl/Makefile b/usr.sbin/smtpd/smtpctl/Makefile
index 9b3f4576c24..948b2d32578 100644
--- a/usr.sbin/smtpd/smtpctl/Makefile
+++ b/usr.sbin/smtpd/smtpctl/Makefile
@@ -1,4 +1,4 @@
-# $OpenBSD: Makefile,v 1.18 2011/09/01 19:56:49 eric Exp $
+# $OpenBSD: Makefile,v 1.19 2011/10/23 09:30:07 gilles Exp $
.PATH: ${.CURDIR}/..
@@ -17,7 +17,7 @@ CFLAGS+= -Wshadow -Wpointer-arith -Wcast-qual
CFLAGS+= -Wsign-compare -Wbounded
CFLAGS+= -DCLIENT_NO_SSL
-SRCS= smtpctl.c parser.c log.c enqueue.c queue_shared.c util.c client.c queue_backend.c queue_fsqueue.c stats.c
+SRCS= smtpctl.c parser.c log.c enqueue.c queue_shared.c util.c client.c queue_backend.c queue_fsqueue.c queue_fsqueue_ascii.c stats.c
LDADD+= -lutil -levent
DPADD+= ${LIBUTIL} ${LIBEVENT}
.include <bsd.prog.mk>
diff --git a/usr.sbin/smtpd/smtpd.h b/usr.sbin/smtpd/smtpd.h
index af037c663fc..0824231361a 100644
--- a/usr.sbin/smtpd/smtpd.h
+++ b/usr.sbin/smtpd/smtpd.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: smtpd.h,v 1.242 2011/10/22 00:16:34 eric Exp $ */
+/* $OpenBSD: smtpd.h,v 1.243 2011/10/23 09:30:07 gilles Exp $ */
/*
* Copyright (c) 2008 Gilles Chehade <gilles@openbsd.org>
@@ -355,21 +355,14 @@ enum delivery_status {
DS_PERMFAILURE = 0x2,
DS_TEMPFAILURE = 0x4,
DS_REJECTED = 0x8,
- DS_ACCEPTED = 0x10,
- DS_RETRY = 0x20,
- DS_EDNS = 0x40,
- DS_ECONNECT = 0x80
+ DS_ACCEPTED = 0x10
};
enum delivery_flags {
- DF_RESOLVED = 0x1,
- DF_SCHEDULED = 0x2,
- DF_PROCESSING = 0x4,
- DF_AUTHENTICATED = 0x8,
- DF_ENQUEUED = 0x10,
- DF_FORCESCHEDULE = 0x20,
- DF_BOUNCE = 0x40,
- DF_INTERNAL = 0x80 /* internal expansion forward */
+ DF_AUTHENTICATED = 0x1,
+ DF_ENQUEUED = 0x2,
+ DF_BOUNCE = 0x4,
+ DF_INTERNAL = 0x8 /* internal expansion forward */
};
union delivery_data {
@@ -389,32 +382,6 @@ struct delivery_mta {
struct mailaddr relay_as;
};
-struct delivery {
- u_int64_t id;
- enum delivery_type type;
-
- char helo[MAXHOSTNAMELEN];
- char hostname[MAXHOSTNAMELEN];
- char errorline[MAX_LINE_SIZE + 1];
- struct sockaddr_storage ss;
-
- struct mailaddr from;
- struct mailaddr rcpt;
- struct mailaddr rcpt_orig;
-
- union delivery_method {
- struct delivery_mda mda;
- struct delivery_mta mta;
- } agent;
-
- time_t creation;
- time_t lasttry;
- time_t expire;
- u_int8_t retry;
- enum delivery_flags flags;
- enum delivery_status status;
-};
-
enum expand_type {
EXPAND_INVALID,
EXPAND_USERNAME,
@@ -440,7 +407,7 @@ struct expandnode {
RB_HEAD(expandtree, expandnode);
-
+#define SMTPD_ENVELOPE_VERSION 1
struct envelope {
TAILQ_ENTRY(envelope) entry;
@@ -450,7 +417,33 @@ struct envelope {
u_int64_t session_id;
u_int64_t batch_id;
- struct delivery delivery;
+// struct delivery delivery;
+
+ u_int32_t version;
+ u_int64_t id;
+ enum delivery_type type;
+
+ char helo[MAXHOSTNAMELEN];
+ char hostname[MAXHOSTNAMELEN];
+ char errorline[MAX_LINE_SIZE + 1];
+ struct sockaddr_storage ss;
+
+ struct mailaddr sender;
+ struct mailaddr rcpt;
+ struct mailaddr dest;
+
+ union delivery_method {
+ struct delivery_mda mda;
+ struct delivery_mta mta;
+ } agent;
+
+ time_t creation;
+ time_t lasttry;
+ time_t expire;
+ u_int8_t retry;
+ enum delivery_flags flags;
+ enum delivery_status status;
+
};
TAILQ_HEAD(deliverylist, envelope);
@@ -1224,6 +1217,8 @@ void sa_set_port(struct sockaddr *, int);
u_int64_t generate_uid(void);
void fdlimit(double);
int availdesc(void);
+u_int32_t msgid_generate(void);
+u_int64_t evpid_generate(u_int32_t);
u_int32_t evpid_to_msgid(u_int64_t);
u_int64_t msgid_to_evpid(u_int32_t);
u_int32_t filename_to_msgid(char *);
diff --git a/usr.sbin/smtpd/smtpd/Makefile b/usr.sbin/smtpd/smtpd/Makefile
index 45ef959c8f2..0e9c42f4a7f 100644
--- a/usr.sbin/smtpd/smtpd/Makefile
+++ b/usr.sbin/smtpd/smtpd/Makefile
@@ -1,4 +1,4 @@
-# $OpenBSD: Makefile,v 1.30 2011/09/01 19:56:49 eric Exp $
+# $OpenBSD: Makefile,v 1.31 2011/10/23 09:30:07 gilles Exp $
PROG= smtpd
SRCS= aliases.c auth_backend.c bounce.c client.c \
@@ -10,7 +10,7 @@ SRCS= aliases.c auth_backend.c bounce.c client.c \
smtp_session.c smtpd.c ssl.c ssl_privsep.c util.c asr.c \
print.c pack.c dname.c res_random.c sockaddr.c \
ramqueue.c queue_backend.c queue_fsqueue.c \
- user_backend.c stats.c
+ queue_fsqueue_ascii.c user_backend.c stats.c
MAN= smtpd.8 smtpd.conf.5
BINDIR= /usr/sbin
diff --git a/usr.sbin/smtpd/util.c b/usr.sbin/smtpd/util.c
index afa5eef128f..128a6275211 100644
--- a/usr.sbin/smtpd/util.c
+++ b/usr.sbin/smtpd/util.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: util.c,v 1.47 2011/05/17 18:54:32 gilles Exp $ */
+/* $OpenBSD: util.c,v 1.48 2011/10/23 09:30:07 gilles Exp $ */
/*
* Copyright (c) 2000,2001 Markus Friedl. All rights reserved.
@@ -352,9 +352,9 @@ envelope_set_errormsg(struct envelope *e, char *fmt, ...)
va_start(ap, fmt);
- ret = vsnprintf(e->delivery.errorline, MAX_LINE_SIZE, fmt, ap);
+ ret = vsnprintf(e->errorline, MAX_LINE_SIZE, fmt, ap);
if (ret >= MAX_LINE_SIZE)
- strlcpy(e->delivery.errorline + (MAX_LINE_SIZE - 4), "...", 4);
+ strlcpy(e->errorline + (MAX_LINE_SIZE - 4), "...", 4);
/* this should not happen */
if (ret == -1)
@@ -366,7 +366,7 @@ envelope_set_errormsg(struct envelope *e, char *fmt, ...)
char *
envelope_get_errormsg(struct envelope *e)
{
- return e->delivery.errorline;
+ return e->errorline;
}
void
@@ -547,6 +547,38 @@ filename_to_evpid(char *filename)
}
u_int32_t
+msgid_generate(void)
+{
+ u_int32_t ret;
+
+ do {
+ ret = arc4random();
+ } while (ret == 0);
+
+ log_debug("msgid_generate: %08x", ret);
+
+ return ret;
+}
+
+u_int64_t
+evpid_generate(u_int32_t msgid)
+{
+ u_int64_t ret;
+
+ ret = msgid;
+ log_debug("evpid_generate: %016llx", ret);
+ ret <<= 32;
+ log_debug("evpid_generate: %016llx", ret);
+ do {
+ ret |= arc4random();
+ } while ((ret & 0xffffffff) == 0);
+
+ log_debug("evpid_generate: %016llx", ret);
+
+ return ret;
+}
+
+u_int32_t
evpid_to_msgid(u_int64_t evpid)
{
return (evpid >> 32);