smtpd.h revision 1.34
1/*	$OpenBSD: smtpd.h,v 1.34 2008/12/21 02:18:46 gilles Exp $	*/
2
3/*
4 * Copyright (c) 2008 Gilles Chehade <gilles@openbsd.org>
5 * Copyright (c) 2008 Pierre-Yves Ritschard <pyr@openbsd.org>
6 *
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 */
19
20#define CONF_FILE		 "/etc/mail/smtpd.conf"
21#define MAX_LISTEN		 16
22#define PROC_COUNT		 9
23#define READ_BUF_SIZE		 32768
24#define MAX_NAME_SIZE		 64
25
26/* sizes include the tailing '\0' */
27#define MAX_LINE_SIZE		 1024
28#define MAX_LOCALPART_SIZE	 65
29#define MAX_DOMAINPART_SIZE	 MAXHOSTNAMELEN
30
31/* return and forward path size */
32#define MAX_PATH_SIZE		 256
33
34/*#define SMTPD_CONNECT_TIMEOUT	 (60)*/
35#define SMTPD_CONNECT_TIMEOUT	 (10)
36#define SMTPD_QUEUE_INTERVAL	 (15 * 60)
37#define SMTPD_QUEUE_MAXINTERVAL	 (4 * 60 * 60)
38#define SMTPD_QUEUE_EXPIRY	 (4 * 24 * 60 * 60)
39#define SMTPD_USER		 "_smtpd"
40#define SMTPD_SOCKET		 "/var/run/smtpd.sock"
41#define SMTPD_BANNER		 "220 %s OpenSMTPD"
42#define SMTPD_SESSION_TIMEOUT	 300
43
44#define RCPTBUFSZ		 256
45
46#define	DIRHASH_BUCKETS		 4096
47
48#define PATH_SPOOL		"/var/spool/smtpd"
49
50#define PATH_INCOMING		"/incoming"
51#define PATH_QUEUE		"/queue"
52#define PATH_PURGE		"/purge"
53
54#define PATH_MESSAGE		"/message"
55#define PATH_ENVELOPES		"/envelopes"
56
57#define PATH_RUNQUEUE		"/runqueue"
58#define PATH_RUNQUEUEHIGH	"/runqueue-high"
59#define PATH_RUNQUEUELOW	"/runqueue-low"
60
61/* used by newaliases */
62#define	PATH_ALIASES		"/etc/mail/aliases"
63#define	PATH_ALIASESDB		"/etc/mail/aliases.db"
64
65/* number of MX records to lookup */
66#define MXARRAYSIZE	5
67
68/* rfc5321 limits */
69#define	SMTP_TEXTLINE_MAX	1000
70#define	SMTP_CMDLINE_MAX	512
71
72#define F_STARTTLS		 0x01
73#define F_SSMTP			 0x02
74#define F_AUTH			 0x04
75#define F_SSL			(F_SSMTP|F_STARTTLS)
76
77
78struct netaddr {
79	struct sockaddr_storage ss;
80	int masked;
81};
82
83struct relayhost {
84	u_int8_t flags;
85	char hostname[MAXHOSTNAMELEN];
86	u_int16_t port;
87};
88
89struct mxhost {
90	u_int8_t flags;
91	struct sockaddr_storage ss;
92};
93
94/* buffer specific headers */
95struct buf {
96	TAILQ_ENTRY(buf)	 entry;
97	u_char			*buf;
98	size_t			 size;
99	size_t			 max;
100	size_t			 wpos;
101	size_t			 rpos;
102	int			 fd;
103};
104
105struct msgbuf {
106	TAILQ_HEAD(, buf)	 bufs;
107	u_int32_t		 queued;
108	int			 fd;
109};
110
111struct buf_read {
112	u_char			 buf[READ_BUF_SIZE];
113	u_char			*rptr;
114	size_t			 wpos;
115};
116
117struct imsg_fd  {
118	TAILQ_ENTRY(imsg_fd)	 entry;
119	int			 fd;
120	u_int32_t		 id;
121};
122
123struct imsgbuf {
124	TAILQ_HEAD(, imsg_fd)	 fds;
125	struct buf_read		 r;
126	struct msgbuf		 w;
127	struct event		 ev;
128	void			(*handler)(int, short, void *);
129	int			 fd;
130	pid_t			 pid;
131	short			 events;
132	void			*data;
133	u_int32_t		 id;
134};
135
136struct imsg_hdr {
137	u_int16_t		 type;
138	u_int16_t		 len;
139	u_int32_t		 peerid;
140	pid_t			 pid;
141};
142
143struct imsg {
144	struct imsg_hdr		 hdr;
145	u_int32_t		 id;
146	void			*data;
147};
148
149enum imsg_type {
150	IMSG_NONE,
151	IMSG_CTL_OK,		/* answer to smtpctl requests */
152	IMSG_CTL_FAIL,
153	IMSG_CTL_SHUTDOWN,
154	IMSG_CONF_START,
155	IMSG_CONF_SSL,
156	IMSG_CONF_SSL_CERT,
157	IMSG_CONF_SSL_KEY,
158	IMSG_CONF_LISTENER,
159	IMSG_CONF_MAP,
160	IMSG_CONF_RULE,
161	IMSG_CONF_CONDITION,
162	IMSG_CONF_OPTION,
163	IMSG_CONF_END,
164	IMSG_CONF_RELOAD,
165	IMSG_LKA_MAIL,
166	IMSG_LKA_RCPT,
167	IMSG_LKA_ALIAS,
168	IMSG_LKA_MX,
169	IMSG_LKA_FORWARD,
170	IMSG_LKA_HOST,
171	IMSG_MDA_MAILBOX_FILE,
172	IMSG_MDA_MESSAGE_FILE,
173	IMSG_MFA_RCPT,
174	IMSG_MFA_MAIL,
175
176	IMSG_QUEUE_CREATE_MESSAGE,
177	IMSG_QUEUE_SUBMIT_ENVELOPE,
178	IMSG_QUEUE_REMOVE_MESSAGE,
179	IMSG_QUEUE_COMMIT_MESSAGE,
180
181	IMSG_QUEUE_REMOVE_SUBMISSION,
182	IMSG_QUEUE_MESSAGE_UPDATE,
183	IMSG_QUEUE_MESSAGE_FD,
184	IMSG_QUEUE_MESSAGE_FILE,
185
186	IMSG_BATCH_CREATE,
187	IMSG_BATCH_APPEND,
188	IMSG_BATCH_CLOSE,
189
190	IMSG_PARENT_MAILBOX_OPEN,
191	IMSG_PARENT_MESSAGE_OPEN,
192	IMSG_PARENT_MAILBOX_RENAME,
193
194	IMSG_PARENT_AUTHENTICATE
195};
196
197#define IMSG_HEADER_SIZE	 sizeof(struct imsg_hdr)
198#define	MAX_IMSGSIZE		 16384
199
200enum blockmodes {
201	BM_NORMAL,
202	BM_NONBLOCK
203};
204
205struct ctl_conn {
206	TAILQ_ENTRY(ctl_conn)	 entry;
207	u_int8_t		 flags;
208#define CTL_CONN_NOTIFY		 0x01
209	struct imsgbuf		 ibuf;
210};
211TAILQ_HEAD(ctl_connlist, ctl_conn);
212
213typedef u_int32_t		 objid_t;
214
215struct ctl_id {
216	objid_t		 id;
217	char		 name[MAX_NAME_SIZE];
218};
219
220enum smtp_proc_type {
221	PROC_PARENT = 0,
222	PROC_SMTP,
223	PROC_MFA,
224	PROC_LKA,
225	PROC_QUEUE,
226	PROC_MDA,
227	PROC_MTA,
228	PROC_CONTROL,
229	PROC_RUNNER,
230} smtpd_process;
231
232struct peer {
233	enum smtp_proc_type	 id;
234	void			(*cb)(int, short, void *);
235};
236
237enum map_type {
238	T_SINGLE,
239	T_LIST,
240	T_HASH
241};
242
243enum map_src {
244	S_NONE,
245	S_DYN,
246	S_DNS,
247	S_FILE,
248	S_DB,
249	S_EXT
250};
251
252enum mapel_type {
253	ME_STRING,
254	ME_NET,
255	ME_NETMASK
256};
257
258struct mapel {
259	TAILQ_ENTRY(mapel)		 me_entry;
260	union mapel_data {
261		char			 med_string[MAX_LINE_SIZE];
262		struct netaddr		 med_addr;
263	}				 me_key;
264	union mapel_data		 me_val;
265};
266
267struct map {
268	TAILQ_ENTRY(map)		 m_entry;
269#define F_USED				 0x01
270#define F_DYNAMIC			 0x02
271	u_int8_t			 m_flags;
272	char				 m_name[MAX_LINE_SIZE];
273	objid_t				 m_id;
274	enum map_type			 m_type;
275	enum mapel_type			 m_eltype;
276	enum map_src			 m_src;
277	char				 m_config[MAXPATHLEN];
278	TAILQ_HEAD(mapel_list, mapel)	 m_contents;
279};
280
281enum cond_type {
282	C_ALL,
283	C_NET,
284	C_DOM
285};
286
287struct cond {
288	TAILQ_ENTRY(cond)		 c_entry;
289	objid_t				 c_map;
290	enum cond_type			 c_type;
291	struct map			*c_match;
292};
293
294enum opt_type {
295	O_RWUSER,			/* rewrite user */
296	O_RWDOMAIN,			/* rewrite domain */
297};
298
299struct opt {
300	TAILQ_ENTRY(opt)		 o_entry;
301	enum opt_type			 o_type;
302};
303
304enum action_type {
305	A_RELAY,
306	A_RELAYVIA,
307	A_MAILDIR,
308	A_MBOX,
309	A_FILENAME,
310	A_EXT
311};
312#define IS_MAILBOX(x)	((x) == A_MAILDIR || (x) == A_MBOX || (x) == A_FILENAME)
313#define IS_RELAY(x)	((x) == A_RELAY || (x) == A_RELAYVIA)
314#define IS_EXT(x)	((x) == A_EXT)
315
316struct rule {
317	TAILQ_ENTRY(rule)		 r_entry;
318	int				 r_accept;
319	struct map			*r_sources;
320	TAILQ_HEAD(condlist, cond)	 r_conditions;
321	enum action_type		 r_action;
322	union rule_dest {
323		char			 path[MAXPATHLEN];
324		struct relayhost       	 relayhost;
325#define	MAXCOMMANDLEN	256
326		char			 command[MAXCOMMANDLEN];
327	}				 r_value;
328	TAILQ_HEAD(optlist, opt)	 r_options;
329};
330
331enum path_flags {
332	F_ALIAS = 0x1,
333	F_VIRTUAL = 0x2,
334	F_EXPANDED = 0x4,
335	F_NOFORWARD = 0x8,
336	F_FORWARDED = 0x10
337};
338
339struct path {
340	TAILQ_ENTRY(path)		 entry;
341	struct rule			 rule;
342	enum path_flags			 flags;
343	u_int8_t			 forwardcnt;
344	char				 user[MAX_LOCALPART_SIZE];
345	char				 domain[MAX_DOMAINPART_SIZE];
346	char				 pw_name[MAXLOGNAME];
347	union path_data {
348		char filename[MAXPATHLEN];
349		char filter[MAXPATHLEN];
350	}				 u;
351};
352
353enum alias_type {
354	ALIAS_USERNAME,
355	ALIAS_FILENAME,
356	ALIAS_FILTER,
357	ALIAS_INCLUDE,
358	ALIAS_ADDRESS
359};
360
361struct alias {
362	TAILQ_ENTRY(alias)		entry;
363	enum alias_type			 type;
364	union alias_data {
365		char username[MAXLOGNAME];
366		char filename[MAXPATHLEN];
367		char filter[MAXPATHLEN];
368		struct path path;
369	}                                   u;
370};
371TAILQ_HEAD(aliaseslist, alias);
372
373enum message_type {
374	T_MDA_MESSAGE		= 0x1,
375	T_MTA_MESSAGE		= 0x2,
376	T_DAEMON_MESSAGE	= 0x4
377};
378
379enum message_status {
380	S_MESSAGE_LOCKFAILURE	= 0x1,
381	S_MESSAGE_PERMFAILURE	= 0x2,
382	S_MESSAGE_TEMPFAILURE	= 0x4,
383	S_MESSAGE_REJECTED	= 0x8,
384	S_MESSAGE_ACCEPTED	= 0x10,
385	S_MESSAGE_RETRY		= 0x20,
386	S_MESSAGE_EDNS		= 0x40,
387	S_MESSAGE_ECONNECT	= 0x80
388};
389
390enum message_flags {
391	F_MESSAGE_RESOLVED	= 0x1,
392	F_MESSAGE_EXPIRED	= 0x2,
393	F_MESSAGE_SCHEDULED	= 0x4,
394	F_MESSAGE_PROCESSING	= 0x8,
395	F_MESSAGE_AUTHENTICATED	= 0x10
396};
397
398struct message {
399	SPLAY_ENTRY(message)		 nodes;
400	TAILQ_ENTRY(message)		 entry;
401
402	enum message_type		 type;
403
404	u_int64_t			 id;
405	u_int64_t			 session_id;
406	u_int64_t			 batch_id;
407
408	char				 message_id[MAXPATHLEN];
409	char				 message_uid[MAXPATHLEN];
410
411	char				 session_helo[MAXHOSTNAMELEN];
412	char				 session_hostname[MAXHOSTNAMELEN];
413	char				 session_errorline[MAX_LINE_SIZE];
414	struct sockaddr_storage		 session_ss;
415
416	struct path			 sender;
417	struct path			 recipient;
418	TAILQ_HEAD(pathlist,path)	 recipients;
419
420	u_int16_t			 rcptcount;
421
422	time_t				 creation;
423	time_t				 lasttry;
424	u_int8_t			 retry;
425	enum message_flags		 flags;
426	enum message_status		 status;
427	FILE				*datafp;
428	int				 mboxfd;
429	int				 messagefd;
430};
431
432enum batch_status {
433	S_BATCH_PERMFAILURE	= 0x1,
434	S_BATCH_TEMPFAILURE	= 0x2,
435	S_BATCH_REJECTED	= 0x4,
436	S_BATCH_ACCEPTED	= 0x8,
437	S_BATCH_RETRY		= 0x10,
438	S_BATCH_EDNS		= 0x20,
439	S_BATCH_ECONNECT	= 0x40
440};
441
442enum batch_type {
443	T_MDA_BATCH		= 0x1,
444	T_MTA_BATCH		= 0x2,
445	T_DAEMON_BATCH		= 0x4
446};
447
448enum batch_flags {
449	F_BATCH_COMPLETE	= 0x1,
450	F_BATCH_RESOLVED	= 0x2,
451	F_BATCH_SCHEDULED	= 0x4,
452	F_BATCH_EXPIRED		= 0x8,
453};
454
455struct mdaproc {
456	SPLAY_ENTRY(mdaproc)	mdaproc_nodes;
457
458	pid_t			pid;
459};
460
461struct batch {
462	SPLAY_ENTRY(batch)	 b_nodes;
463
464	u_int64_t		 id;
465	enum batch_type		 type;
466	enum batch_flags	 flags;
467
468	struct rule			 rule;
469
470	struct event			 ev;
471	struct timeval			 tv;
472	int				 peerfd;
473	struct bufferevent		*bev;
474	u_int8_t			 state;
475	struct smtpd			*env;
476
477	char				 message_id[MAXPATHLEN];
478	char				 hostname[MAXHOSTNAMELEN];
479	char				 errorline[MAX_LINE_SIZE];
480
481	int8_t				 getaddrinfo_error;
482	struct mxhost			 mxarray[MXARRAYSIZE*2];
483	u_int8_t			 mx_cnt;
484	u_int8_t			 mx_off;
485
486	time_t				 creation;
487	time_t				 lasttry;
488	u_int8_t			 retry;
489
490	struct message			message;
491	struct message			*messagep;
492	FILE				*messagefp;
493	TAILQ_HEAD(messagelist, message) messages;
494
495	enum batch_status		status;
496};
497
498enum session_state {
499	S_INIT = 0,
500	S_GREETED,
501	S_TLS,
502	S_AUTH_INIT,
503	S_AUTH_USERNAME,
504	S_AUTH_PASSWORD,
505	S_AUTH_FINALIZE,
506	S_HELO,
507	S_MAILREQUEST,
508	S_MAIL,
509	S_RCPTREQUEST,
510	S_RCPT,
511	S_DATAREQUEST,
512	S_DATA,
513	S_DATACONTENT,
514	S_DONE,
515	S_QUIT
516};
517#define	IS_AUTH(x)	((x) == S_AUTH_INIT || (x) == S_AUTH_USERNAME || (x) == S_AUTH_PASSWORD || (x) == S_AUTH_FINALIZE)
518
519struct ssl {
520	SPLAY_ENTRY(ssl)	 ssl_nodes;
521	char			 ssl_name[PATH_MAX];
522	char			*ssl_cert;
523	off_t			 ssl_cert_len;
524	char			*ssl_key;
525	off_t			 ssl_key_len;
526};
527
528struct listener {
529	u_int8_t		 flags;
530	int			 fd;
531	struct sockaddr_storage	 ss;
532	in_port_t		 port;
533	int			 backlog;
534	struct timeval		 timeout;
535	struct event		 ev;
536	struct smtpd		*env;
537	char			 ssl_cert_name[PATH_MAX];
538	struct ssl		*ssl;
539	void			*ssl_ctx;
540	TAILQ_ENTRY(listener)	 entry;
541};
542
543struct session_auth_req {
544	u_int64_t	session_id;
545	char		buffer[MAX_LINE_SIZE];
546};
547
548struct session_auth_reply {
549	u_int64_t	session_id;
550	u_int8_t	value;
551};
552
553enum session_flags {
554	F_EHLO		= 0x1,
555	F_QUIT		= 0x2,
556	F_8BITMIME	= 0x4,
557	F_SECURE	= 0x8,
558	F_AUTHENTICATED	= 0x10
559};
560
561struct session {
562	SPLAY_ENTRY(session)		 s_nodes;
563	u_int64_t			 s_id;
564
565	enum session_flags		 s_flags;
566	enum session_state		 s_state;
567	time_t				 s_tm;
568	int				 s_fd;
569	struct sockaddr_storage		 s_ss;
570	char				 s_hostname[MAXHOSTNAMELEN];
571	struct event			 s_ev;
572	struct bufferevent		*s_bev;
573	struct listener			*s_l;
574	struct smtpd			*s_env;
575	void				*s_ssl;
576	u_char				*s_buf;
577	int				 s_buflen;
578	struct timeval			 s_tv;
579	struct message			 s_msg;
580
581	struct session_auth_req		 s_auth;
582};
583
584struct smtpd {
585#define SMTPD_OPT_VERBOSE			 0x00000001
586#define SMTPD_OPT_NOACTION			 0x00000002
587	u_int32_t				 sc_opts;
588#define SMTPD_CONFIGURING			 0x00000001
589#define SMTPD_EXITING				 0x00000002
590	u_int32_t				 sc_flags;
591	struct timeval				 sc_qintval;
592	struct event				 sc_ev;
593	int					 sc_pipes[PROC_COUNT]
594						    [PROC_COUNT][2];
595	struct imsgbuf				*sc_ibufs[PROC_COUNT];
596	struct passwd				*sc_pw;
597	char					 sc_hostname[MAXHOSTNAMELEN];
598	TAILQ_HEAD(listenerlist, listener)	 sc_listeners;
599	TAILQ_HEAD(maplist, map)		*sc_maps;
600	TAILQ_HEAD(rulelist, rule)		*sc_rules;
601	SPLAY_HEAD(sessiontree, session)	 sc_sessions;
602	SPLAY_HEAD(msgtree, message)		 sc_messages;
603	SPLAY_HEAD(ssltree, ssl)		 sc_ssl;
604
605	SPLAY_HEAD(batchtree, batch)		batch_queue;
606	SPLAY_HEAD(mdaproctree, mdaproc)	mdaproc_queue;
607};
608
609struct submit_status {
610	u_int64_t			 id;
611	int				 code;
612	union submit_path {
613		struct path		 path;
614		char			 msgid[MAXPATHLEN];
615		char			 errormsg[MAX_LINE_SIZE];
616	}				 u;
617	enum message_flags		 flags;
618	struct sockaddr_storage		 ss;
619};
620
621struct message_recipient {
622	u_int64_t			 id;
623	struct sockaddr_storage		 ss;
624	enum message_flags		 flags;
625	struct path			 path;
626};
627
628
629/* aliases.c */
630int aliases_exist(struct smtpd *, char *);
631int aliases_get(struct smtpd *, struct aliaseslist *, char *);
632int aliases_virtual_exist(struct smtpd *, struct path *);
633int aliases_virtual_get(struct smtpd *, struct aliaseslist *, struct path *);
634int alias_parse(struct alias *, char *);
635
636
637/* log.c */
638void		log_init(int);
639void		log_warn(const char *, ...)
640    __attribute__ ((format (printf, 1, 2)));
641void		log_warnx(const char *, ...)
642    __attribute__ ((format (printf, 1, 2)));
643void		log_info(const char *, ...)
644    __attribute__ ((format (printf, 1, 2)));
645void		log_debug(const char *, ...)
646    __attribute__ ((format (printf, 1, 2)));
647__dead void	fatal(const char *);
648__dead void	fatalx(const char *);
649
650
651/* buffer.c */
652struct buf	*buf_open(size_t);
653struct buf	*buf_dynamic(size_t, size_t);
654int		 buf_add(struct buf *, void *, size_t);
655void		*buf_reserve(struct buf *, size_t);
656int		 buf_close(struct msgbuf *, struct buf *);
657void		 buf_free(struct buf *);
658void		 msgbuf_init(struct msgbuf *);
659void		 msgbuf_clear(struct msgbuf *);
660int		 msgbuf_write(struct msgbuf *);
661
662
663/* dns.c */
664size_t getmxbyname(char *, char ***);
665
666
667/* forward.c */
668int forwards_get(struct aliaseslist *, char *);
669
670
671/* imsg.c */
672void	 imsg_init(struct imsgbuf *, int, void (*)(int, short, void *));
673ssize_t	 imsg_read(struct imsgbuf *);
674ssize_t	 imsg_get(struct imsgbuf *, struct imsg *);
675int	 imsg_compose(struct imsgbuf *, enum imsg_type, u_int32_t, pid_t,
676	    int, void *, u_int16_t);
677int	 imsg_composev(struct imsgbuf *, enum imsg_type, u_int32_t,
678	    pid_t, int, const struct iovec *, int);
679int	 imsg_compose_fds(struct imsgbuf *, enum imsg_type, u_int32_t, pid_t,
680	    void *, u_int16_t, int, ...);
681struct buf *imsg_create(struct imsgbuf *, enum imsg_type, u_int32_t, pid_t,
682	    u_int16_t);
683int	 imsg_add(struct buf *, void *, u_int16_t);
684int	 imsg_append(struct imsgbuf *, struct buf *);
685int	 imsg_close(struct imsgbuf *, struct buf *);
686void	 imsg_free(struct imsg *);
687void	 imsg_event_add(struct imsgbuf *); /* needs to be provided externally */
688int	 imsg_get_fd(struct imsgbuf *, struct imsg *);
689int	 imsg_flush(struct imsgbuf *);
690void	 imsg_clear(struct imsgbuf *);
691
692/* lka.c */
693pid_t		 lka(struct smtpd *);
694
695/* mfa.c */
696pid_t		 mfa(struct smtpd *);
697int		 msg_cmp(struct message *, struct message *);
698SPLAY_PROTOTYPE(msgtree, message, nodes, msg_cmp);
699
700/* queue.c */
701pid_t		 queue(struct smtpd *);
702u_int64_t	 queue_generate_id(void);
703int		 batch_cmp(struct batch *, struct batch *);
704struct batch    *batch_by_id(struct smtpd *, u_int64_t);
705struct message	*message_by_id(struct smtpd *, struct batch *, u_int64_t);
706int		 queue_remove_batch_message(struct smtpd *, struct batch *, struct message *);
707
708/* mda.c */
709pid_t		 mda(struct smtpd *);
710int		 mdaproc_cmp(struct mdaproc *, struct mdaproc *);
711SPLAY_PROTOTYPE(mdaproctree, mdaproc, mdaproc_nodes, mdaproc_cmp);
712
713/* mta.c */
714pid_t		 mta(struct smtpd *);
715
716/* control.c */
717pid_t		 control(struct smtpd *);
718void		 session_socket_blockmode(int, enum blockmodes);
719
720/* runner.c */
721pid_t		 runner(struct smtpd *);
722SPLAY_PROTOTYPE(batchtree, batch, b_nodes, batch_cmp);
723
724
725/* smtp.c */
726pid_t		 smtp(struct smtpd *);
727void		 smtp_listener_setup(struct smtpd *, struct listener *);
728
729/* smtp_session.c */
730void		 session_init(struct listener *, struct session *);
731int		 session_cmp(struct session *, struct session *);
732void		 session_pickup(struct session *, struct submit_status *);
733void		 session_destroy(struct session *);
734SPLAY_PROTOTYPE(sessiontree, session, s_nodes, session_cmp);
735
736/* store.c */
737int store_write_header(struct batch *, struct message *, FILE *);
738int store_write_message(struct batch *, struct message *);
739int store_write_daemon(struct batch *, struct message *);
740int store_message(struct batch *, struct message *,
741    int (*)(struct batch *, struct message *));
742
743/* config.c */
744#define		 PURGE_LISTENERS	0x01
745#define		 PURGE_MAPS		0x02
746#define		 PURGE_RULES		0x04
747#define		 PURGE_SSL		0x08
748#define		 PURGE_EVERYTHING	0xff
749void		 purge_config(struct smtpd *, u_int8_t);
750void		 unconfigure(struct smtpd *);
751void		 configure(struct smtpd *);
752void		 init_peers(struct smtpd *);
753void		 config_peers(struct smtpd *, struct peer *, u_int);
754
755/* parse.y */
756int		 parse_config(struct smtpd *, const char *, int);
757int		 cmdline_symset(char *);
758
759/* ssl.c */
760void	 ssl_init(void);
761void	 ssl_transaction(struct session *);
762
763void	 ssl_session_init(struct session *);
764void	 ssl_session_destroy(struct session *);
765int	 ssl_load_certfile(struct smtpd *, const char *);
766void	 ssl_setup(struct smtpd *, struct listener *);
767int	 ssl_cmp(struct ssl *, struct ssl *);
768SPLAY_PROTOTYPE(ssltree, ssl, ssl_nodes, ssl_cmp);
769
770/* ssl_privsep.c */
771int	 ssl_ctx_use_private_key(void *, char *, off_t);
772int	 ssl_ctx_use_certificate_chain(void *, char *, off_t);
773
774/* smtpd.c */
775struct map	*map_find(struct smtpd *, objid_t);
776struct map	*map_findbyname(struct smtpd *, const char *);
777
778/* util.c */
779int		bsnprintf(char *, size_t, const char *, ...)
780    __attribute__ ((format (printf, 3, 4)));
781int		safe_fclose(FILE *);
782