remove dead files
authoreric <eric@openbsd.org>
Tue, 20 May 2014 08:09:04 +0000 (08:09 +0000)
committereric <eric@openbsd.org>
Tue, 20 May 2014 08:09:04 +0000 (08:09 +0000)
usr.sbin/smtpd/mfa.c [deleted file]
usr.sbin/smtpd/mfa_session.c [deleted file]

diff --git a/usr.sbin/smtpd/mfa.c b/usr.sbin/smtpd/mfa.c
deleted file mode 100644 (file)
index 6372a4d..0000000
+++ /dev/null
@@ -1,397 +0,0 @@
-/*     $OpenBSD: mfa.c,v 1.82 2014/04/04 16:10:42 eric Exp $   */
-
-/*
- * Copyright (c) 2008 Gilles Chehade <gilles@poolp.org>
- * Copyright (c) 2008 Pierre-Yves Ritschard <pyr@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/wait.h>
-#include <sys/queue.h>
-#include <sys/tree.h>
-#include <sys/socket.h>
-
-#include <err.h>
-#include <errno.h>
-#include <event.h>
-#include <imsg.h>
-#include <inttypes.h>
-#include <pwd.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include "smtpd.h"
-#include "log.h"
-
-struct mfa_tx {
-       uint64_t         reqid;
-       struct io        io;
-       struct iobuf     iobuf;
-       FILE            *ofile;
-       size_t           datain;
-       size_t           datalen;
-       int              eom;
-       int              error;
-};
-
-static void mfa_imsg(struct mproc *, struct imsg *);
-static void mfa_shutdown(void);
-static void mfa_sig_handler(int, short, void *);
-static void mfa_tx_io(struct io *, int);
-static int mfa_tx(uint64_t, int);
-static void mfa_tx_done(struct mfa_tx *);
-
-struct tree tx_tree;
-
-static void
-mfa_imsg(struct mproc *p, struct imsg *imsg)
-{
-       struct sockaddr_storage  local, remote;
-       struct mailaddr          maddr;
-       struct msg               m;
-       const char              *line, *hostname;
-       uint64_t                 reqid;
-       uint32_t                 datalen; /* XXX make it off_t? */
-       int                      v, success, fdout;
-
-       if (p->proc == PROC_PONY) {
-               switch (imsg->hdr.type) {
-               case IMSG_SMTP_REQ_CONNECT:
-                       m_msg(&m, imsg);
-                       m_get_id(&m, &reqid);
-                       m_get_sockaddr(&m, (struct sockaddr *)&local);
-                       m_get_sockaddr(&m, (struct sockaddr *)&remote);
-                       m_get_string(&m, &hostname);
-                       m_end(&m);
-                       mfa_filter_connect(reqid, (struct sockaddr *)&local,
-                           (struct sockaddr *)&remote, hostname);
-                       return;
-
-               case IMSG_SMTP_REQ_HELO:
-                       m_msg(&m, imsg);
-                       m_get_id(&m, &reqid);
-                       m_get_string(&m, &line);
-                       m_end(&m);
-                       mfa_filter_line(reqid, HOOK_HELO, line);
-                       return;
-
-               case IMSG_SMTP_REQ_MAIL:
-                       m_msg(&m, imsg);
-                       m_get_id(&m, &reqid);
-                       m_get_mailaddr(&m, &maddr);
-                       m_end(&m);
-                       mfa_filter_mailaddr(reqid, HOOK_MAIL, &maddr);
-                       return;
-
-               case IMSG_SMTP_REQ_RCPT:
-                       m_msg(&m, imsg);
-                       m_get_id(&m, &reqid);
-                       m_get_mailaddr(&m, &maddr);
-                       m_end(&m);
-                       mfa_filter_mailaddr(reqid, HOOK_RCPT, &maddr);
-                       return;
-
-               case IMSG_SMTP_REQ_DATA:
-                       m_msg(&m, imsg);
-                       m_get_id(&m, &reqid);
-                       m_end(&m);
-                       mfa_filter(reqid, HOOK_DATA);
-                       return;
-
-               case IMSG_SMTP_REQ_EOM:
-                       m_msg(&m, imsg);
-                       m_get_id(&m, &reqid);
-                       m_get_u32(&m, &datalen);
-                       m_end(&m);
-                       mfa_filter_eom(reqid, HOOK_EOM, datalen);
-                       return;
-
-               case IMSG_SMTP_EVENT_RSET:
-                       m_msg(&m, imsg);
-                       m_get_id(&m, &reqid);
-                       m_end(&m);
-                       mfa_filter_event(reqid, HOOK_RESET);
-                       return;
-
-               case IMSG_SMTP_EVENT_COMMIT:
-                       m_msg(&m, imsg);
-                       m_get_id(&m, &reqid);
-                       m_end(&m);
-                       mfa_filter_event(reqid, HOOK_COMMIT);
-                       return;
-
-               case IMSG_SMTP_EVENT_ROLLBACK:
-                       m_msg(&m, imsg);
-                       m_get_id(&m, &reqid);
-                       m_end(&m);
-                       mfa_filter_event(reqid, HOOK_ROLLBACK);
-                       return;
-
-               case IMSG_SMTP_EVENT_DISCONNECT:
-                       m_msg(&m, imsg);
-                       m_get_id(&m, &reqid);
-                       m_end(&m);
-                       mfa_filter_event(reqid, HOOK_DISCONNECT);
-                       return;
-               }
-       }
-
-       if (p->proc == PROC_QUEUE) {
-               switch (imsg->hdr.type) {
-               case IMSG_SMTP_MESSAGE_OPEN: /* XXX bogus */
-                       m_msg(&m, imsg);
-                       m_get_id(&m, &reqid);
-                       m_get_int(&m, &success);
-                       m_end(&m);
-
-                       fdout = mfa_tx(reqid, imsg->fd);
-                       mfa_build_fd_chain(reqid, fdout);
-                       return;
-               }
-       }
-
-       if (p->proc == PROC_PARENT) {
-               switch (imsg->hdr.type) {
-               case IMSG_CONF_START:
-                       return;
-
-               case IMSG_CONF_END:
-                       mfa_filter_init();
-                       return;
-                       
-               case IMSG_CTL_VERBOSE:
-                       m_msg(&m, imsg);
-                       m_get_int(&m, &v);
-                       m_end(&m);
-                       log_verbose(v);
-                       return;
-
-               case IMSG_CTL_PROFILE:
-                       m_msg(&m, imsg);
-                       m_get_int(&m, &v);
-                       m_end(&m);
-                       profiling = v;
-                       return;
-               }
-       }
-
-       errx(1, "mfa_imsg: unexpected %s imsg", imsg_to_str(imsg->hdr.type));
-}
-
-static void
-mfa_sig_handler(int sig, short event, void *p)
-{
-       switch (sig) {
-       case SIGINT:
-       case SIGTERM:
-               mfa_shutdown();
-               break;
-
-       case SIGCHLD:
-               fatalx("unexpected SIGCHLD");
-               break;
-
-       default:
-               fatalx("mfa_sig_handler: unexpected signal");
-       }
-}
-
-static void
-mfa_shutdown(void)
-{
-       pid_t pid;
-
-       do {
-               pid = waitpid(WAIT_MYPGRP, NULL, 0);
-       } while (pid != -1 || (pid == -1 && errno == EINTR));
-
-       log_info("info: mail filter exiting");
-       _exit(0);
-}
-
-pid_t
-mfa(void)
-{
-       pid_t            pid;
-       struct passwd   *pw;
-       struct event     ev_sigint;
-       struct event     ev_sigterm;
-       struct event     ev_sigchld;
-
-       switch (pid = fork()) {
-       case -1:
-               fatal("filter: cannot fork");
-       case 0:
-               post_fork(PROC_MFA);
-               break;
-       default:
-               return (pid);
-       }
-
-       mfa_filter_prepare();
-
-       purge_config(PURGE_EVERYTHING);
-
-       if ((pw =  getpwnam(SMTPD_USER)) == NULL)
-               fatalx("unknown user " SMTPD_USER);
-
-       config_process(PROC_MFA);
-
-       if (chroot(PATH_CHROOT) == -1)
-               fatal("scheduler: chroot");
-       if (chdir("/") == -1)
-               fatal("scheduler: chdir(\"/\")");
-
-       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))
-               fatal("filter: cannot drop privileges");
-
-       imsg_callback = mfa_imsg;
-       event_init();
-
-       signal_set(&ev_sigint, SIGINT, mfa_sig_handler, NULL);
-       signal_set(&ev_sigterm, SIGTERM, mfa_sig_handler, NULL);
-       signal_set(&ev_sigchld, SIGCHLD, mfa_sig_handler, NULL);
-       signal_add(&ev_sigint, NULL);
-       signal_add(&ev_sigterm, NULL);
-       signal_add(&ev_sigchld, NULL);
-       signal(SIGPIPE, SIG_IGN);
-       signal(SIGHUP, SIG_IGN);
-
-       config_peer(PROC_PARENT);
-       config_peer(PROC_CONTROL);
-       config_peer(PROC_PONY);
-       config_done();
-
-       mproc_disable(p_pony);
-
-       if (event_dispatch() < 0)
-               fatal("event_dispatch");
-       mfa_shutdown();
-
-       return (0);
-}
-
-void
-mfa_ready(void)
-{
-       log_debug("debug: mfa ready");
-       mproc_enable(p_pony);
-}
-
-static int
-mfa_tx(uint64_t reqid, int fdout)
-{
-       struct mfa_tx   *tx;
-       int              sp[2];
-
-       if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, sp) == -1) {
-               log_warn("warn: mfa: socketpair");
-               return (-1);
-       }
-
-       tx = xcalloc(1, sizeof(*tx), "mfa_tx");
-
-       if ((tx->ofile = fdopen(fdout, "w")) == NULL) {
-               log_warn("warn: mfa: fdopen");
-               free(tx);
-               close(sp[0]);
-               close(sp[1]);
-               return (-1);
-       }
-
-       iobuf_init(&tx->iobuf, 0, 0);
-       io_init(&tx->io, sp[0], tx, mfa_tx_io, &tx->iobuf);
-       io_set_read(&tx->io);
-       tx->reqid = reqid;
-       tree_xset(&tx_tree, reqid, tx);
-
-       return (sp[1]);
-}
-
-static void
-mfa_tx_io(struct io *io, int evt)
-{
-       struct mfa_tx   *tx = io->arg;
-       size_t           len, n;
-       char            *data;
-
-       switch (evt) {
-       case IO_DATAIN:
-               data = iobuf_data(&tx->iobuf);
-               len = iobuf_len(&tx->iobuf);
-               log_debug("debug: mfa: tx data (%zu) for req %016"PRIx64,
-                   len, tx->reqid);
-               n = fwrite(data, 1, len, tx->ofile);
-               if (n != len) {
-                       tx->error = 1;
-                       break;
-               }
-               tx->datain += n;
-               iobuf_drop(&tx->iobuf, n);
-               iobuf_normalize(&tx->iobuf);
-               return;
-
-       case IO_DISCONNECTED:
-               log_debug("debug: mfa: tx done for req %016"PRIx64,
-                   tx->reqid);
-               break;
-
-       default:
-               log_debug("debug: mfa: tx error for req %016"PRIx64,
-                   tx->reqid);
-               tx->error = 1;
-               break;
-       }
-
-       io_clear(&tx->io);
-       iobuf_clear(&tx->iobuf);
-       fclose(tx->ofile);
-       tx->ofile = NULL;
-       if (tx->eom)
-               mfa_tx_done(tx);
-}
-
-static void
-mfa_tx_done(struct mfa_tx *tx)
-{
-       log_debug("debug: mfa: tx done for %016"PRIx64, tx->reqid);
-
-       if (!tx->error && tx->datain != tx->datalen) {
-               log_debug("debug: mfa: tx datalen mismatch: %zu/%zu",
-                   tx->datain, tx->datalen);
-               tx->error = 1;
-       }
-
-       if (tx->error) {
-               log_debug("debug: mfa: tx error");
-
-               m_create(p_pony, IMSG_MFA_SMTP_RESPONSE, 0, 0, -1);
-               m_add_id(p_pony, tx->reqid);
-               m_add_int(p_pony, MFA_FAIL);
-               m_add_u32(p_pony, 0);
-               m_add_string(p_pony, "Internal server error");
-               m_close(p_pony);
-       }
-#if 0
-       else
-               mfa_filter(tx->reqid, HOOK_EOM);
-#endif
-       free(tx);
-}
diff --git a/usr.sbin/smtpd/mfa_session.c b/usr.sbin/smtpd/mfa_session.c
deleted file mode 100644 (file)
index 7fe9a45..0000000
+++ /dev/null
@@ -1,821 +0,0 @@
-/*     $OpenBSD: mfa_session.c,v 1.22 2014/04/19 13:18:14 gilles Exp $ */
-
-/*
- * Copyright (c) 2011 Gilles Chehade <gilles@poolp.org>
- * Copyright (c) 2012 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/socket.h>
-#include <sys/wait.h>
-
-#include <netinet/in.h>
-
-#include <ctype.h>
-#include <errno.h>
-#include <event.h>
-#include <imsg.h>
-#include <inttypes.h>
-#include <resolv.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include "smtpd.h"
-#include "log.h"
-
-enum {
-       QT_QUERY,
-       QT_EVENT,
-};
-
-enum {
-       QUERY_READY,
-       QUERY_WAITING,
-       QUERY_RUNNING,
-       QUERY_DONE
-};
-
-
-struct mfa_filterproc {
-       TAILQ_ENTRY(mfa_filterproc)      entry;
-       struct mproc                     mproc;
-       int                              hooks;
-       int                              flags;
-       int                              ready;
-};
-
-struct mfa_filter {
-       TAILQ_ENTRY(mfa_filter)          entry;
-       struct mfa_filterproc           *proc;
-};
-TAILQ_HEAD(mfa_filters, mfa_filter);
-
-struct mfa_session {
-       uint64_t                                 id;
-       int                                      terminate;
-       TAILQ_HEAD(mfa_queries, mfa_query)       queries;
-       struct mfa_filters                      *filters;
-       struct mfa_filter                       *fcurr;
-};
-
-struct mfa_query {
-       uint64_t                 qid;
-       int                      type;
-       int                      hook;
-       struct mfa_session      *session;
-       TAILQ_ENTRY(mfa_query)   entry;
-
-       int                      state;
-       int                      hasrun;
-       struct mfa_filter       *current;
-       struct tree              notify;  /* list of filters to notify */
-
-       /* current data */
-       union {
-               struct {
-                       struct sockaddr_storage  local;
-                       struct sockaddr_storage  remote;
-                       char                     hostname[SMTPD_MAXHOSTNAMELEN];
-               } connect;
-               char                    line[SMTPD_MAXLINESIZE];
-               struct mailaddr         maddr;
-               size_t                  datalen;
-       } u;
-
-       /* current response */
-       struct {
-               int      status;
-               int      code;
-               char    *response;      
-       } smtp;
-};
-
-static void mfa_filter_imsg(struct mproc *, struct imsg *);
-static struct mfa_query *mfa_query(struct mfa_session *, int, int);
-static void mfa_drain_query(struct mfa_query *);
-static void mfa_run_query(struct mfa_filter *, struct mfa_query *);
-static void mfa_set_fdout(struct mfa_session *, int);
-
-static TAILQ_HEAD(, mfa_filterproc)    procs;
-struct dict                            chains;
-
-static const char * mfa_query_to_text(struct mfa_query *);
-static const char * mfa_filter_to_text(struct mfa_filter *);
-static const char * mfa_filterproc_to_text(struct mfa_filterproc *);
-static const char * type_to_str(int);
-static const char * hook_to_str(int);
-static const char * status_to_str(int);
-static const char * filterimsg_to_str(int);
-
-struct tree    sessions;
-struct tree    queries;
-
-
-static void
-mfa_extend_chain(struct mfa_filters *chain, const char *name)
-{
-       struct mfa_filter       *n;
-       struct mfa_filters      *fchain;
-       struct filter           *fconf;
-       int                      i;
-
-       fconf = dict_xget(&env->sc_filters, name);
-       if (fconf->chain) {
-               log_debug("mfa:     extending with \"%s\"", name);
-               for (i = 0; i < MAX_FILTER_PER_CHAIN; i++) {
-                       if (!fconf->filters[i][0])
-                               break;
-                       mfa_extend_chain(chain, fconf->filters[i]);
-               }
-       }
-       else {
-               log_debug("mfa:     adding filter \"%s\"", name);
-               n = xcalloc(1, sizeof(*n), "mfa_extend_chain");
-               fchain = dict_get(&chains, name);
-               n->proc = TAILQ_FIRST(fchain)->proc;
-               TAILQ_INSERT_TAIL(chain, n, entry);
-       }
-}
-
-void
-mfa_filter_prepare(void)
-{
-       static int               prepare = 0;
-       struct filter           *filter;
-       void                    *iter;
-       struct mfa_filterproc   *proc;
-       struct mfa_filters      *fchain;
-       struct mfa_filter       *f;
-       struct mproc            *p;
-       int                      done, i;
-
-       if (prepare)
-               return;
-       prepare = 1;
-
-       TAILQ_INIT(&procs);
-       dict_init(&chains);
-
-       log_debug("mfa: building simple chains...");
-
-       /* create all filter proc and associated chains */
-       iter = NULL;
-       while (dict_iter(&env->sc_filters, &iter, NULL, (void **)&filter)) {
-               if (filter->chain)
-                       continue;
-
-               log_debug("mfa: building simple chain \"%s\"", filter->name);
-
-               proc = xcalloc(1, sizeof(*proc), "mfa_filter_init");
-               p = &proc->mproc;
-               p->handler = mfa_filter_imsg;
-               p->proc = PROC_FILTER;
-               p->name = xstrdup(filter->name, "mfa_filter_init");
-               p->data = proc;
-               if (mproc_fork(p, filter->path, filter->name) < 0)
-                       fatalx("mfa_filter_init");
-
-               log_debug("mfa: registering proc \"%s\"", filter->name);
-
-               f = xcalloc(1, sizeof(*f), "mfa_filter_init");
-               f->proc = proc;
-
-               TAILQ_INSERT_TAIL(&procs, proc, entry);
-               fchain = xcalloc(1, sizeof(*fchain), "mfa_filter_prepare");
-               TAILQ_INIT(fchain);
-               TAILQ_INSERT_TAIL(fchain, f, entry);
-               dict_xset(&chains, filter->name, fchain);
-               filter->done = 1;
-       }
-
-       log_debug("mfa: building complex chains...");
-
-       /* resolve all chains */
-       done = 0;
-       while (!done) {
-               done = 1;
-               iter = NULL;
-               while (dict_iter(&env->sc_filters, &iter, NULL, (void **)&filter)) {
-                       if (filter->done)
-                               continue;
-                       done = 0;
-                       filter->done = 1;
-                       for (i = 0; i < MAX_FILTER_PER_CHAIN; i++) {
-                               if (!filter->filters[i][0])
-                                       break;
-                               if (!dict_get(&chains, filter->filters[i])) {
-                                       filter->done = 0;
-                                       break;
-                               }
-                       }
-                       if (filter->done == 0)
-                               continue;
-                       fchain = xcalloc(1, sizeof(*fchain), "mfa_filter_prepare");
-                       TAILQ_INIT(fchain);
-                       log_debug("mfa: building chain \"%s\"...", filter->name);
-                       for (i = 0; i < MAX_FILTER_PER_CHAIN; i++) {
-                               if (!filter->filters[i][0])
-                                       break;
-                               mfa_extend_chain(fchain, filter->filters[i]);
-                       }
-                       log_debug("mfa: done building chain \"%s\"", filter->name);
-                       dict_xset(&chains, filter->name, fchain);
-               }
-       }
-       log_debug("mfa: done building complex chains");
-
-       if (dict_get(&chains, "default") == NULL) {
-               log_debug("mfa: done building default chain");
-               fchain = xcalloc(1, sizeof(*fchain), "mfa_filter_prepare");
-               TAILQ_INIT(fchain);
-               dict_xset(&chains, "default", fchain);
-       }
-}
-
-void
-mfa_filter_init(void)
-{
-       static int               init = 0;
-       struct mfa_filterproc   *p;
-
-       if (init)
-               return;
-       init = 1;
-
-       tree_init(&sessions);
-       tree_init(&queries);
-
-       TAILQ_FOREACH(p, &procs, entry) {
-               m_create(&p->mproc, IMSG_FILTER_REGISTER, 0, 0, -1);
-               m_add_u32(&p->mproc, FILTER_API_VERSION);
-               m_add_string(&p->mproc, p->mproc.name);
-               m_close(&p->mproc);
-               mproc_enable(&p->mproc);
-       }
-
-       if (TAILQ_FIRST(&procs) == NULL)
-               mfa_ready();
-}
-
-void
-mfa_filter_connect(uint64_t id, const struct sockaddr *local,
-       const struct sockaddr *remote, const char *host)
-{
-       struct mfa_session      *s;
-       struct mfa_query        *q;
-
-       s = xcalloc(1, sizeof(*s), "mfa_query_connect");
-       s->id = id;
-       s->filters = dict_xget(&chains, "default");
-       TAILQ_INIT(&s->queries);
-       tree_xset(&sessions, s->id, s);
-
-       q = mfa_query(s, QT_QUERY, HOOK_CONNECT);
-
-       memmove(&q->u.connect.local, local, local->sa_len);
-       memmove(&q->u.connect.remote, remote, remote->sa_len);
-       if (strlcpy(q->u.connect.hostname, host,
-               sizeof(q->u.connect.hostname)) >=
-           sizeof(q->u.connect.hostname))
-               fatalx("hostname too large");
-
-       q->smtp.status = MFA_OK;
-       q->smtp.code = 0;
-       q->smtp.response = NULL;
-
-       mfa_drain_query(q);
-}
-
-void
-mfa_filter_event(uint64_t id, int hook)
-{
-       struct mfa_session      *s;
-       struct mfa_query        *q;
-
-       /* On disconnect, the session is virtualy dead */
-       if (hook == HOOK_DISCONNECT)
-               s = tree_xpop(&sessions, id);
-       else
-               s = tree_xget(&sessions, id);
-       q = mfa_query(s, QT_EVENT, hook);
-
-       mfa_drain_query(q);
-}
-
-void
-mfa_filter_mailaddr(uint64_t id, int hook, const struct mailaddr *maddr)
-{
-       struct mfa_session      *s;
-       struct mfa_query        *q;
-
-       s = tree_xget(&sessions, id);
-       q = mfa_query(s, QT_QUERY, hook);
-
-       if (strlcpy(q->u.maddr.user, maddr->user, sizeof(q->u.maddr.user))
-           >= sizeof(q.u.maddr.user))
-               fatalx("username too large");
-       if (strlcpy(q->u.maddr.domain, maddr->domain, sizeof(q->u.maddr.domain))
-           >= sizeof(q.u.maddr.domain))
-               fatalx("hostname too large");
-
-       mfa_drain_query(q);
-}
-
-void
-mfa_filter_line(uint64_t id, int hook, const char *line)
-{
-       struct mfa_session      *s;
-       struct mfa_query        *q;
-
-       s = tree_xget(&sessions, id);
-       q = mfa_query(s, QT_QUERY, hook);
-
-       if (strlcpy(q->u.line, line, sizeof(q->u.line))
-           >= sizeof(q->u.line))
-               fatalx("line too large");
-
-       mfa_drain_query(q);
-}
-
-void
-mfa_filter_eom(uint64_t id, int hook, size_t datalen)
-{
-       struct mfa_session      *s;
-       struct mfa_query        *q;
-
-       s = tree_xget(&sessions, id);
-       q = mfa_query(s, QT_QUERY, hook);
-       q->u.datalen = datalen;
-
-       mfa_drain_query(q);
-}
-
-void
-mfa_filter(uint64_t id, int hook)
-{
-       struct mfa_session      *s;
-       struct mfa_query        *q;
-
-       s = tree_xget(&sessions, id);
-       q = mfa_query(s, QT_QUERY, hook);
-
-       mfa_drain_query(q);
-}
-
-static void
-mfa_set_fdout(struct mfa_session *s, int fdout)
-{
-       struct mproc    *p;
-
-       while(s->fcurr) {
-               if (s->fcurr->proc->hooks & HOOK_DATALINE) {
-                       log_trace(TRACE_MFA, "mfa: sending fd %d to %s", fdout, mfa_filter_to_text(s->fcurr));
-                       p = &s->fcurr->proc->mproc;
-                       m_create(p, IMSG_FILTER_PIPE_SETUP, 0, 0, fdout);
-                       m_add_id(p, s->id);
-                       m_close(p);
-                       return;
-               }
-               s->fcurr = TAILQ_PREV(s->fcurr, mfa_filters, entry);
-       }
-
-       log_trace(TRACE_MFA, "mfa: chain input is %d", fdout);
-
-       m_create(p_pony, IMSG_SMTP_MESSAGE_OPEN, 0, 0, fdout); /* XXX bogus */
-       m_add_id(p_pony, s->id);
-       m_add_int(p_pony, 1);
-       m_close(p_pony);
-       return;
-}
-
-void
-mfa_build_fd_chain(uint64_t id, int fdout)
-{
-       struct mfa_session      *s;
-
-       s = tree_xget(&sessions, id);
-       s->fcurr = TAILQ_LAST(s->filters, mfa_filters);
-       mfa_set_fdout(s, fdout);
-}
-
-static struct mfa_query *
-mfa_query(struct mfa_session *s, int type, int hook)
-{
-       struct mfa_query        *q;
-
-       q = xcalloc(1, sizeof *q, "mfa_query");
-       q->qid = generate_uid();
-       q->session = s;
-       q->type = type;
-       q->hook = hook;
-       tree_init(&q->notify);
-       TAILQ_INSERT_TAIL(&s->queries, q, entry);
-
-       q->state = QUERY_READY;
-       q->current = TAILQ_FIRST(s->filters);
-       q->hasrun = 0;
-
-       log_trace(TRACE_MFA, "filter: new query %s %s", type_to_str(type),
-           hook_to_str(hook));
-
-       return (q);
-}
-
-static void
-mfa_drain_query(struct mfa_query *q)
-{
-       struct mfa_filterproc   *proc;
-       struct mfa_query        *prev;
-
-       log_trace(TRACE_MFA, "filter: draining query %s", mfa_query_to_text(q));
-
-       /*
-        * The query must be passed through all filters that registered
-        * a hook, until one rejects it.  
-        */
-       while (q->state != QUERY_DONE) {
-
-               /* Walk over all filters */
-               while (q->current) {
-
-                       /* Trigger the current filter if not done yet. */
-                       if (!q->hasrun) {
-                               mfa_run_query(q->current, q);
-                               q->hasrun = 1;
-                       }
-                       if (q->state == QUERY_RUNNING) {
-                               log_trace(TRACE_MFA,
-                                   "filter: waiting for running query %s",
-                                   mfa_query_to_text(q));
-                               return;
-                       }
-
-                       /*
-                        * Do not move forward if the query ahead of us is
-                        * waiting on this filter.
-                        */
-                       prev = TAILQ_PREV(q, mfa_queries, entry);
-                       if (prev && prev->current == q->current) {
-                               q->state = QUERY_WAITING;
-                               log_trace(TRACE_MFA,
-                                   "filter: query blocked by previoius query %s",
-                                   mfa_query_to_text(prev));
-                               return;
-                       }
-
-                       q->current = TAILQ_NEXT(q->current, entry);
-                       q->hasrun = 0;
-               }
-               q->state = QUERY_DONE;
-       }
-
-       if (q->type == QT_QUERY) {
-
-               log_trace(TRACE_MFA,
-                   "filter: query %016"PRIx64" done: "
-                   "status=%s code=%d response=\"%s\"",
-                   q->qid,
-                   status_to_str(q->smtp.status),
-                   q->smtp.code,
-                   q->smtp.response);
-
-               /* Done, notify all listeners and return smtp response */
-               while (tree_poproot(&q->notify, NULL, (void**)&proc)) {
-                       m_create(&proc->mproc, IMSG_FILTER_NOTIFY, 0, 0, -1);
-                       m_add_id(&proc->mproc, q->qid);
-                       m_add_int(&proc->mproc, q->smtp.status);
-                       m_close(&proc->mproc);
-               }
-
-               m_create(p_pony, IMSG_MFA_SMTP_RESPONSE, 0, 0, -1);
-               m_add_id(p_pony, q->session->id);
-               m_add_int(p_pony, q->smtp.status);
-               m_add_u32(p_pony, q->smtp.code);
-               if (q->smtp.response)
-                       m_add_string(p_pony, q->smtp.response);
-               m_close(p_pony);
-
-               free(q->smtp.response);
-       }
-
-       TAILQ_REMOVE(&q->session->queries, q, entry);
-       /* If the query was a disconnect event, the session can be freed */
-       if (q->hook == HOOK_DISCONNECT) {
-               /* XXX assert prev == NULL */
-               log_trace(TRACE_MFA, "filter: freeing session %016" PRIx64, q->session->id);
-               free(q->session);
-       }
-
-       log_trace(TRACE_MFA, "filter: freeing query %016" PRIx64, q->qid);
-       free(q);
-}
-
-static void
-mfa_run_query(struct mfa_filter *f, struct mfa_query *q)
-{
-       if ((f->proc->hooks & q->hook) == 0) {
-               log_trace(TRACE_MFA, "filter: skipping filter %s for query %s",
-                   mfa_filter_to_text(f), mfa_query_to_text(q));
-               return;
-       }
-
-       log_trace(TRACE_MFA, "filter: running filter %s for query %s",
-           mfa_filter_to_text(f), mfa_query_to_text(q));
-
-       if (q->type == QT_QUERY) {
-               m_create(&f->proc->mproc, IMSG_FILTER_QUERY, 0, 0, -1);
-               m_add_id(&f->proc->mproc, q->session->id);
-               m_add_id(&f->proc->mproc, q->qid);
-               m_add_int(&f->proc->mproc, q->hook);
-
-               switch (q->hook) {
-               case HOOK_CONNECT:
-                       m_add_sockaddr(&f->proc->mproc,
-                           (struct sockaddr *)&q->u.connect.local);
-                       m_add_sockaddr(&f->proc->mproc,
-                           (struct sockaddr *)&q->u.connect.remote);
-                       m_add_string(&f->proc->mproc, q->u.connect.hostname);
-                       break;
-               case HOOK_HELO:
-                       m_add_string(&f->proc->mproc, q->u.line);
-                       break;
-               case HOOK_MAIL:
-               case HOOK_RCPT:
-                       m_add_mailaddr(&f->proc->mproc, &q->u.maddr);
-                       break;
-               case HOOK_EOM:
-                       m_add_u32(&f->proc->mproc, q->u.datalen);
-                       break;
-               default:
-                       break;
-               }
-               m_close(&f->proc->mproc);
-
-               tree_xset(&queries, q->qid, q);
-               q->state = QUERY_RUNNING;
-       }
-       else {
-               m_create(&f->proc->mproc, IMSG_FILTER_EVENT, 0, 0, -1);
-               m_add_id(&f->proc->mproc, q->session->id);
-               m_add_int(&f->proc->mproc, q->hook);
-               m_close(&f->proc->mproc);
-       }
-}
-
-static void
-mfa_filter_imsg(struct mproc *p, struct imsg *imsg)
-{
-       struct mfa_filterproc   *proc = p->data;
-       struct mfa_session      *s;
-       struct mfa_query        *q, *next;
-       struct msg               m;
-       const char              *line;
-       uint64_t                 qid;
-       uint32_t                 datalen;
-       int                      qhook, status, code, notify;
-
-       if (imsg == NULL) {
-               log_warnx("warn: filter \"%s\" closed unexpectedly", p->name);
-               fatalx("exiting");
-       }
-
-       log_trace(TRACE_MFA, "filter: imsg %s from procfilter %s",
-           filterimsg_to_str(imsg->hdr.type),
-           mfa_filterproc_to_text(proc));
-
-       switch (imsg->hdr.type) {
-
-       case IMSG_FILTER_REGISTER:
-               if (proc->ready) {
-                       log_warnx("warn: filter \"%s\" already registered",
-                           proc->mproc.name);
-                       exit(1);
-               }
-               
-               m_msg(&m, imsg);
-               m_get_int(&m, &proc->hooks);
-               m_get_int(&m, &proc->flags);
-               m_end(&m);
-               proc->ready = 1;
-
-               log_debug("debug: filter \"%s\": hooks 0x%08x flags 0x%04x",
-                   proc->mproc.name, proc->hooks, proc->flags);
-
-               TAILQ_FOREACH(proc, &procs, entry)
-                       if (!proc->ready)
-                               return;
-               mfa_ready();
-               break;
-
-       case IMSG_FILTER_RESPONSE:
-               m_msg(&m, imsg);
-               m_get_id(&m, &qid);
-               m_get_int(&m, &qhook);
-               if (qhook == HOOK_EOM)
-                       m_get_u32(&m, &datalen);
-               m_get_int(&m, &status);
-               m_get_int(&m, &code);
-               m_get_int(&m, &notify);
-               if (m_is_eom(&m))
-                       line = NULL;
-               else
-                       m_get_string(&m, &line);
-               m_end(&m);
-
-               q = tree_xpop(&queries, qid);
-               if (q->hook != qhook) {
-                       log_warnx("warn: mfa: hook mismatch %d != %d", q->hook, qhook);
-                       fatalx("exiting");
-               }
-               q->smtp.status = status;
-               if (code)
-                       q->smtp.code = code;
-               if (line) {
-                       free(q->smtp.response);
-                       q->smtp.response = xstrdup(line, "mfa_filter_imsg");
-               }
-               q->state = (status == FILTER_OK) ? QUERY_READY : QUERY_DONE;
-               if (notify)
-                       tree_xset(&q->notify, (uintptr_t)(proc), proc);
-               if (qhook == HOOK_EOM)
-                       q->u.datalen = datalen;
-
-               next = TAILQ_NEXT(q, entry);
-               mfa_drain_query(q);
-
-               /*
-                * If there is another query after this one which is waiting,
-                * make it move forward.
-                */
-               if (next && next->state == QUERY_WAITING)
-                       mfa_drain_query(next);
-               break;
-
-       case IMSG_FILTER_PIPE_SETUP:
-               m_msg(&m, imsg);
-               m_get_id(&m, &qid);
-               m_end(&m);
-
-               s = tree_xget(&sessions, qid);
-               s->fcurr = TAILQ_PREV(s->fcurr, mfa_filters, entry);
-               mfa_set_fdout(s, imsg->fd);
-               break;
-
-       default:
-               log_warnx("warn: bad imsg from filter %s", p->name);
-               exit(1);
-       }
-}
-
-
-static const char *
-mfa_query_to_text(struct mfa_query *q)
-{
-       static char buf[1024];
-       char tmp[1024];
-       int ret;
-
-       tmp[0] = '\0';
-
-       switch(q->hook) {
-
-       case HOOK_CONNECT:
-               (void)strlcat(tmp, "=", sizeof tmp);
-               (void)strlcat(tmp, ss_to_text(&q->u.connect.local), sizeof tmp);
-               (void)strlcat(tmp, " <-> ", sizeof tmp);
-               (void)strlcat(tmp, ss_to_text(&q->u.connect.remote), sizeof tmp);
-               (void)strlcat(tmp, "(", sizeof tmp);
-               (void)strlcat(tmp, q->u.connect.hostname, sizeof tmp);
-               if (strlcat(tmp, ")", sizeof tmp) >= sizeof tmp)
-                       fatalx("line too large");
-               break;
-
-       case HOOK_MAIL:
-       case HOOK_RCPT:
-               ret = snprintf(tmp, sizeof tmp, "=%s@%s",
-                   q->u.maddr.user, q->u.maddr.domain);
-               if (ret == -1 || ret >= sizeof tmp)
-                       fatalx("line too large");
-               break;
-
-       case HOOK_HELO:
-               ret = snprintf(tmp, sizeof tmp, "=%s", q->u.line);
-               if (ret == -1 || ret >= sizeof tmp)
-                       fatalx("line too large");
-               break;
-
-       default:
-               break;
-       }
-
-       ret = snprintf(buf, sizeof buf, "%016"PRIx64"[%s,%s%s]",
-           q->qid, type_to_str(q->type), hook_to_str(q->hook), tmp);
-       if (ret == -1 || ret >= sizeof buf)
-               fatalx("line too large");
-       return (buf);
-}
-
-static const char *
-mfa_filter_to_text(struct mfa_filter *f)
-{
-       static char buf[1024];
-       int ret;
-
-       ret = snprintf(buf, sizeof buf, "filter:%s", mfa_filterproc_to_text(f->proc));
-       if (ret == -1 || ret >= sizeof buf)
-               fatalx("line too large");
-
-       return (buf);
-}
-
-static const char *
-mfa_filterproc_to_text(struct mfa_filterproc *proc)
-{
-       static char buf[1024];
-       int ret;
-
-       ret = snprintf(buf, sizeof buf, "%s[hooks=0x%08x,flags=0x%04x]",
-           proc->mproc.name, proc->hooks, proc->flags);
-       if (ret == -1 || ret >= sizeof buf)
-               fatalx("line too large");
-
-       return (buf);
-}
-
-#define CASE(x) case x : return #x
-
-static const char *
-filterimsg_to_str(int imsg)
-{
-       switch (imsg) {
-       CASE(IMSG_FILTER_REGISTER);
-       CASE(IMSG_FILTER_EVENT);
-       CASE(IMSG_FILTER_QUERY);
-       CASE(IMSG_FILTER_PIPE_SETUP);
-       CASE(IMSG_FILTER_PIPE_ABORT);
-       CASE(IMSG_FILTER_NOTIFY);
-       CASE(IMSG_FILTER_RESPONSE);
-       default:
-               return "IMSG_FILTER_???";
-       }
-}
-
-static const char *
-hook_to_str(int hook)
-{
-       switch (hook) {
-       CASE(HOOK_CONNECT);
-       CASE(HOOK_HELO);
-       CASE(HOOK_MAIL);
-       CASE(HOOK_RCPT);
-       CASE(HOOK_DATA);
-       CASE(HOOK_EOM);
-       CASE(HOOK_RESET);
-       CASE(HOOK_DISCONNECT);
-       CASE(HOOK_COMMIT);
-       CASE(HOOK_ROLLBACK);
-       CASE(HOOK_DATALINE);
-       default:
-               return "HOOK_???";
-       }
-}
-
-static const char *
-type_to_str(int type)
-{
-       switch (type) {
-       CASE(QT_QUERY);
-       CASE(QT_EVENT);
-       default:
-               return "QT_???";
-       }
-}
-
-static const char *
-status_to_str(int status)
-{
-       switch (status) {
-       CASE(MFA_OK);
-       CASE(MFA_FAIL);
-       CASE(MFA_CLOSE);
-       default:
-               return "MFA_???";
-       }
-}