summaryrefslogtreecommitdiff
path: root/usr.sbin/smtpd
diff options
context:
space:
mode:
authorGilles Chehade <gilles@cvs.openbsd.org>2011-04-14 20:11:09 +0000
committerGilles Chehade <gilles@cvs.openbsd.org>2011-04-14 20:11:09 +0000
commit88bf84069c919f11e6072a750f6b1ac7a9f492ed (patch)
treeaa65e237bb6da0e7a3a54688a157d9dad87cec47 /usr.sbin/smtpd
parent37d103bd8ed97c8b053353cc4a7f56b18f87a1af (diff)
fsqueue queue backend will implement a filesystem queue:
- fsqueue->setup() performs the queue initialization; - fsqueue->message() controls messages; - fsqueue->envelope() controls envelopes; This commit brings the following to fsbackend: fsqueue_setup(), fsqueue_message_delete(), fsqueue_envelope_load(), fsqueue_envelope_update(), fsqueue_envelope_delete(). It also makes smtpd use the queue_backend API for these operations.
Diffstat (limited to 'usr.sbin/smtpd')
-rw-r--r--usr.sbin/smtpd/bounce.c6
-rw-r--r--usr.sbin/smtpd/queue_backend.c14
-rw-r--r--usr.sbin/smtpd/queue_fsqueue.c382
-rw-r--r--usr.sbin/smtpd/queue_shared.c159
-rw-r--r--usr.sbin/smtpd/ramqueue.c7
-rw-r--r--usr.sbin/smtpd/runner.c24
-rw-r--r--usr.sbin/smtpd/smtpctl/Makefile4
-rw-r--r--usr.sbin/smtpd/smtpd.c137
-rw-r--r--usr.sbin/smtpd/smtpd.h5
9 files changed, 421 insertions, 317 deletions
diff --git a/usr.sbin/smtpd/bounce.c b/usr.sbin/smtpd/bounce.c
index 780e1f894b5..9bea66eb241 100644
--- a/usr.sbin/smtpd/bounce.c
+++ b/usr.sbin/smtpd/bounce.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: bounce.c,v 1.26 2011/03/26 10:59:59 gilles Exp $ */
+/* $OpenBSD: bounce.c,v 1.27 2011/04/14 20:11:08 gilles Exp $ */
/*
* Copyright (c) 2009 Gilles Chehade <gilles@openbsd.org>
@@ -147,14 +147,14 @@ bounce_event(int fd, short event, void *p)
out:
if (*ep == '2')
- queue_remove_envelope(&cc->m);
+ queue_envelope_delete(cc->env, Q_QUEUE, &cc->m);
else {
if (*ep == '5' || *ep == '6')
cc->m.status = S_MESSAGE_PERMFAILURE;
else
cc->m.status = S_MESSAGE_TEMPFAILURE;
message_set_errormsg(&cc->m, "%s", ep);
- queue_message_update(&cc->m);
+ queue_message_update(cc->env, &cc->m);
}
cc->env->stats->runner.active--;
diff --git a/usr.sbin/smtpd/queue_backend.c b/usr.sbin/smtpd/queue_backend.c
index aa9847b929c..ac677521882 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.5 2011/04/14 17:06:43 gilles Exp $ */
+/* $OpenBSD: queue_backend.c,v 1.6 2011/04/14 20:11:08 gilles Exp $ */
/*
* Copyright (c) 2011 Gilles Chehade <gilles@openbsd.org>
@@ -35,15 +35,19 @@
#include "smtpd.h"
#include "log.h"
-int queue_fsqueue_message(struct smtpd *, enum queue_kind,
+/* fsqueue backend */
+int fsqueue_init(struct smtpd *);
+int fsqueue_message(struct smtpd *, enum queue_kind,
enum queue_op, char *);
-int queue_fsqueue_envelope(struct smtpd *, enum queue_kind,
+int fsqueue_envelope(struct smtpd *, enum queue_kind,
enum queue_op , struct message *);
+
struct queue_backend queue_backends[] = {
{ QT_FS,
- queue_fsqueue_message,
- queue_fsqueue_envelope }
+ fsqueue_init,
+ fsqueue_message,
+ fsqueue_envelope }
};
struct queue_backend *
diff --git a/usr.sbin/smtpd/queue_fsqueue.c b/usr.sbin/smtpd/queue_fsqueue.c
index ee2766c69cd..ef5668d049a 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.1 2011/04/14 17:06:43 gilles Exp $ */
+/* $OpenBSD: queue_fsqueue.c,v 1.2 2011/04/14 20:11:08 gilles Exp $ */
/*
* Copyright (c) 2011 Gilles Chehade <gilles@openbsd.org>
@@ -23,6 +23,8 @@
#include <sys/socket.h>
#include <sys/stat.h>
+#include <err.h>
+#include <errno.h>
#include <event.h>
#include <imsg.h>
#include <libgen.h>
@@ -35,21 +37,391 @@
#include "smtpd.h"
#include "log.h"
-int queue_fsqueue_message(struct smtpd *, enum queue_kind,
+static char *fsqueue_getpath(enum queue_kind);
+static u_int16_t fsqueue_hash(char *);
+
+static int fsqueue_envelope_load(struct smtpd *, enum queue_kind, struct message *);
+static int fsqueue_envelope_update(struct smtpd *, enum queue_kind, struct message *);
+static int fsqueue_envelope_delete(struct smtpd *, enum queue_kind, struct message *);
+
+static int fsqueue_message_delete(struct smtpd *, enum queue_kind, char *);
+
+int fsqueue_init(struct smtpd *);
+int fsqueue_message(struct smtpd *, enum queue_kind,
enum queue_op, char *);
-int queue_fsqueue_envelope(struct smtpd *, enum queue_kind,
+int fsqueue_envelope(struct smtpd *, enum queue_kind,
enum queue_op , struct message *);
+static char *
+fsqueue_getpath(enum queue_kind kind)
+{
+ switch (kind) {
+ case Q_INCOMING:
+ return (PATH_INCOMING);
+
+ case Q_ENQUEUE:
+ return (PATH_INCOMING);
+
+ case Q_QUEUE:
+ return (PATH_QUEUE);
+
+ case Q_PURGE:
+ return (PATH_PURGE);
+
+ case Q_OFFLINE:
+ return (PATH_OFFLINE);
+
+ case Q_BOUNCE:
+ return (PATH_BOUNCE);
+
+ default:
+ fatalx("queue_fsqueue_getpath: unsupported queue kind.");
+ }
+ return NULL;
+}
+
+static u_int16_t
+fsqueue_hash(char *msgid)
+{
+ u_int16_t h;
+
+ for (h = 5381; *msgid; msgid++)
+ h = ((h << 5) + h) + *msgid;
+
+ return (h % DIRHASH_BUCKETS);
+}
+
+static int
+fsqueue_envelope_load(struct smtpd *env, enum queue_kind qkind,
+ struct message *envelope)
+{
+ char pathname[MAXPATHLEN];
+ char msgid[MAX_ID_SIZE];
+ FILE *fp;
+
+ if (strlcpy(msgid, envelope->message_uid, sizeof(msgid)) >= sizeof(msgid))
+ return 0;
+
+ *strrchr(msgid, '.') = '\0';
+ if (! bsnprintf(pathname, sizeof(pathname), "%s/%d/%s%s/%s",
+ fsqueue_getpath(qkind),
+ fsqueue_hash(msgid), msgid, PATH_ENVELOPES, envelope->message_uid))
+ fatalx("fsqueue_envelope_load: snprintf");
+
+ fp = fopen(pathname, "r");
+ if (fp == NULL) {
+ if (errno == ENOENT || errno == ENFILE)
+ return 0;
+ fatal("fsqueue_envelope_load: fopen");
+ }
+ if (fread(envelope, sizeof(struct message), 1, fp) != 1)
+ fatal("fsqueue_envelope_load: fread");
+ fclose(fp);
+ return 1;
+}
+
+int
+fsqueue_envelope_update(struct smtpd *env, enum queue_kind qkind,
+ struct message *envelope)
+{
+ char temp[MAXPATHLEN];
+ char dest[MAXPATHLEN];
+ FILE *fp;
+ u_int64_t batch_id;
+
+ batch_id = envelope->batch_id;
+ envelope->batch_id = 0;
+
+ if (! bsnprintf(temp, sizeof(temp), "%s/envelope.tmp", PATH_QUEUE))
+ fatalx("fsqueue_envelope_update");
+
+ if (! bsnprintf(dest, sizeof(dest), "%s/%d/%s%s/%s",
+ fsqueue_getpath(qkind),
+ fsqueue_hash(envelope->message_id),
+ envelope->message_id,
+ PATH_ENVELOPES, envelope->message_uid))
+ fatal("fsqueue_envelope_update: snprintf");
+
+ fp = fopen(temp, "w");
+ if (fp == NULL) {
+ if (errno == ENOSPC || errno == ENFILE)
+ goto tempfail;
+ fatal("fsqueue_envelope_update: open");
+ }
+ if (fwrite(envelope, sizeof(struct message), 1, fp) != 1) {
+ if (errno == ENOSPC)
+ goto tempfail;
+ fatal("fsqueue_envelope_update: fwrite");
+ }
+ if (! safe_fclose(fp))
+ goto tempfail;
+
+ if (rename(temp, dest) == -1) {
+ if (errno == ENOSPC)
+ goto tempfail;
+ fatal("fsqueue_envelope_update: rename");
+ }
+
+ envelope->batch_id = batch_id;
+ return 1;
+
+tempfail:
+ if (unlink(temp) == -1)
+ fatal("fsqueue_envelope_update: unlink");
+ if (fp)
+ fclose(fp);
+
+ envelope->batch_id = batch_id;
+ return 0;
+}
+
+int
+fsqueue_envelope_delete(struct smtpd *env, enum queue_kind qkind,
+ struct message *envelope)
+{
+ char pathname[MAXPATHLEN];
+ u_int16_t hval;
+
+ hval = fsqueue_hash(envelope->message_id);
+
+ if (! bsnprintf(pathname, sizeof(pathname), "%s/%d/%s%s/%s",
+ fsqueue_getpath(qkind),
+ hval, envelope->message_id, PATH_ENVELOPES,
+ envelope->message_uid))
+ fatal("fsqueue_envelope_delete: snprintf");
+
+ if (unlink(pathname) == -1)
+ fatal("fsqueue_envelope_delete: unlink");
+
+ if (! bsnprintf(pathname, sizeof(pathname), "%s/%d/%s%s", PATH_QUEUE,
+ hval, envelope->message_id, PATH_ENVELOPES))
+ fatal("fsqueue_envelope_delete: snprintf");
+
+ if (rmdir(pathname) != -1)
+ fsqueue_message_delete(env, qkind, envelope->message_id);
+
+ return 1;
+}
+
+int
+fsqueue_message_delete(struct smtpd *env, enum queue_kind qkind, char *msgid)
+{
+ char rootdir[MAXPATHLEN];
+ char evpdir[MAXPATHLEN];
+ char msgpath[MAXPATHLEN];
+ u_int16_t hval;
+
+ hval = queue_hash(msgid);
+ if (! bsnprintf(rootdir, sizeof(rootdir), "%s/%d/%s", PATH_QUEUE,
+ hval, msgid))
+ fatal("queue_delete_message: snprintf");
+
+ if (! bsnprintf(evpdir, sizeof(evpdir), "%s%s", rootdir,
+ PATH_ENVELOPES))
+ fatal("queue_delete_message: snprintf");
+
+ if (! bsnprintf(msgpath, sizeof(msgpath), "%s/message", rootdir))
+ fatal("queue_delete_message: snprintf");
+
+ if (unlink(msgpath) == -1)
+ fatal("queue_delete_message: unlink");
+
+ if (rmdir(evpdir) == -1) {
+ /* It is ok to fail rmdir with ENOENT here
+ * because upon successful delivery of the
+ * last envelope, we remove the directory.
+ */
+ if (errno != ENOENT)
+ fatal("queue_delete_message: rmdir");
+ }
+
+ if (rmdir(rootdir) == -1)
+ fatal("#2 queue_delete_message: rmdir");
+
+ if (! bsnprintf(rootdir, sizeof(rootdir), "%s/%d", PATH_QUEUE, hval))
+ fatal("queue_delete_message: snprintf");
+
+ rmdir(rootdir);
+
+ return 1;
+}
+
+int
+fsqueue_init(struct smtpd *env)
+{
+ unsigned int n;
+ char *paths[] = { PATH_INCOMING, PATH_ENQUEUE, PATH_QUEUE,
+ PATH_PURGE, PATH_OFFLINE, PATH_BOUNCE };
+ char pathname[MAXPATHLEN];
+ struct stat sb;
+ int ret;
+
+ if (! bsnprintf(pathname, sizeof(pathname), "%s", PATH_SPOOL))
+ fatal("snprintf");
+
+ if (stat(pathname, &sb) == -1) {
+ if (errno != ENOENT) {
+ warn("stat: %s", pathname);
+ return 0;
+ }
+
+ if (mkdir(pathname, 0711) == -1) {
+ warn("mkdir: %s", pathname);
+ return 0;
+ }
+
+ if (chown(pathname, 0, 0) == -1) {
+ warn("chown: %s", pathname);
+ return 0;
+ }
+
+ if (stat(pathname, &sb) == -1)
+ err(1, "stat: %s", pathname);
+ }
+
+ /* check if it's a directory */
+ if (!S_ISDIR(sb.st_mode)) {
+ warnx("%s is not a directory", pathname);
+ return 0;
+ }
+
+ /* check that it is owned by uid/gid */
+ if (sb.st_uid != 0 || sb.st_gid != 0) {
+ warnx("%s must be owned by root:wheel", pathname);
+ return 0;
+ }
+
+ /* check permission */
+ if ((sb.st_mode & (S_IRUSR|S_IWUSR|S_IXUSR)) != (S_IRUSR|S_IWUSR|S_IXUSR) ||
+ (sb.st_mode & (S_IRGRP|S_IWGRP|S_IXGRP)) != S_IXGRP ||
+ (sb.st_mode & (S_IROTH|S_IWOTH|S_IXOTH)) != S_IXOTH) {
+ warnx("%s must be rwx--x--x (0711)", pathname);
+ return 0;
+ }
+
+ ret = 1;
+ for (n = 0; n < nitems(paths); n++) {
+ mode_t mode;
+ uid_t owner;
+ gid_t group;
+
+ if (!strcmp(paths[n], PATH_OFFLINE)) {
+ mode = 01777;
+ owner = 0;
+ group = 0;
+ } else {
+ mode = 0700;
+ owner = env->sc_pw->pw_uid;
+ group = env->sc_pw->pw_gid;
+ }
+
+ if (! bsnprintf(pathname, sizeof(pathname), "%s%s", PATH_SPOOL,
+ paths[n]))
+ fatal("snprintf");
+
+ if (stat(pathname, &sb) == -1) {
+ if (errno != ENOENT) {
+ warn("stat: %s", pathname);
+ ret = 0;
+ continue;
+ }
+
+ /* chmod is deffered to avoid umask effect */
+ if (mkdir(pathname, 0) == -1) {
+ ret = 0;
+ warn("mkdir: %s", pathname);
+ }
+
+ if (chown(pathname, owner, group) == -1) {
+ ret = 0;
+ warn("chown: %s", pathname);
+ }
+
+ if (chmod(pathname, mode) == -1) {
+ ret = 0;
+ warn("chmod: %s", pathname);
+ }
+
+ if (stat(pathname, &sb) == -1)
+ err(1, "stat: %s", pathname);
+ }
+
+ /* check if it's a directory */
+ if (!S_ISDIR(sb.st_mode)) {
+ ret = 0;
+ warnx("%s is not a directory", pathname);
+ }
+
+ /* check that it is owned by owner/group */
+ if (sb.st_uid != owner) {
+ ret = 0;
+ warnx("%s is not owned by uid %d", pathname, owner);
+ }
+ if (sb.st_gid != group) {
+ ret = 0;
+ warnx("%s is not owned by gid %d", pathname, group);
+ }
+
+ /* check permission */
+ if ((sb.st_mode & 07777) != mode) {
+ char mode_str[12];
+
+ ret = 0;
+ strmode(mode, mode_str);
+ mode_str[10] = '\0';
+ warnx("%s must be %s (%o)", pathname, mode_str + 1, mode);
+ }
+ }
+ return ret;
+}
+
int
-queue_fsqueue_message(struct smtpd *env, enum queue_kind qkind,
+fsqueue_message(struct smtpd *env, enum queue_kind qkind,
enum queue_op qop, char *msgid)
{
+ switch (qop) {
+ case QOP_CREATE:
+ return 0;
+
+ case QOP_DELETE:
+ return fsqueue_message_delete(env, qkind, msgid);
+
+ case QOP_COMMIT:
+ return 0;
+
+ case QOP_FD_R:
+ return 0;
+
+ case QOP_FD_RW:
+ return 0;
+
+ default:
+ fatalx("queue_fsqueue_message: unsupported operation.");
+ }
+
return 0;
}
int
-queue_fsqueue_envelope(struct smtpd *env, enum queue_kind qkind,
+fsqueue_envelope(struct smtpd *env, enum queue_kind qkind,
enum queue_op qop, struct message *envelope)
{
+ switch (qop) {
+ case QOP_CREATE:
+ return 0;
+
+ case QOP_DELETE:
+ return fsqueue_envelope_delete(env, qkind, envelope);
+
+ case QOP_LOAD:
+ return fsqueue_envelope_load(env, qkind, envelope);
+
+ case QOP_UPDATE:
+ return fsqueue_envelope_update(env, qkind, envelope);
+
+ default:
+ fatalx("queue_fsqueue_envelope: unsupported operation.");
+ }
+
return 0;
}
diff --git a/usr.sbin/smtpd/queue_shared.c b/usr.sbin/smtpd/queue_shared.c
index 18549901553..1d8f1c415ef 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.37 2011/04/13 20:53:18 gilles Exp $ */
+/* $OpenBSD: queue_shared.c,v 1.38 2011/04/14 20:11:08 gilles Exp $ */
/*
* Copyright (c) 2008 Gilles Chehade <gilles@openbsd.org>
@@ -404,50 +404,7 @@ queue_open_message_file(char *msgid)
}
void
-queue_delete_message(char *msgid)
-{
- char rootdir[MAXPATHLEN];
- char evpdir[MAXPATHLEN];
- char msgpath[MAXPATHLEN];
- u_int16_t hval;
-
- hval = queue_hash(msgid);
- if (! bsnprintf(rootdir, sizeof(rootdir), "%s/%d/%s", PATH_QUEUE,
- hval, msgid))
- fatal("queue_delete_message: snprintf");
-
- if (! bsnprintf(evpdir, sizeof(evpdir), "%s%s", rootdir,
- PATH_ENVELOPES))
- fatal("queue_delete_message: snprintf");
-
- if (! bsnprintf(msgpath, sizeof(msgpath), "%s/message", rootdir))
- fatal("queue_delete_message: snprintf");
-
- if (unlink(msgpath) == -1)
- fatal("queue_delete_message: unlink");
-
- if (rmdir(evpdir) == -1) {
- /* It is ok to fail rmdir with ENOENT here
- * because upon successful delivery of the
- * last envelope, we remove the directory.
- */
- if (errno != ENOENT)
- fatal("queue_delete_message: rmdir");
- }
-
- if (rmdir(rootdir) == -1)
- fatal("#2 queue_delete_message: rmdir");
-
- if (! bsnprintf(rootdir, sizeof(rootdir), "%s/%d", PATH_QUEUE, hval))
- fatal("queue_delete_message: snprintf");
-
- rmdir(rootdir);
-
- return;
-}
-
-void
-queue_message_update(struct message *messagep)
+queue_message_update(struct smtpd *env, struct message *messagep)
{
messagep->flags &= ~F_MESSAGE_PROCESSING;
messagep->status &= ~(S_MESSAGE_ACCEPTED|S_MESSAGE_REJECTED);
@@ -461,124 +418,18 @@ queue_message_update(struct message *messagep)
bounce_record_message(messagep, &bounce);
}
- queue_remove_envelope(messagep);
+ queue_envelope_delete(env, Q_QUEUE, messagep);
return;
}
if (messagep->status & S_MESSAGE_TEMPFAILURE) {
messagep->status &= ~S_MESSAGE_TEMPFAILURE;
- queue_update_envelope(messagep);
+ queue_envelope_update(env, Q_QUEUE, messagep);
return;
}
/* no error, remove envelope */
- queue_remove_envelope(messagep);
-}
-
-int
-queue_remove_envelope(struct message *messagep)
-{
- char pathname[MAXPATHLEN];
- u_int16_t hval;
-
- hval = queue_hash(messagep->message_id);
-
- if (! bsnprintf(pathname, sizeof(pathname), "%s/%d/%s%s/%s",
- PATH_QUEUE, hval, messagep->message_id, PATH_ENVELOPES,
- messagep->message_uid))
- fatal("queue_remove_envelope: snprintf");
-
- if (unlink(pathname) == -1)
- fatal("queue_remove_envelope: unlink");
-
- if (! bsnprintf(pathname, sizeof(pathname), "%s/%d/%s%s", PATH_QUEUE,
- hval, messagep->message_id, PATH_ENVELOPES))
- fatal("queue_remove_envelope: snprintf");
-
- if (rmdir(pathname) != -1)
- queue_delete_message(messagep->message_id);
-
- return 1;
-}
-
-int
-queue_update_envelope(struct message *messagep)
-{
- char temp[MAXPATHLEN];
- char dest[MAXPATHLEN];
- FILE *fp;
- u_int64_t batch_id;
-
- batch_id = messagep->batch_id;
- messagep->batch_id = 0;
-
- if (! bsnprintf(temp, sizeof(temp), "%s/envelope.tmp", PATH_QUEUE))
- fatalx("queue_update_envelope");
-
- if (! bsnprintf(dest, sizeof(dest), "%s/%d/%s%s/%s", PATH_QUEUE,
- queue_hash(messagep->message_id), messagep->message_id,
- PATH_ENVELOPES, messagep->message_uid))
- fatal("queue_update_envelope: snprintf");
-
- fp = fopen(temp, "w");
- if (fp == NULL) {
- if (errno == ENOSPC || errno == ENFILE)
- goto tempfail;
- fatal("queue_update_envelope: open");
- }
- if (fwrite(messagep, sizeof(struct message), 1, fp) != 1) {
- if (errno == ENOSPC)
- goto tempfail;
- fatal("queue_update_envelope: fwrite");
- }
- if (! safe_fclose(fp))
- goto tempfail;
-
- if (rename(temp, dest) == -1) {
- if (errno == ENOSPC)
- goto tempfail;
- fatal("queue_update_envelope: rename");
- }
-
- messagep->batch_id = batch_id;
- return 1;
-
-tempfail:
- if (unlink(temp) == -1)
- fatal("queue_update_envelope: unlink");
- if (fp)
- fclose(fp);
-
- messagep->batch_id = batch_id;
- return 0;
-}
-
-int
-queue_load_envelope(struct message *messagep, char *evpid)
-{
- char pathname[MAXPATHLEN];
- char msgid[MAX_ID_SIZE];
- FILE *fp;
-
- if (strlcpy(msgid, evpid, sizeof(msgid)) >= sizeof(msgid))
- fatalx("queue_load_envelope: truncation");
- *strrchr(msgid, '.') = '\0';
-
- if (! bsnprintf(pathname, sizeof(pathname), "%s/%d/%s%s/%s", PATH_QUEUE,
- queue_hash(msgid), msgid, PATH_ENVELOPES, evpid))
- fatalx("queue_load_envelope: snprintf");
-
- fp = fopen(pathname, "r");
- if (fp == NULL) {
- if (errno == ENOENT || errno == ENFILE)
- return 0;
- fatal("queue_load_envelope: fopen");
- }
- if (fread(messagep, sizeof(struct message), 1, fp) != 1)
- fatal("queue_load_envelope: fread");
- fclose(fp);
-
- return 1;
+ queue_envelope_delete(env, Q_QUEUE, messagep);
}
u_int16_t
diff --git a/usr.sbin/smtpd/ramqueue.c b/usr.sbin/smtpd/ramqueue.c
index 17d10f7002b..8e98de29dc0 100644
--- a/usr.sbin/smtpd/ramqueue.c
+++ b/usr.sbin/smtpd/ramqueue.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ramqueue.c,v 1.1 2011/04/13 20:53:18 gilles Exp $ */
+/* $OpenBSD: ramqueue.c,v 1.2 2011/04/14 20:11:08 gilles Exp $ */
/*
* Copyright (c) 2011 Gilles Chehade <gilles@openbsd.org>
@@ -140,7 +140,8 @@ ramqueue_load(struct ramqueue *rqueue, time_t *nsched)
while (qwalk(q, path)) {
curtm = time(NULL);
- if (! queue_load_envelope(&envelope, basename(path)))
+ if (! queue_envelope_load(rqueue->env, Q_QUEUE,
+ basename(path), &envelope))
continue;
if (ramqueue_expire(rqueue->env, &envelope, curtm))
continue;
@@ -216,7 +217,7 @@ ramqueue_expire(struct smtpd *env, struct message *envelope, time_t curtm)
envelope->expire / 60 / 60 / 24);
bounce_record_message(envelope, &bounce);
ramqueue_insert(&env->sc_rqueue, &bounce, time(NULL));
- queue_remove_envelope(envelope);
+ queue_envelope_delete(env, Q_QUEUE, envelope);
return 1;
}
return 0;
diff --git a/usr.sbin/smtpd/runner.c b/usr.sbin/smtpd/runner.c
index da71b28eb53..fb8e185f0ab 100644
--- a/usr.sbin/smtpd/runner.c
+++ b/usr.sbin/smtpd/runner.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: runner.c,v 1.96 2011/04/13 20:53:18 gilles Exp $ */
+/* $OpenBSD: runner.c,v 1.97 2011/04/14 20:11:08 gilles Exp $ */
/*
* Copyright (c) 2008 Gilles Chehade <gilles@openbsd.org>
@@ -84,7 +84,7 @@ runner_imsg(struct smtpd *env, struct imsgev *iev, struct imsg *imsg)
*/
if (m->status & S_MESSAGE_TEMPFAILURE) {
m->status &= ~S_MESSAGE_TEMPFAILURE;
- queue_update_envelope(m);
+ queue_envelope_update(env, Q_QUEUE, m);
ramqueue_insert(&env->sc_rqueue, m, time(NULL));
runner_setup_events(env);
return;
@@ -107,7 +107,7 @@ runner_imsg(struct smtpd *env, struct imsgev *iev, struct imsg *imsg)
/* successful delivery or permanent failure,
* remove envelope from queue.
*/
- queue_remove_envelope(m);
+ queue_envelope_delete(env, Q_QUEUE, m);
return;
case IMSG_MDA_SESS_NEW:
@@ -126,7 +126,7 @@ runner_imsg(struct smtpd *env, struct imsgev *iev, struct imsg *imsg)
m = imsg->data;
if (imsg->fd < 0 || !bounce_session(env, imsg->fd, m)) {
m->status = 0;
- queue_update_envelope(m);
+ queue_envelope_update(env, Q_QUEUE, m);
ramqueue_insert(&env->sc_rqueue, m, time(NULL));
runner_setup_events(env);
return;
@@ -339,7 +339,7 @@ runner_process_envelope(struct smtpd *env, struct ramqueue_envelope *rq_evp, tim
mda_av = env->sc_maxconn - env->stats->mda.sessions_active;
bnc_av = env->sc_maxconn - env->stats->runner.bounces_active;
- if (! queue_load_envelope(&envelope, rq_evp->id))
+ if (! queue_envelope_load(env, Q_QUEUE, rq_evp->id, &envelope))
return 0;
if (envelope.type & T_MDA_MESSAGE) {
@@ -370,7 +370,7 @@ runner_process_envelope(struct smtpd *env, struct ramqueue_envelope *rq_evp, tim
bounce_record_message(&envelope, &bounce);
ramqueue_insert(&env->sc_rqueue, &bounce, time(NULL));
runner_setup_events(env);
- queue_remove_envelope(&envelope);
+ queue_envelope_delete(env, Q_QUEUE, &envelope);
return 0;
}
@@ -395,7 +395,8 @@ runner_process_batch(struct smtpd *env, struct ramqueue_envelope *rq_evp, time_t
switch (batch->type) {
case T_BOUNCE_MESSAGE:
while ((rq_evp = ramqueue_batch_first_envelope(batch))) {
- if (! queue_load_envelope(&envelope, rq_evp->id))
+ if (! queue_envelope_load(env, Q_QUEUE, rq_evp->id,
+ &envelope))
return;
envelope.lasttry = curtm;
imsg_compose_event(env->sc_ievs[PROC_QUEUE],
@@ -416,7 +417,8 @@ runner_process_batch(struct smtpd *env, struct ramqueue_envelope *rq_evp, time_t
case T_MDA_MESSAGE:
rq_evp = ramqueue_batch_first_envelope(batch);
- if (! queue_load_envelope(&envelope, rq_evp->id))
+ if (! queue_envelope_load(env, Q_QUEUE, rq_evp->id,
+ &envelope))
return;
envelope.lasttry = curtm;
fd = queue_open_message_file(envelope.message_id);
@@ -440,7 +442,8 @@ runner_process_batch(struct smtpd *env, struct ramqueue_envelope *rq_evp, time_t
IMSG_BATCH_CREATE, PROC_MTA, 0, -1, batch,
sizeof *batch);
while ((rq_evp = ramqueue_batch_first_envelope(batch))) {
- if (! queue_load_envelope(&envelope, rq_evp->id))
+ if (! queue_envelope_load(env, Q_QUEUE, rq_evp->id,
+ &envelope))
return;
envelope.lasttry = curtm;
envelope.batch_id = batch->b_id;
@@ -502,7 +505,8 @@ runner_force_message_to_ramqueue(struct ramqueue *rqueue, char *mid)
curtm = time(NULL);
while ((dp = readdir(dirp)) != NULL) {
if (valid_message_uid(dp->d_name)) {
- if (! queue_load_envelope(&envelope, dp->d_name))
+ if (! queue_envelope_load(rqueue->env, Q_QUEUE, dp->d_name,
+ &envelope))
continue;
ramqueue_insert(rqueue, &envelope, curtm);
}
diff --git a/usr.sbin/smtpd/smtpctl/Makefile b/usr.sbin/smtpd/smtpctl/Makefile
index 9d794d0ff24..7cf59de82eb 100644
--- a/usr.sbin/smtpd/smtpctl/Makefile
+++ b/usr.sbin/smtpd/smtpctl/Makefile
@@ -1,4 +1,4 @@
-# $OpenBSD: Makefile,v 1.16 2010/10/09 22:05:35 gilles Exp $
+# $OpenBSD: Makefile,v 1.17 2011/04/14 20:11:08 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
+SRCS= smtpctl.c parser.c log.c enqueue.c queue_shared.c util.c client.c queue_backend.c queue_fsqueue.c
LDADD+= -lutil -levent
DPADD+= ${LIBUTIL} ${LIBEVENT}
.include <bsd.prog.mk>
diff --git a/usr.sbin/smtpd/smtpd.c b/usr.sbin/smtpd/smtpd.c
index f1719b6ef00..4aed7f9664e 100644
--- a/usr.sbin/smtpd/smtpd.c
+++ b/usr.sbin/smtpd/smtpd.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: smtpd.c,v 1.118 2011/04/14 17:06:43 gilles Exp $ */
+/* $OpenBSD: smtpd.c,v 1.119 2011/04/14 20:11:08 gilles Exp $ */
/*
* Copyright (c) 2008 Gilles Chehade <gilles@openbsd.org>
@@ -488,13 +488,13 @@ main(int argc, char *argv[])
if ((env.sc_pw = getpwnam(SMTPD_USER)) == NULL)
errx(1, "unknown user %s", SMTPD_USER);
- if (!setup_spool(env.sc_pw->pw_uid, 0))
- errx(1, "invalid directory permissions");
-
env.sc_queue = queue_backend_lookup(QT_FS);
if (env.sc_queue == NULL)
errx(1, "could not find queue backend");
+ if (!env.sc_queue->setup(&env))
+ errx(1, "invalid directory permissions");
+
log_init(debug);
log_verbose(verbose);
@@ -637,135 +637,6 @@ child_lookup(struct smtpd *env, pid_t pid)
return SPLAY_FIND(childtree, &env->children, &key);
}
-int
-setup_spool(uid_t uid, gid_t gid)
-{
- unsigned int n;
- char *paths[] = { PATH_INCOMING, PATH_ENQUEUE, PATH_QUEUE,
- PATH_PURGE, PATH_OFFLINE, PATH_BOUNCE };
- char pathname[MAXPATHLEN];
- struct stat sb;
- int ret;
-
- if (! bsnprintf(pathname, sizeof(pathname), "%s", PATH_SPOOL))
- fatal("snprintf");
-
- if (stat(pathname, &sb) == -1) {
- if (errno != ENOENT) {
- warn("stat: %s", pathname);
- return 0;
- }
-
- if (mkdir(pathname, 0711) == -1) {
- warn("mkdir: %s", pathname);
- return 0;
- }
-
- if (chown(pathname, 0, 0) == -1) {
- warn("chown: %s", pathname);
- return 0;
- }
-
- if (stat(pathname, &sb) == -1)
- err(1, "stat: %s", pathname);
- }
-
- /* check if it's a directory */
- if (!S_ISDIR(sb.st_mode)) {
- warnx("%s is not a directory", pathname);
- return 0;
- }
-
- /* check that it is owned by uid/gid */
- if (sb.st_uid != 0 || sb.st_gid != 0) {
- warnx("%s must be owned by root:wheel", pathname);
- return 0;
- }
-
- /* check permission */
- if ((sb.st_mode & (S_IRUSR|S_IWUSR|S_IXUSR)) != (S_IRUSR|S_IWUSR|S_IXUSR) ||
- (sb.st_mode & (S_IRGRP|S_IWGRP|S_IXGRP)) != S_IXGRP ||
- (sb.st_mode & (S_IROTH|S_IWOTH|S_IXOTH)) != S_IXOTH) {
- warnx("%s must be rwx--x--x (0711)", pathname);
- return 0;
- }
-
- ret = 1;
- for (n = 0; n < nitems(paths); n++) {
- mode_t mode;
- uid_t owner;
- gid_t group;
-
- if (!strcmp(paths[n], PATH_OFFLINE)) {
- mode = 01777;
- owner = 0;
- group = 0;
- } else {
- mode = 0700;
- owner = uid;
- group = gid;
- }
-
- if (! bsnprintf(pathname, sizeof(pathname), "%s%s", PATH_SPOOL,
- paths[n]))
- fatal("snprintf");
-
- if (stat(pathname, &sb) == -1) {
- if (errno != ENOENT) {
- warn("stat: %s", pathname);
- ret = 0;
- continue;
- }
-
- /* chmod is deffered to avoid umask effect */
- if (mkdir(pathname, 0) == -1) {
- ret = 0;
- warn("mkdir: %s", pathname);
- }
-
- if (chown(pathname, owner, group) == -1) {
- ret = 0;
- warn("chown: %s", pathname);
- }
-
- if (chmod(pathname, mode) == -1) {
- ret = 0;
- warn("chmod: %s", pathname);
- }
-
- if (stat(pathname, &sb) == -1)
- err(1, "stat: %s", pathname);
- }
-
- /* check if it's a directory */
- if (!S_ISDIR(sb.st_mode)) {
- ret = 0;
- warnx("%s is not a directory", pathname);
- }
-
- /* check that it is owned by owner/group */
- if (sb.st_uid != owner) {
- ret = 0;
- warnx("%s is not owned by uid %d", pathname, owner);
- }
- if (sb.st_gid != group) {
- ret = 0;
- warnx("%s is not owned by gid %d", pathname, group);
- }
-
- /* check permission */
- if ((sb.st_mode & 07777) != mode) {
- char mode_str[12];
-
- ret = 0;
- strmode(mode, mode_str);
- mode_str[10] = '\0';
- warnx("%s must be %s (%o)", pathname, mode_str + 1, mode);
- }
- }
- return ret;
-}
-
void
imsg_event_add(struct imsgev *iev)
{
diff --git a/usr.sbin/smtpd/smtpd.h b/usr.sbin/smtpd/smtpd.h
index d1d84cccc58..67ca4e3c1fb 100644
--- a/usr.sbin/smtpd/smtpd.h
+++ b/usr.sbin/smtpd/smtpd.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: smtpd.h,v 1.209 2011/04/14 17:06:43 gilles Exp $ */
+/* $OpenBSD: smtpd.h,v 1.210 2011/04/14 20:11:08 gilles Exp $ */
/*
* Copyright (c) 2008 Gilles Chehade <gilles@openbsd.org>
@@ -931,6 +931,7 @@ enum queue_op {
struct queue_backend {
enum queue_type type;
+ int (*setup)(struct smtpd *);
int (*message)(struct smtpd *, enum queue_kind, enum queue_op, char *);
int (*envelope)(struct smtpd *, enum queue_kind, enum queue_op,
struct message *);
@@ -1097,7 +1098,7 @@ int queue_remove_incoming_envelope(struct message *);
int queue_commit_incoming_message(struct message *);
int queue_open_incoming_message_file(struct message *);
int queue_open_message_file(char *msgid);
-void queue_message_update(struct message *);
+void queue_message_update(struct smtpd *, struct message *);
void queue_delete_message(char *);
struct qwalk *qwalk_new(char *);
int qwalk(struct qwalk *, char *);