summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--usr.sbin/smtpd/scheduler_api.c416
-rw-r--r--usr.sbin/smtpd/scheduler_backend.c5
-rw-r--r--usr.sbin/smtpd/scheduler_null.c2
-rw-r--r--usr.sbin/smtpd/scheduler_proc.c423
-rw-r--r--usr.sbin/smtpd/scheduler_ramqueue.c2
-rw-r--r--usr.sbin/smtpd/smtpd-api.h93
-rw-r--r--usr.sbin/smtpd/smtpd.h54
-rw-r--r--usr.sbin/smtpd/smtpd/Makefile3
8 files changed, 940 insertions, 58 deletions
diff --git a/usr.sbin/smtpd/scheduler_api.c b/usr.sbin/smtpd/scheduler_api.c
new file mode 100644
index 00000000000..6f0b214d798
--- /dev/null
+++ b/usr.sbin/smtpd/scheduler_api.c
@@ -0,0 +1,416 @@
+/* $OpenBSD: scheduler_api.c,v 1.1 2013/07/19 21:34:31 eric Exp $ */
+
+/*
+ * Copyright (c) 2013 Eric Faurot <eric@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/uio.h>
+
+#include <imsg.h>
+#include <pwd.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "smtpd-defines.h"
+#include "smtpd-api.h"
+#include "log.h"
+
+static int (*handler_init)(void);
+static int (*handler_insert)(struct scheduler_info *);
+static size_t (*handler_commit)(uint32_t);
+static size_t (*handler_rollback)(uint32_t);
+static int (*handler_update)(struct scheduler_info *);
+static int (*handler_delete)(uint64_t);
+static int (*handler_batch)(int, struct scheduler_batch *);
+static size_t (*handler_messages)(uint32_t, uint32_t *, size_t);
+static size_t (*handler_envelopes)(uint64_t, struct evpstate *, size_t);
+static int (*handler_schedule)(uint64_t);
+static int (*handler_remove)(uint64_t);
+static int (*handler_suspend)(uint64_t);
+static int (*handler_resume)(uint64_t);
+
+#define MAX_BATCH_SIZE 1024
+
+static struct imsgbuf ibuf;
+static struct imsg imsg;
+static size_t rlen;
+static char *rdata;
+static struct ibuf *buf;
+static char *rootpath = PATH_CHROOT;
+static char *user = SMTPD_USER;
+
+static void
+scheduler_msg_get(void *dst, size_t len)
+{
+ if (len > rlen) {
+ log_warnx("warn: scheduler-proc: bad msg len");
+ fatalx("scheduler-proc: exiting");
+ }
+
+ if (len == 0)
+ return;
+
+ if (dst)
+ memmove(dst, rdata, len);
+
+ rlen -= len;
+ rdata += len;
+}
+
+static void
+scheduler_msg_end(void)
+{
+ if (rlen) {
+ log_warnx("warn: scheduler-proc: bogus data");
+ fatalx("scheduler-proc: exiting");
+ }
+ imsg_free(&imsg);
+}
+
+static void
+scheduler_msg_add(const void *data, size_t len)
+{
+ if (buf == NULL)
+ buf = imsg_create(&ibuf, PROC_SCHEDULER_OK, 0, 0, 1024);
+ if (buf == NULL) {
+ log_warnx("warn: table-api: imsg_create failed");
+ fatalx("table-api: exiting");
+ }
+ if (imsg_add(buf, data, len) == -1) {
+ log_warnx("warn: table-api: imsg_add failed");
+ fatalx("table-api: exiting");
+ }
+}
+
+static void
+scheduler_msg_close(void)
+{
+ imsg_close(&ibuf, buf);
+ buf = NULL;
+}
+
+static void
+scheduler_msg_dispatch(void)
+{
+ size_t n, sz;
+ struct evpstate evpstates[MAX_BATCH_SIZE];
+ uint64_t evpid, evpids[MAX_BATCH_SIZE];
+ uint32_t msgids[MAX_BATCH_SIZE], version, msgid;
+ struct scheduler_info info;
+ struct scheduler_batch batch;
+ int typemask, r;
+
+ switch (imsg.hdr.type) {
+ case PROC_SCHEDULER_INIT:
+ log_debug("scheduler-api: PROC_SCHEDULER_INIT");
+ scheduler_msg_get(&version, sizeof(version));
+ scheduler_msg_end();
+
+ if (version != PROC_SCHEDULER_API_VERSION) {
+ log_warnx("warn: scheduler-api: bad API version");
+ fatalx("scheduler-api: exiting");
+ }
+
+ r = handler_init();
+
+ imsg_compose(&ibuf, PROC_SCHEDULER_OK, 0, 0, -1, &r, sizeof(r));
+ break;
+
+ case PROC_SCHEDULER_INSERT:
+ log_debug("scheduler-api: PROC_SCHEDULER_INSERT");
+ scheduler_msg_get(&info, sizeof(info));
+ scheduler_msg_end();
+
+ r = handler_insert(&info);
+
+ imsg_compose(&ibuf, PROC_SCHEDULER_OK, 0, 0, -1, &r, sizeof(r));
+ break;
+
+ case PROC_SCHEDULER_COMMIT:
+ log_debug("scheduler-api: PROC_SCHEDULER_COMMIT");
+ scheduler_msg_get(&msgid, sizeof(msgid));
+ scheduler_msg_end();
+
+ n = handler_commit(msgid);
+
+ imsg_compose(&ibuf, PROC_SCHEDULER_OK, 0, 0, -1, &n, sizeof(n));
+ break;
+
+ case PROC_SCHEDULER_ROLLBACK:
+ log_debug("scheduler-api: PROC_SCHEDULER_ROLLBACK");
+ scheduler_msg_get(&msgid, sizeof(msgid));
+ scheduler_msg_end();
+
+ n = handler_rollback(msgid);
+
+ imsg_compose(&ibuf, PROC_SCHEDULER_OK, 0, 0, -1, &n, sizeof(n));
+ break;
+
+ case PROC_SCHEDULER_UPDATE:
+ log_debug("scheduler-api: PROC_SCHEDULER_UPDATE");
+ scheduler_msg_get(&info, sizeof(info));
+ scheduler_msg_end();
+
+ r = handler_update(&info);
+
+ scheduler_msg_add(&r, sizeof(r));
+ if (r == 1)
+ scheduler_msg_add(&info, sizeof(info));
+ scheduler_msg_close();
+ break;
+
+ case PROC_SCHEDULER_DELETE:
+ log_debug("scheduler-api: PROC_SCHEDULER_DELETE");
+ scheduler_msg_get(&evpid, sizeof(evpid));
+ scheduler_msg_end();
+
+ r = handler_delete(evpid);
+
+ imsg_compose(&ibuf, PROC_SCHEDULER_OK, 0, 0, -1, &r, sizeof(r));
+ break;
+
+ case PROC_SCHEDULER_BATCH:
+ log_debug("scheduler-api: PROC_SCHEDULER_BATCH");
+ scheduler_msg_get(&typemask, sizeof(typemask));
+ scheduler_msg_get(&batch.evpcount, sizeof(batch.evpcount));
+ scheduler_msg_end();
+
+ if (batch.evpcount > MAX_BATCH_SIZE)
+ batch.evpcount = MAX_BATCH_SIZE;
+ batch.evpids = evpids;
+
+ handler_batch(typemask, &batch);
+
+ scheduler_msg_add(&batch, sizeof(batch));
+ scheduler_msg_add(evpids, sizeof(*evpids) * batch.evpcount);
+ scheduler_msg_close();
+ break;
+
+ case PROC_SCHEDULER_MESSAGES:
+ log_debug("scheduler-api: PROC_SCHEDULER_MESSAGES");
+ scheduler_msg_get(&msgid, sizeof(msgid));
+ scheduler_msg_get(&sz, sizeof(sz));
+ scheduler_msg_end();
+
+ if (sz > MAX_BATCH_SIZE)
+ sz = MAX_BATCH_SIZE;
+
+ n = handler_messages(msgid, msgids, sz);
+
+ imsg_compose(&ibuf, PROC_SCHEDULER_OK, 0, 0, -1, msgids,
+ n * sizeof(*msgids));
+ break;
+
+ case PROC_SCHEDULER_ENVELOPES:
+ log_debug("scheduler-api: PROC_SCHEDULER_ENVELOPES");
+ scheduler_msg_get(&evpid, sizeof(evpid));
+ scheduler_msg_get(&sz, sizeof(sz));
+ scheduler_msg_end();
+
+ if (sz > MAX_BATCH_SIZE)
+ sz = MAX_BATCH_SIZE;
+
+ n = handler_envelopes(evpid, evpstates, sz);
+
+ imsg_compose(&ibuf, PROC_SCHEDULER_OK, 0, 0, -1, evpstates,
+ n * sizeof(*evpstates));
+ break;
+
+ case PROC_SCHEDULER_SCHEDULE:
+ log_debug("scheduler-api: PROC_SCHEDULER_SCHEDULE");
+ scheduler_msg_get(&evpid, sizeof(evpid));
+ scheduler_msg_end();
+
+ r = handler_schedule(evpid);
+
+ imsg_compose(&ibuf, PROC_SCHEDULER_OK, 0, 0, -1, &r, sizeof(r));
+ break;
+
+ case PROC_SCHEDULER_REMOVE:
+ log_debug("scheduler-api: PROC_SCHEDULER_REMOVE");
+ scheduler_msg_get(&evpid, sizeof(evpid));
+ scheduler_msg_end();
+
+ r = handler_remove(evpid);
+
+ imsg_compose(&ibuf, PROC_SCHEDULER_OK, 0, 0, -1, &r, sizeof(r));
+ break;
+
+ case PROC_SCHEDULER_SUSPEND:
+ log_debug("scheduler-api: PROC_SCHEDULER_SUSPEND");
+ scheduler_msg_get(&evpid, sizeof(evpid));
+ scheduler_msg_end();
+
+ r = handler_suspend(evpid);
+
+ imsg_compose(&ibuf, PROC_SCHEDULER_OK, 0, 0, -1, &r, sizeof(r));
+ break;
+
+ case PROC_SCHEDULER_RESUME:
+ log_debug("scheduler-api: PROC_SCHEDULER_RESUME");
+ scheduler_msg_get(&evpid, sizeof(evpid));
+ scheduler_msg_end();
+
+ r = handler_resume(evpid);
+
+ imsg_compose(&ibuf, PROC_SCHEDULER_OK, 0, 0, -1, &r, sizeof(r));
+ break;
+
+ default:
+ log_warnx("warn: scheduler-api: bad message %i", imsg.hdr.type);
+ fatalx("scheduler-api: exiting");
+ }
+}
+
+void
+scheduler_api_on_init(int(*cb)(void))
+{
+ handler_init = cb;
+}
+
+void
+scheduler_api_on_insert(int(*cb)(struct scheduler_info *))
+{
+ handler_insert = cb;
+}
+
+void
+scheduler_api_on_commit(size_t(*cb)(uint32_t))
+{
+ handler_commit = cb;
+}
+
+void
+scheduler_api_on_rollback(size_t(*cb)(uint32_t))
+{
+ handler_rollback = cb;
+}
+
+void
+scheduler_api_on_update(int(*cb)(struct scheduler_info *))
+{
+ handler_update = cb;
+}
+
+void
+scheduler_api_on_delete(int(*cb)(uint64_t))
+{
+ handler_delete = cb;
+}
+
+void
+scheduler_api_on_batch(int(*cb)(int, struct scheduler_batch *))
+{
+ handler_batch = cb;
+}
+
+void
+scheduler_api_on_messages(size_t(*cb)(uint32_t, uint32_t *, size_t))
+{
+ handler_messages = cb;
+}
+
+void
+scheduler_api_on_envelopes(size_t(*cb)(uint64_t, struct evpstate *, size_t))
+{
+ handler_envelopes = cb;
+}
+
+void
+scheduler_api_on_schedule(int(*cb)(uint64_t))
+{
+ handler_schedule = cb;
+}
+
+void
+scheduler_api_on_remove(int(*cb)(uint64_t))
+{
+ handler_remove = cb;
+}
+
+void
+scheduler_api_on_suspend(int(*cb)(uint64_t))
+{
+ handler_suspend = cb;
+}
+
+void
+scheduler_api_on_resume(int(*cb)(uint64_t))
+{
+ handler_resume = cb;
+}
+
+int
+scheduler_api_dispatch(void)
+{
+ struct passwd *pw;
+ ssize_t n;
+
+ pw = getpwnam(user);
+ if (pw == NULL) {
+ log_warn("scheduler-api: getpwnam");
+ fatalx("scheduler-api: exiting");
+ }
+
+ if (rootpath) {
+ if (chroot(rootpath) == -1) {
+ log_warn("scheduler-api: chroot");
+ fatalx("scheduler-api: exiting");
+ }
+ if (chdir("/") == -1) {
+ log_warn("scheduler-api: chdir");
+ fatalx("scheduler-api: exiting");
+ }
+ }
+
+ if (setgroups(1, &pw->pw_gid) ||
+ setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) ||
+ setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid)) {
+ log_warn("scheduler-api: cannot drop privileges");
+ fatalx("scheduler-api: exiting");
+ }
+
+ imsg_init(&ibuf, 0);
+
+ while (1) {
+ n = imsg_get(&ibuf, &imsg);
+ if (n == -1) {
+ log_warn("warn: scheduler-api: imsg_get");
+ break;
+ }
+
+ if (n) {
+ rdata = imsg.data;
+ rlen = imsg.hdr.len - IMSG_HEADER_SIZE;
+ scheduler_msg_dispatch();
+ imsg_flush(&ibuf);
+ continue;
+ }
+
+ n = imsg_read(&ibuf);
+ if (n == -1) {
+ log_warn("warn: scheduler-api: imsg_read");
+ break;
+ }
+ if (n == 0) {
+ log_warnx("warn: scheduler-api: pipe closed");
+ break;
+ }
+ }
+
+ return (1);
+}
diff --git a/usr.sbin/smtpd/scheduler_backend.c b/usr.sbin/smtpd/scheduler_backend.c
index 34d9d204c71..8df4d3693a3 100644
--- a/usr.sbin/smtpd/scheduler_backend.c
+++ b/usr.sbin/smtpd/scheduler_backend.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: scheduler_backend.c,v 1.10 2013/07/19 15:14:23 eric Exp $ */
+/* $OpenBSD: scheduler_backend.c,v 1.11 2013/07/19 21:34:31 eric Exp $ */
/*
* Copyright (c) 2012 Gilles Chehade <gilles@poolp.org>
@@ -34,6 +34,7 @@
#include "log.h"
extern struct scheduler_backend scheduler_backend_null;
+extern struct scheduler_backend scheduler_backend_proc;
extern struct scheduler_backend scheduler_backend_ramqueue;
struct scheduler_backend *
@@ -41,6 +42,8 @@ scheduler_backend_lookup(const char *name)
{
if (!strcmp(name, "null"))
return &scheduler_backend_null;
+ if (!strcmp(name, "proc"))
+ return &scheduler_backend_proc;
if (!strcmp(name, "ramqueue"))
return &scheduler_backend_ramqueue;
diff --git a/usr.sbin/smtpd/scheduler_null.c b/usr.sbin/smtpd/scheduler_null.c
index 943b762d38e..020f05869b6 100644
--- a/usr.sbin/smtpd/scheduler_null.c
+++ b/usr.sbin/smtpd/scheduler_null.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: scheduler_null.c,v 1.3 2013/07/19 15:14:23 eric Exp $ */
+/* $OpenBSD: scheduler_null.c,v 1.4 2013/07/19 21:34:31 eric Exp $ */
/*
* Copyright (c) 2012 Eric Faurot <eric@openbsd.org>
diff --git a/usr.sbin/smtpd/scheduler_proc.c b/usr.sbin/smtpd/scheduler_proc.c
new file mode 100644
index 00000000000..dd962d93289
--- /dev/null
+++ b/usr.sbin/smtpd/scheduler_proc.c
@@ -0,0 +1,423 @@
+/* $OpenBSD: scheduler_proc.c,v 1.1 2013/07/19 21:34:31 eric Exp $ */
+
+/*
+ * Copyright (c) 2013 Eric Faurot <eric@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 <ctype.h>
+#include <err.h>
+#include <errno.h>
+#include <event.h>
+#include <fcntl.h>
+#include <imsg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "smtpd.h"
+#include "log.h"
+
+static pid_t pid;
+static struct imsgbuf ibuf;
+static struct imsg imsg;
+static size_t rlen;
+static char *rdata;
+
+static const char *execpath = "/usr/libexec/smtpd/backend-scheduler";
+
+static void
+scheduler_proc_call(void)
+{
+ ssize_t n;
+
+ if (imsg_flush(&ibuf) == -1) {
+ log_warn("warn: scheduler-proc: imsg_flush");
+ fatalx("scheduler-proc: exiting");
+ }
+
+ while (1) {
+ if ((n = imsg_get(&ibuf, &imsg)) == -1) {
+ log_warn("warn: scheduler-proc: imsg_get");
+ break;
+ }
+ if (n) {
+ rlen = imsg.hdr.len - IMSG_HEADER_SIZE;
+ rdata = imsg.data;
+
+ if (imsg.hdr.type != PROC_SCHEDULER_OK) {
+ log_warnx("warn: scheduler-proc: bad response");
+ break;
+ }
+ return;
+ }
+
+ if ((n = imsg_read(&ibuf)) == -1) {
+ log_warn("warn: scheduler-proc: imsg_read");
+ break;
+ }
+
+ if (n == 0) {
+ log_warnx("warn: scheduler-proc: pipe closed");
+ break;
+ }
+ }
+
+ fatalx("scheduler-proc: exiting");
+}
+
+static void
+scheduler_proc_read(void *dst, size_t len)
+{
+ if (len > rlen) {
+ log_warnx("warn: scheduler-proc: bad msg len");
+ fatalx("scheduler-proc: exiting");
+ }
+
+ memmove(dst, rdata, len);
+ rlen -= len;
+ rdata += len;
+}
+
+static void
+scheduler_proc_end(void)
+{
+ if (rlen) {
+ log_warnx("warn: scheduler-proc: bogus data");
+ fatalx("scheduler-proc: exiting");
+ }
+ imsg_free(&imsg);
+}
+
+/*
+ * API
+ */
+
+static int
+scheduler_proc_init(void)
+{
+ int sp[2], r;
+ uint32_t version;
+
+ errno = 0;
+
+ if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, sp) < 0) {
+ log_warn("warn: scheduler-proc: socketpair");
+ goto err;
+ }
+
+ if ((pid = fork()) == -1) {
+ log_warn("warn: scheduler-proc: fork");
+ goto err;
+ }
+
+ if (pid == 0) {
+ /* child process */
+ dup2(sp[0], STDIN_FILENO);
+ if (closefrom(STDERR_FILENO + 1) < 0)
+ exit(1);
+
+ execl(execpath, "scheduler-proc", NULL);
+ err(1, "execl");
+ }
+
+ /* parent process */
+ close(sp[0]);
+ imsg_init(&ibuf, sp[1]);
+
+ version = PROC_SCHEDULER_API_VERSION;
+ imsg_compose(&ibuf, PROC_SCHEDULER_INIT, 0, 0, -1,
+ &version, sizeof(version));
+
+ scheduler_proc_call();
+ scheduler_proc_read(&r, sizeof(r));
+ scheduler_proc_end();
+
+ return (r);
+
+err:
+ close(sp[0]);
+ close(sp[1]);
+ fatalx("scheduler-proc: exiting");
+
+ return (0);
+}
+
+static int
+scheduler_proc_insert(struct scheduler_info *si)
+{
+ int r;
+
+ log_debug("debug: scheduler-proc: PROC_SCHEDULER_INSERT");
+
+ imsg_compose(&ibuf, PROC_SCHEDULER_INSERT, 0, 0, -1, si, sizeof(*si));
+
+ scheduler_proc_call();
+ scheduler_proc_read(&r, sizeof(r));
+ scheduler_proc_end();
+
+ return (r);
+}
+
+static size_t
+scheduler_proc_commit(uint32_t msgid)
+{
+ size_t s;
+
+ log_debug("debug: scheduler-proc: PROC_SCHEDULER_COMMIT");
+
+ imsg_compose(&ibuf, PROC_SCHEDULER_COMMIT, 0, 0, -1,
+ &msgid, sizeof(msgid));
+
+ scheduler_proc_call();
+ scheduler_proc_read(&s, sizeof(s));
+ scheduler_proc_end();
+
+ return (s);
+}
+
+static size_t
+scheduler_proc_rollback(uint32_t msgid)
+{
+ size_t s;
+
+ log_debug("debug: scheduler-proc: PROC_SCHEDULER_ROLLBACK");
+
+ imsg_compose(&ibuf, PROC_SCHEDULER_ROLLBACK, 0, 0, -1,
+ &msgid, sizeof(msgid));
+
+ scheduler_proc_call();
+ scheduler_proc_read(&s, sizeof(s));
+ scheduler_proc_end();
+
+ return (s);
+}
+
+static int
+scheduler_proc_update(struct scheduler_info *si)
+{
+ int r;
+
+ log_debug("debug: scheduler-proc: PROC_SCHEDULER_UPDATE");
+
+ imsg_compose(&ibuf, PROC_SCHEDULER_UPDATE, 0, 0, -1, si, sizeof(*si));
+
+ scheduler_proc_call();
+ scheduler_proc_read(&r, sizeof(r));
+ if (r == 1)
+ scheduler_proc_read(si, sizeof(*si));
+ scheduler_proc_end();
+
+ return (r);
+}
+
+static int
+scheduler_proc_delete(uint64_t evpid)
+{
+ int r;
+
+ log_debug("debug: scheduler-proc: PROC_SCHEDULER_DELETE");
+
+ imsg_compose(&ibuf, PROC_SCHEDULER_DELETE, 0, 0, -1,
+ &evpid, sizeof(evpid));
+
+ scheduler_proc_call();
+ scheduler_proc_read(&r, sizeof(r));
+ scheduler_proc_end();
+
+ return (r);
+}
+
+static int
+scheduler_proc_batch(int typemask, struct scheduler_batch *ret)
+{
+ struct ibuf *buf;
+ uint64_t *evpids;
+
+ log_debug("debug: scheduler-proc: PROC_SCHEDULER_BATCH");
+
+ buf = imsg_create(&ibuf, PROC_SCHEDULER_BATCH, 0, 0,
+ sizeof(typemask) + sizeof(ret->evpcount));
+ if (buf == NULL)
+ return (-1);
+ if (imsg_add(buf, &typemask, sizeof(typemask)) == -1)
+ return (-1);
+ if (imsg_add(buf, &ret->evpcount, sizeof(ret->evpcount)) == -1)
+ return (-1);
+ imsg_close(&ibuf, buf);
+
+ evpids = ret->evpids;
+
+ scheduler_proc_call();
+
+ scheduler_proc_read(ret, sizeof(*ret));
+ scheduler_proc_read(evpids, sizeof(*evpids) * ret->evpcount);
+ scheduler_proc_end();
+
+ ret->evpids = evpids;
+
+ if (ret->type == SCHED_NONE)
+ return (0);
+
+ return (1);
+}
+
+static size_t
+scheduler_proc_messages(uint32_t from, uint32_t *dst, size_t size)
+{
+ struct ibuf *buf;
+ size_t s;
+
+ log_debug("debug: scheduler-proc: PROC_SCHEDULER_MESSAGES");
+
+ buf = imsg_create(&ibuf, PROC_SCHEDULER_MESSAGES, 0, 0,
+ sizeof(from) + sizeof(size));
+ if (buf == NULL)
+ return (-1);
+ if (imsg_add(buf, &from, sizeof(from)) == -1)
+ return (-1);
+ if (imsg_add(buf, &size, sizeof(size)) == -1)
+ return (-1);
+ imsg_close(&ibuf, buf);
+
+ scheduler_proc_call();
+
+ s = rlen / sizeof(*dst);
+ scheduler_proc_read(dst, s * sizeof(*dst));
+ scheduler_proc_end();
+
+ return (s);
+}
+
+static size_t
+scheduler_proc_envelopes(uint64_t from, struct evpstate *dst, size_t size)
+{
+ struct ibuf *buf;
+ size_t s;
+
+ log_debug("debug: scheduler-proc: PROC_SCHEDULER_ENVELOPES");
+
+ buf = imsg_create(&ibuf, PROC_SCHEDULER_ENVELOPES, 0, 0,
+ sizeof(from) + sizeof(size));
+ if (buf == NULL)
+ return (-1);
+ if (imsg_add(buf, &from, sizeof(from)) == -1)
+ return (-1);
+ if (imsg_add(buf, &size, sizeof(size)) == -1)
+ return (-1);
+ imsg_close(&ibuf, buf);
+
+ scheduler_proc_call();
+
+ s = rlen / sizeof(*dst);
+ scheduler_proc_read(dst, s * sizeof(*dst));
+ scheduler_proc_end();
+
+ return (s);
+}
+
+static int
+scheduler_proc_schedule(uint64_t evpid)
+{
+ int r;
+
+ log_debug("debug: scheduler-proc: PROC_SCHEDULER_SCHEDULE");
+
+ imsg_compose(&ibuf, PROC_SCHEDULER_SCHEDULE, 0, 0, -1,
+ &evpid, sizeof(evpid));
+
+ scheduler_proc_call();
+
+ scheduler_proc_read(&r, sizeof(r));
+ scheduler_proc_end();
+
+ return (r);
+}
+
+static int
+scheduler_proc_remove(uint64_t evpid)
+{
+ int r;
+
+ log_debug("debug: scheduler-proc: PROC_SCHEDULER_REMOVE");
+
+ imsg_compose(&ibuf, PROC_SCHEDULER_REMOVE, 0, 0, -1,
+ &evpid, sizeof(evpid));
+
+ scheduler_proc_call();
+
+ scheduler_proc_read(&r, sizeof(r));
+ scheduler_proc_end();
+
+ return (r);
+}
+
+static int
+scheduler_proc_suspend(uint64_t evpid)
+{
+ int r;
+
+ log_debug("debug: scheduler-proc: PROC_SCHEDULER_SUSPEND");
+
+ imsg_compose(&ibuf, PROC_SCHEDULER_SUSPEND, 0, 0, -1,
+ &evpid, sizeof(evpid));
+
+ scheduler_proc_call();
+
+ scheduler_proc_read(&r, sizeof(r));
+ scheduler_proc_end();
+
+ return (r);
+}
+
+static int
+scheduler_proc_resume(uint64_t evpid)
+{
+ int r;
+
+ log_debug("debug: scheduler-proc: PROC_SCHEDULER_RESUME");
+
+ imsg_compose(&ibuf, PROC_SCHEDULER_RESUME, 0, 0, -1,
+ &evpid, sizeof(evpid));
+
+ scheduler_proc_call();
+
+ scheduler_proc_read(&r, sizeof(r));
+ scheduler_proc_end();
+
+ return (r);
+}
+
+struct scheduler_backend scheduler_backend_proc = {
+ scheduler_proc_init,
+ scheduler_proc_insert,
+ scheduler_proc_commit,
+ scheduler_proc_rollback,
+ scheduler_proc_update,
+ scheduler_proc_delete,
+ scheduler_proc_batch,
+ scheduler_proc_messages,
+ scheduler_proc_envelopes,
+ scheduler_proc_schedule,
+ scheduler_proc_remove,
+ scheduler_proc_suspend,
+ scheduler_proc_resume,
+};
diff --git a/usr.sbin/smtpd/scheduler_ramqueue.c b/usr.sbin/smtpd/scheduler_ramqueue.c
index 482928d8ed5..4efd88d132b 100644
--- a/usr.sbin/smtpd/scheduler_ramqueue.c
+++ b/usr.sbin/smtpd/scheduler_ramqueue.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: scheduler_ramqueue.c,v 1.29 2013/07/19 15:14:23 eric Exp $ */
+/* $OpenBSD: scheduler_ramqueue.c,v 1.30 2013/07/19 21:34:31 eric Exp $ */
/*
* Copyright (c) 2012 Gilles Chehade <gilles@poolp.org>
diff --git a/usr.sbin/smtpd/smtpd-api.h b/usr.sbin/smtpd/smtpd-api.h
index 7c4f4f6cf58..b7353667b6d 100644
--- a/usr.sbin/smtpd/smtpd-api.h
+++ b/usr.sbin/smtpd/smtpd-api.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: smtpd-api.h,v 1.7 2013/07/19 20:37:07 eric Exp $ */
+/* $OpenBSD: smtpd-api.h,v 1.8 2013/07/19 21:34:31 eric Exp $ */
/*
* Copyright (c) 2013 Eric Faurot <eric@openbsd.org>
@@ -105,6 +105,81 @@ enum {
PROC_QUEUE_ENVELOPE_WALK,
};
+#define PROC_SCHEDULER_API_VERSION 1
+
+struct scheduler_info;
+struct scheduler_batch;
+
+enum {
+ PROC_SCHEDULER_OK,
+ PROC_SCHEDULER_FAIL,
+ PROC_SCHEDULER_INIT,
+ PROC_SCHEDULER_INSERT,
+ PROC_SCHEDULER_COMMIT,
+ PROC_SCHEDULER_ROLLBACK,
+ PROC_SCHEDULER_UPDATE,
+ PROC_SCHEDULER_DELETE,
+ PROC_SCHEDULER_BATCH,
+ PROC_SCHEDULER_MESSAGES,
+ PROC_SCHEDULER_ENVELOPES,
+ PROC_SCHEDULER_SCHEDULE,
+ PROC_SCHEDULER_REMOVE,
+ PROC_SCHEDULER_SUSPEND,
+ PROC_SCHEDULER_RESUME,
+};
+
+enum envelope_flags {
+ EF_AUTHENTICATED = 0x01,
+ EF_BOUNCE = 0x02,
+ EF_INTERNAL = 0x04, /* Internal expansion forward */
+
+ /* runstate, not saved on disk */
+
+ EF_PENDING = 0x10,
+ EF_INFLIGHT = 0x20,
+ EF_SUSPEND = 0x40,
+};
+
+struct evpstate {
+ uint64_t evpid;
+ uint16_t flags;
+ uint16_t retry;
+ time_t time;
+};
+
+enum delivery_type {
+ D_MDA,
+ D_MTA,
+ D_BOUNCE,
+};
+
+struct scheduler_info {
+ uint64_t evpid;
+ enum delivery_type type;
+ uint16_t retry;
+ time_t creation;
+ time_t expire;
+ time_t lasttry;
+ time_t lastbounce;
+ time_t nexttry;
+ uint8_t penalty;
+};
+
+#define SCHED_NONE 0x00
+#define SCHED_DELAY 0x01
+#define SCHED_REMOVE 0x02
+#define SCHED_EXPIRE 0x04
+#define SCHED_BOUNCE 0x08
+#define SCHED_MDA 0x10
+#define SCHED_MTA 0x20
+
+struct scheduler_batch {
+ int type;
+ time_t delay;
+ size_t evpcount;
+ uint64_t *evpids;
+};
+
#define PROC_TABLE_API_VERSION 1
enum table_service {
@@ -196,6 +271,22 @@ void queue_api_on_envelope_load(int(*)(uint64_t, char *, size_t));
void queue_api_on_envelope_walk(int(*)(uint64_t *, char *, size_t));
int queue_api_dispatch(void);
+/* scheduler */
+void scheduler_api_on_init(int(*)(void));
+void scheduler_api_on_insert(int(*)(struct scheduler_info *));
+void scheduler_api_on_commit(size_t(*)(uint32_t));
+void scheduler_api_on_rollback(size_t(*)(uint32_t));
+void scheduler_api_on_update(int(*)(struct scheduler_info *));
+void scheduler_api_on_delete(int(*)(uint64_t));
+void scheduler_api_on_batch(int(*)(int, struct scheduler_batch *));
+void scheduler_api_on_messages(size_t(*)(uint32_t, uint32_t *, size_t));
+void scheduler_api_on_envelopes(size_t(*)(uint64_t, struct evpstate *, size_t));
+void scheduler_api_on_schedule(int(*)(uint64_t));
+void scheduler_api_on_remove(int(*)(uint64_t));
+void scheduler_api_on_suspend(int(*)(uint64_t));
+void scheduler_api_on_resume(int(*)(uint64_t));
+int scheduler_api_dispatch(void);
+
/* table */
void table_api_on_update(int(*)(void));
void table_api_on_check(int(*)(int, const char *));
diff --git a/usr.sbin/smtpd/smtpd.h b/usr.sbin/smtpd/smtpd.h
index 9dbe77e26e0..961b8a78ab4 100644
--- a/usr.sbin/smtpd/smtpd.h
+++ b/usr.sbin/smtpd/smtpd.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: smtpd.h,v 1.421 2013/07/19 21:14:52 eric Exp $ */
+/* $OpenBSD: smtpd.h,v 1.422 2013/07/19 21:34:31 eric Exp $ */
/*
* Copyright (c) 2008 Gilles Chehade <gilles@poolp.org>
@@ -356,12 +356,6 @@ struct rule {
time_t r_qexpire;
};
-enum delivery_type {
- D_MDA,
- D_MTA,
- D_BOUNCE,
-};
-
struct delivery_mda {
enum action_type method;
char usertable[SMTPD_MAXPATHLEN];
@@ -425,18 +419,6 @@ struct expand {
struct expandnode *parent;
};
-enum envelope_flags {
- EF_AUTHENTICATED = 0x01,
- EF_BOUNCE = 0x02,
- EF_INTERNAL = 0x04, /* Internal expansion forward */
-
- /* runstate, not saved on disk */
-
- EF_PENDING = 0x10,
- EF_INFLIGHT = 0x20,
- EF_SUSPEND = 0x40,
-};
-
#define SMTPD_ENVELOPE_VERSION 1
struct envelope {
TAILQ_ENTRY(envelope) entry;
@@ -819,40 +801,6 @@ struct delivery_backend {
void (*open)(struct deliver *);
};
-struct evpstate {
- uint64_t evpid;
- uint16_t flags;
- uint16_t retry;
- time_t time;
-};
-
-struct scheduler_info {
- uint64_t evpid;
- enum delivery_type type;
- uint16_t retry;
- time_t creation;
- time_t expire;
- time_t lasttry;
- time_t lastbounce;
- time_t nexttry;
- uint8_t penalty;
-};
-
-#define SCHED_NONE 0x00
-#define SCHED_DELAY 0x01
-#define SCHED_REMOVE 0x02
-#define SCHED_EXPIRE 0x04
-#define SCHED_BOUNCE 0x08
-#define SCHED_MDA 0x10
-#define SCHED_MTA 0x20
-
-struct scheduler_batch {
- int type;
- time_t delay;
- size_t evpcount;
- uint64_t *evpids;
-};
-
struct scheduler_backend {
int (*init)(void);
diff --git a/usr.sbin/smtpd/smtpd/Makefile b/usr.sbin/smtpd/smtpd/Makefile
index fa024ced24e..c6ac4b63cfd 100644
--- a/usr.sbin/smtpd/smtpd/Makefile
+++ b/usr.sbin/smtpd/smtpd/Makefile
@@ -1,4 +1,4 @@
-# $OpenBSD: Makefile,v 1.64 2013/07/19 21:14:52 eric Exp $
+# $OpenBSD: Makefile,v 1.65 2013/07/19 21:34:31 eric Exp $
.PATH: ${.CURDIR}/..
@@ -31,6 +31,7 @@ SRCS+= queue_proc.c
SRCS+= queue_ram.c
SRCS+= scheduler_ramqueue.c
SRCS+= scheduler_null.c
+SRCS+= scheduler_proc.c
SRCS+= stat_ramstat.c
MAN= smtpd.8 smtpd.conf.5