summaryrefslogtreecommitdiff
path: root/usr.sbin/smtpd/smtpd.h
diff options
context:
space:
mode:
Diffstat (limited to 'usr.sbin/smtpd/smtpd.h')
-rw-r--r--usr.sbin/smtpd/smtpd.h745
1 files changed, 745 insertions, 0 deletions
diff --git a/usr.sbin/smtpd/smtpd.h b/usr.sbin/smtpd/smtpd.h
new file mode 100644
index 00000000000..6fa1af2d741
--- /dev/null
+++ b/usr.sbin/smtpd/smtpd.h
@@ -0,0 +1,745 @@
+/*
+ * Copyright (c) 2008 Gilles Chehade <gilles@openbsd.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.
+ */
+
+#define CONF_FILE "/etc/mail/smtpd.conf"
+#define MAX_LISTEN 16
+#define STRLEN 1024
+#define PROC_COUNT 8
+#define READ_BUF_SIZE 65535
+#define MAX_NAME_SIZE 64
+
+/* sizes include the tailing '\0' */
+#define MAX_LOCALPART_SIZE 65
+#define MAX_DOMAINPART_SIZE MAXHOSTNAMELEN
+#define MAX_PATH_SIZE 256
+
+/*#define SMTPD_CONNECT_TIMEOUT (60)*/
+#define SMTPD_CONNECT_TIMEOUT (10)
+#define SMTPD_QUEUE_INTERVAL (15 * 60)
+#define SMTPD_QUEUE_MAXINTERVAL (4 * 60 * 60)
+#define SMTPD_QUEUE_EXPIRY (4 * 24 * 60 * 60)
+#define SMTPD_USER "_smtpd"
+#define SMTPD_SOCKET "/var/run/smtpd.sock"
+#define SMTPD_BANNER "220 %s OpenSMTPD\r\n"
+#define SMTPD_SESSION_TIMEOUT 300
+
+#define RCPTBUFSZ 256
+
+#define PATH_SPOOL "/var/spool/smtpd"
+
+#define PATH_MESSAGES "/messages"
+#define PATH_LOCAL "/local"
+#define PATH_RELAY "/relay"
+#define PATH_DAEMON "/daemon"
+#define PATH_ENVELOPES "/envelopes"
+
+/* used by newaliases */
+#define PATH_ALIASES "/etc/mail/aliases"
+#define PATH_ALIASESDB "/etc/mail/aliases.db"
+
+/* number of MX records to lookup */
+#define MXARRAYSIZE 5
+
+struct address {
+ char hostname[MAXHOSTNAMELEN];
+ u_int16_t port;
+};
+
+struct netaddr {
+ struct sockaddr_storage ss;
+ int masked;
+};
+
+/* buffer specific headers */
+struct buf {
+ TAILQ_ENTRY(buf) entry;
+ u_char *buf;
+ size_t size;
+ size_t max;
+ size_t wpos;
+ size_t rpos;
+ int fd;
+};
+
+struct msgbuf {
+ TAILQ_HEAD(, buf) bufs;
+ u_int32_t queued;
+ int fd;
+};
+
+struct buf_read {
+ u_char buf[READ_BUF_SIZE];
+ u_char *rptr;
+ size_t wpos;
+};
+
+struct imsg_fd {
+ TAILQ_ENTRY(imsg_fd) entry;
+ int fd;
+ u_int32_t id;
+};
+
+struct imsgbuf {
+ TAILQ_HEAD(, imsg_fd) fds;
+ struct buf_read r;
+ struct msgbuf w;
+ struct event ev;
+ void (*handler)(int, short, void *);
+ int fd;
+ pid_t pid;
+ short events;
+ void *data;
+ u_int32_t id;
+};
+
+struct imsg_hdr {
+ u_int16_t type;
+ u_int16_t len;
+ u_int32_t peerid;
+ pid_t pid;
+};
+
+struct imsg {
+ struct imsg_hdr hdr;
+ u_int32_t id;
+ void *data;
+};
+
+enum imsg_type {
+ IMSG_NONE,
+ IMSG_CTL_OK, /* answer to smtpctl requests */
+ IMSG_CTL_FAIL,
+ IMSG_CTL_SHUTDOWN,
+ IMSG_CONF_START,
+ IMSG_CONF_SSL,
+ IMSG_CONF_SSL_CERT,
+ IMSG_CONF_SSL_KEY,
+ IMSG_CONF_LISTENER,
+ IMSG_CONF_MAP,
+ IMSG_CONF_RULE,
+ IMSG_CONF_CONDITION,
+ IMSG_CONF_OPTION,
+ IMSG_CONF_END,
+ IMSG_CONF_RELOAD,
+ IMSG_LKA_LOOKUP_MAIL,
+ IMSG_LKA_LOOKUP_RCPT,
+ IMSG_LKA_ALIAS_LOOKUP,
+ IMSG_LKA_VUSER_LOOKUP,
+ IMSG_LKA_ALIAS_RESULT,
+ IMSG_LKA_VUSER_RESULT,
+ IMSG_LKA_ALIAS_RESULT_ACK,
+ IMSG_LKA_ALIAS_SCHEDULE,
+ IMSG_LKA_ALIAS_END,
+ IMSG_LKA_NO_ALIAS,
+ IMSG_LKA_MX_LOOKUP,
+ IMSG_LKA_FORWARD_LOOKUP,
+ IMSG_LKA_HOSTNAME_LOOKUP,
+ IMSG_MDA_MAILBOX_FILE,
+ IMSG_MDA_MESSAGE_FILE,
+ IMSG_MDA_MAILBOX_FILE_ERROR,
+ IMSG_MDA_MESSAGE_FILE_ERROR,
+ IMSG_MFA_RPATH_SUBMIT,
+ IMSG_MFA_RCPT_SUBMIT,
+ IMSG_MFA_DATA_SUBMIT,
+ IMSG_MFA_LOOKUP_MAIL,
+ IMSG_MFA_LOOKUP_RCPT,
+ IMSG_QUEUE_REMOVE_SUBMISSION,
+ IMSG_QUEUE_CREATE_MESSAGE_FILE,
+ IMSG_QUEUE_DELETE_MESSAGE_FILE,
+ IMSG_QUEUE_MESSAGE_SUBMIT,
+ IMSG_QUEUE_MESSAGE_UPDATE,
+ IMSG_QUEUE_BATCH_COMPLETE,
+ IMSG_QUEUE_BATCH_CLOSE,
+ IMSG_QUEUE_MESSAGE_FD,
+
+ IMSG_QUEUE_ACCEPTED_CLOSE,
+ IMSG_QUEUE_RETRY_CLOSE,
+ IMSG_QUEUE_REJECTED_CLOSE,
+
+ IMSG_QUEUE_RECIPIENT_ACCEPTED,
+ IMSG_QUEUE_RECIPIENT_UPDATED,
+
+ IMSG_CREATE_BATCH,
+ IMSG_BATCH_APPEND,
+ IMSG_BATCH_CLOSE,
+
+ IMSG_SMTP_MESSAGE_FILE,
+ IMSG_SMTP_SUBMIT_ACK,
+ IMSG_SMTP_HOSTNAME_ANSWER,
+ IMSG_PARENT_MAILBOX_OPEN,
+ IMSG_PARENT_MESSAGE_OPEN,
+ IMSG_PARENT_MAILBOX_RENAME,
+
+ IMSG_PARENT_AUTHENTICATE
+};
+
+#define IMSG_HEADER_SIZE sizeof(struct imsg_hdr)
+#define MAX_IMSGSIZE 16384
+
+enum blockmodes {
+ BM_NORMAL,
+ BM_NONBLOCK
+};
+
+struct ctl_conn {
+ TAILQ_ENTRY(ctl_conn) entry;
+ u_int8_t flags;
+#define CTL_CONN_NOTIFY 0x01
+ struct imsgbuf ibuf;
+};
+TAILQ_HEAD(ctl_connlist, ctl_conn);
+
+typedef u_int32_t objid_t;
+
+struct ctl_id {
+ objid_t id;
+ char name[MAX_NAME_SIZE];
+};
+
+enum smtp_proc_type {
+ PROC_PARENT = 0,
+ PROC_SMTP,
+ PROC_MFA,
+ PROC_LKA,
+ PROC_QUEUE,
+ PROC_MDA,
+ PROC_MTA,
+ PROC_CONTROL,
+} smtpd_process;
+
+struct peer {
+ enum smtp_proc_type id;
+ void (*cb)(int, short, void *);
+};
+
+enum map_type {
+ T_SINGLE,
+ T_LIST,
+ T_HASH
+};
+
+enum map_src {
+ S_NONE,
+ S_DYN,
+ S_DNS,
+ S_FILE,
+ S_DB,
+ S_EXT
+};
+
+enum mapel_type {
+ ME_STRING,
+ ME_NET,
+ ME_NETMASK
+};
+
+struct mapel {
+ TAILQ_ENTRY(mapel) me_entry;
+ union mapel_data {
+ char med_string[STRLEN];
+ struct netaddr med_addr;
+ } me_key;
+ union mapel_data me_val;
+};
+
+struct map {
+ TAILQ_ENTRY(map) m_entry;
+#define F_USED 0x01
+#define F_DYNAMIC 0x02
+ u_int8_t m_flags;
+ char m_name[STRLEN];
+ objid_t m_id;
+ enum map_type m_type;
+ enum mapel_type m_eltype;
+ enum map_src m_src;
+ char m_config[MAXPATHLEN];
+ TAILQ_HEAD(mapel_list, mapel) m_contents;
+};
+
+enum cond_type {
+ C_ALL,
+ C_NET,
+ C_DOM
+};
+
+struct cond {
+ TAILQ_ENTRY(cond) c_entry;
+ objid_t c_map;
+ enum cond_type c_type;
+ struct map *c_match;
+};
+
+enum opt_type {
+ O_RWUSER, /* rewrite user */
+ O_RWDOMAIN, /* rewrite domain */
+};
+
+struct opt {
+ TAILQ_ENTRY(opt) o_entry;
+ enum opt_type o_type;
+};
+
+enum action_type {
+ A_RELAY,
+ A_RELAYVIA,
+ A_MAILDIR,
+ A_MBOX,
+ A_FILENAME,
+ A_EXT
+};
+#define IS_MAILBOX(x) ((x) == A_MAILDIR || (x) == A_MBOX || (x) == A_FILENAME)
+#define IS_RELAY(x) ((x) == A_RELAY || (x) == A_RELAYVIA)
+#define IS_EXT(x) ((x) == A_EXT)
+
+struct rule {
+ TAILQ_ENTRY(rule) r_entry;
+ int r_accept;
+ struct map *r_sources;
+ TAILQ_HEAD(condlist, cond) r_conditions;
+ enum action_type r_action;
+ union {
+ char path[MAXPATHLEN];
+ struct address host;
+#define MAXCOMMANDLEN 256
+ char command[MAXCOMMANDLEN];
+ } r_value;
+ TAILQ_HEAD(optlist, opt) r_options;
+};
+
+enum path_flags {
+ F_ALIAS = 0x1,
+ F_VIRTUAL = 0x2,
+ F_EXPANDED = 0x4,
+ F_NOFORWARD = 0x8,
+ F_FORWARDED = 0x10
+};
+
+struct path {
+ TAILQ_ENTRY(path) entry;
+ struct rule rule;
+ enum path_flags flags;
+ u_int8_t forwardcnt;
+ char user[MAX_LOCALPART_SIZE];
+ char domain[MAX_DOMAINPART_SIZE];
+ char pw_name[MAXLOGNAME];
+ union {
+ char filename[MAXPATHLEN];
+ char filter[MAXPATHLEN];
+ } u;
+};
+
+enum alias_type {
+ ALIAS_USERNAME,
+ ALIAS_FILENAME,
+ ALIAS_FILTER,
+ ALIAS_INCLUDE,
+ ALIAS_ADDRESS
+};
+
+struct alias {
+ TAILQ_ENTRY(alias) entry;
+ enum alias_type type;
+ union {
+ char username[MAXLOGNAME];
+ char filename[MAXPATHLEN];
+ char filter[MAXPATHLEN];
+ struct path path;
+ } u;
+};
+TAILQ_HEAD(aliaseslist, alias);
+
+struct submit_status {
+ u_int64_t id;
+ int code;
+ union {
+ struct path path;
+ char msgid[MAXPATHLEN];
+ char errormsg[STRLEN];
+ } u;
+ struct sockaddr_storage ss;
+};
+
+struct message_recipient {
+ u_int64_t id;
+ struct sockaddr_storage ss;
+ struct path path;
+};
+
+enum message_type {
+ T_MDA_MESSAGE = 0x1,
+ T_MTA_MESSAGE = 0x2,
+ T_DAEMON_MESSAGE = 0x4
+};
+
+enum message_status {
+ S_MESSAGE_PERMFAILURE = 0x1,
+ S_MESSAGE_TEMPFAILURE = 0x2,
+ S_MESSAGE_REJECTED = 0x4,
+ S_MESSAGE_ACCEPTED = 0x8,
+ S_MESSAGE_RETRY = 0x10,
+ S_MESSAGE_EDNS = 0x20,
+ S_MESSAGE_ECONNECT = 0x40
+};
+
+enum message_flags {
+ F_MESSAGE_COMPLETE = 0x1,
+ F_MESSAGE_RESOLVED = 0x2,
+ F_MESSAGE_READY = 0x4,
+ F_MESSAGE_EXPIRED = 0x8,
+ F_MESSAGE_PROCESSING = 0x10
+};
+
+struct message {
+ SPLAY_ENTRY(message) nodes;
+ TAILQ_ENTRY(message) entry;
+
+ enum message_type type;
+
+ u_int64_t id;
+ u_int64_t session_id;
+ u_int64_t batch_id;
+
+ char message_id[MAXPATHLEN];
+ char message_uid[MAXPATHLEN];
+
+ char session_helo[MAXHOSTNAMELEN];
+ char session_hostname[MAXHOSTNAMELEN];
+ char session_errorline[STRLEN];
+ struct sockaddr_storage session_ss;
+
+ struct path sender;
+ struct path recipient;
+ TAILQ_HEAD(pathlist,path) recipients;
+
+ u_int16_t rcptcount;
+
+ time_t creation;
+ time_t lasttry;
+ u_int8_t retry;
+ enum message_flags flags;
+ enum message_status status;
+ FILE *datafp;
+ int mboxfd;
+ int messagefd;
+};
+
+enum batch_status {
+ S_BATCH_PERMFAILURE = 0x1,
+ S_BATCH_TEMPFAILURE = 0x2,
+ S_BATCH_REJECTED = 0x4,
+ S_BATCH_ACCEPTED = 0x8,
+ S_BATCH_RETRY = 0x10,
+ S_BATCH_EDNS = 0x20,
+ S_BATCH_ECONNECT = 0x40
+};
+
+enum batch_type {
+ T_MDA_BATCH = 0x1,
+ T_MTA_BATCH = 0x2,
+ T_DAEMON_BATCH = 0x4
+};
+
+enum batch_flags {
+ F_BATCH_COMPLETE = 0x1,
+ F_BATCH_RESOLVED = 0x2,
+ F_BATCH_SCHEDULED = 0x4,
+ F_BATCH_EXPIRED = 0x8,
+};
+
+struct mdaproc {
+ SPLAY_ENTRY(mdaproc) mdaproc_nodes;
+
+ pid_t pid;
+};
+
+struct batch {
+ SPLAY_ENTRY(batch) b_nodes;
+
+ u_int64_t id;
+ enum batch_type type;
+ enum batch_flags flags;
+
+ struct rule rule;
+
+ struct event ev;
+ struct timeval tv;
+ int peerfd;
+ struct bufferevent *bev;
+ u_int8_t state;
+ struct smtpd *env;
+
+ char message_id[MAXPATHLEN];
+ char hostname[MAXHOSTNAMELEN];
+ char errorline[STRLEN];
+
+ u_int8_t h_errno;
+ struct sockaddr_storage ss[MXARRAYSIZE*2];
+ u_int8_t ss_cnt;
+ u_int8_t ss_off;
+
+ time_t creation;
+ time_t lasttry;
+ u_int8_t retry;
+
+ struct message message;
+ struct message *messagep;
+ FILE *messagefp;
+ TAILQ_HEAD(messagelist, message) messages;
+
+ enum batch_status status;
+};
+
+enum session_state {
+ S_INIT = 0,
+ S_GREETED,
+ S_TLS,
+ S_AUTH,
+ S_HELO,
+ S_MAIL,
+ S_RCPT,
+ S_DATA,
+ S_DATACONTENT,
+ S_DONE,
+ S_QUIT
+};
+
+struct ssl {
+ SPLAY_ENTRY(ssl) ssl_nodes;
+ char ssl_name[PATH_MAX];
+ char *ssl_cert;
+ off_t ssl_cert_len;
+ char *ssl_key;
+ off_t ssl_key_len;
+};
+
+struct listener {
+#define F_STARTTLS 0x01
+#define F_SSMTP 0x02
+#define F_SSL (F_SSMTP|F_STARTTLS)
+ u_int8_t flags;
+ int fd;
+ struct sockaddr_storage ss;
+ in_port_t port;
+ int backlog;
+ struct timeval timeout;
+ struct event ev;
+ struct smtpd *env;
+ char ssl_cert_name[PATH_MAX];
+ struct ssl *ssl;
+ void *ssl_ctx;
+ TAILQ_ENTRY(listener) entry;
+};
+
+struct session_auth_req {
+ u_int64_t session_id;
+ char buffer[STRLEN];
+};
+
+struct session_auth_reply {
+ u_int64_t session_id;
+ u_int8_t value;
+};
+
+enum session_flags {
+ F_QUIT = 0x1,
+ F_IMSG_SENT = 0x2,
+ F_8BITMIME = 0x4,
+ F_SECURE = 0x8,
+ F_AUTHENTICATED = 0x10
+};
+
+struct session {
+ SPLAY_ENTRY(session) s_nodes;
+ u_int64_t s_id;
+
+ enum session_flags s_flags;
+ enum session_state s_state;
+ time_t s_tm;
+ int s_fd;
+ struct sockaddr_storage s_ss;
+ char s_hostname[MAXHOSTNAMELEN];
+ struct event s_ev;
+ struct bufferevent *s_bev;
+ struct listener *s_l;
+ struct smtpd *s_env;
+ void *s_ssl;
+ u_char *s_buf;
+ int s_buflen;
+ struct timeval s_tv;
+ struct message s_msg;
+};
+
+struct smtpd {
+#define SMTPD_OPT_VERBOSE 0x00000001
+#define SMTPD_OPT_NOACTION 0x00000002
+ u_int32_t sc_opts;
+#define SMTPD_CONFIGURING 0x00000001
+#define SMTPD_EXITING 0x00000002
+ u_int32_t sc_flags;
+ struct timeval sc_qintval;
+ struct event sc_ev;
+ int sc_pipes[PROC_COUNT]
+ [PROC_COUNT][2];
+ struct imsgbuf *sc_ibufs[PROC_COUNT];
+ struct passwd *sc_pw;
+ char sc_hostname[MAXHOSTNAMELEN];
+ TAILQ_HEAD(listenerlist, listener) sc_listeners;
+ TAILQ_HEAD(maplist, map) *sc_maps;
+ TAILQ_HEAD(rulelist, rule) *sc_rules;
+ SPLAY_HEAD(sessiontree, session) sc_sessions;
+ SPLAY_HEAD(msgtree, message) sc_messages;
+ SPLAY_HEAD(ssltree, ssl) sc_ssl;
+
+ SPLAY_HEAD(batchtree, batch) batch_queue;
+ SPLAY_HEAD(mdaproctree, mdaproc) mdaproc_queue;
+};
+
+/* aliases.c */
+int is_alias(struct path *);
+
+/* atomic.c */
+ssize_t atomic_read(int, void *, size_t);
+ssize_t atomic_write(int, const void *, size_t);
+ssize_t atomic_printfd(int, const char *, ...);
+
+/* log.c */
+void log_init(int);
+void log_warn(const char *, ...);
+void log_warnx(const char *, ...);
+void log_info(const char *, ...);
+void log_debug(const char *, ...);
+__dead void fatal(const char *);
+__dead void fatalx(const char *);
+
+
+/* buffer.c */
+struct buf *buf_open(size_t);
+struct buf *buf_dynamic(size_t, size_t);
+int buf_add(struct buf *, void *, size_t);
+void *buf_reserve(struct buf *, size_t);
+int buf_close(struct msgbuf *, struct buf *);
+void buf_free(struct buf *);
+void msgbuf_init(struct msgbuf *);
+void msgbuf_clear(struct msgbuf *);
+int msgbuf_write(struct msgbuf *);
+
+/* imsg.c */
+void imsg_init(struct imsgbuf *, int, void (*)(int, short, void *));
+ssize_t imsg_read(struct imsgbuf *);
+ssize_t imsg_get(struct imsgbuf *, struct imsg *);
+int imsg_compose(struct imsgbuf *, enum imsg_type, u_int32_t, pid_t,
+ int, void *, u_int16_t);
+int imsg_composev(struct imsgbuf *, enum imsg_type, u_int32_t,
+ pid_t, int, const struct iovec *, int);
+int imsg_compose_fds(struct imsgbuf *, enum imsg_type, u_int32_t, pid_t,
+ void *, u_int16_t, int, ...);
+struct buf *imsg_create(struct imsgbuf *, enum imsg_type, u_int32_t, pid_t,
+ u_int16_t);
+int imsg_add(struct buf *, void *, u_int16_t);
+int imsg_append(struct imsgbuf *, struct buf *);
+int imsg_close(struct imsgbuf *, struct buf *);
+void imsg_free(struct imsg *);
+void imsg_event_add(struct imsgbuf *); /* needs to be provided externally */
+int imsg_get_fd(struct imsgbuf *, struct imsg *);
+int imsg_flush(struct imsgbuf *);
+void imsg_clear(struct imsgbuf *);
+
+/* lka.c */
+pid_t lka(struct smtpd *);
+
+/* mfa.c */
+pid_t mfa(struct smtpd *);
+int msg_cmp(struct message *, struct message *);
+SPLAY_PROTOTYPE(msgtree, message, nodes, msg_cmp);
+
+/* queue.c */
+pid_t queue(struct smtpd *);
+u_int64_t queue_generate_id(void);
+int batch_cmp(struct batch *, struct batch *);
+struct batch *batch_by_id(struct smtpd *, u_int64_t);
+struct message *message_by_id(struct smtpd *, struct batch *, u_int64_t);
+int queue_remove_batch_message(struct smtpd *, struct batch *, struct message *);
+SPLAY_PROTOTYPE(batchtree, batch, b_nodes, batch_cmp);
+
+/* mda.c */
+pid_t mda(struct smtpd *);
+int mdaproc_cmp(struct mdaproc *, struct mdaproc *);
+SPLAY_PROTOTYPE(mdaproctree, mdaproc, mdaproc_nodes, mdaproc_cmp);
+
+/* mta.c */
+pid_t mta(struct smtpd *);
+
+/* control.c */
+pid_t control(struct smtpd *);
+void session_socket_blockmode(int, enum blockmodes);
+
+/* smtp.c */
+pid_t smtp(struct smtpd *);
+void smtp_listener_setup(struct smtpd *, struct listener *);
+
+/* smtp_session.c */
+void session_init(struct listener *, struct session *);
+void session_read(struct bufferevent *, void *);
+void session_write(struct bufferevent *, void *);
+void session_error(struct bufferevent *, short, void *);
+int session_cmp(struct session *, struct session *);
+void session_msg_submit(struct session *);
+void session_pickup(struct session *, struct submit_status *);
+void session_destroy(struct session *);
+SPLAY_PROTOTYPE(sessiontree, session, s_nodes, session_cmp);
+
+/* store.c */
+int store_write_header(struct batch *, struct message *);
+int store_write_message(struct batch *, struct message *);
+int store_write_daemon(struct batch *, struct message *);
+int store_message(struct batch *, struct message *,
+ int (*)(struct batch *, struct message *));
+
+/* config.c */
+#define PURGE_LISTENERS 0x01
+#define PURGE_MAPS 0x02
+#define PURGE_RULES 0x04
+#define PURGE_SSL 0x08
+#define PURGE_EVERYTHING 0xff
+void purge_config(struct smtpd *, u_int8_t);
+void unconfigure(struct smtpd *);
+void configure(struct smtpd *);
+void init_peers(struct smtpd *);
+void config_peers(struct smtpd *, struct peer *, u_int);
+
+/* parse.y */
+int parse_config(struct smtpd *, const char *, int);
+int cmdline_symset(char *);
+
+/* ssl.c */
+void ssl_init(void);
+void ssl_transaction(struct session *);
+
+void ssl_session_init(struct session *);
+void ssl_session_destroy(struct session *);
+int ssl_load_certfile(struct smtpd *, const char *);
+void ssl_setup(struct smtpd *, struct listener *);
+int ssl_cmp(struct ssl *, struct ssl *);
+SPLAY_PROTOTYPE(ssltree, ssl, ssl_nodes, ssl_cmp);
+
+/* ssl_privsep.c */
+int ssl_ctx_use_private_key(void *, char *, off_t);
+int ssl_ctx_use_certificate_chain(void *, char *, off_t);
+
+/* smtpd.c */
+struct map *map_find(struct smtpd *, objid_t);
+struct map *map_findbyname(struct smtpd *, const char *);