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