smtpd.h revision 1.33
1/*	$OpenBSD: smtpd.h,v 1.33 2008/12/20 00:18:03 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,
503	S_HELO,
504	S_MAILREQUEST,
505	S_MAIL,
506	S_RCPTREQUEST,
507	S_RCPT,
508	S_DATAREQUEST,
509	S_DATA,
510	S_DATACONTENT,
511	S_DONE,
512	S_QUIT
513};
514
515struct ssl {
516	SPLAY_ENTRY(ssl)	 ssl_nodes;
517	char			 ssl_name[PATH_MAX];
518	char			*ssl_cert;
519	off_t			 ssl_cert_len;
520	char			*ssl_key;
521	off_t			 ssl_key_len;
522};
523
524struct listener {
525	u_int8_t		 flags;
526	int			 fd;
527	struct sockaddr_storage	 ss;
528	in_port_t		 port;
529	int			 backlog;
530	struct timeval		 timeout;
531	struct event		 ev;
532	struct smtpd		*env;
533	char			 ssl_cert_name[PATH_MAX];
534	struct ssl		*ssl;
535	void			*ssl_ctx;
536	TAILQ_ENTRY(listener)	 entry;
537};
538
539struct session_auth_req {
540	u_int64_t	session_id;
541	char		buffer[MAX_LINE_SIZE];
542};
543
544struct session_auth_reply {
545	u_int64_t	session_id;
546	u_int8_t	value;
547};
548
549enum session_flags {
550	F_EHLO		= 0x1,
551	F_QUIT		= 0x2,
552	F_8BITMIME	= 0x4,
553	F_SECURE	= 0x8,
554	F_AUTHENTICATED	= 0x10
555};
556
557struct session {
558	SPLAY_ENTRY(session)		 s_nodes;
559	u_int64_t			 s_id;
560
561	enum session_flags		 s_flags;
562	enum session_state		 s_state;
563	time_t				 s_tm;
564	int				 s_fd;
565	struct sockaddr_storage		 s_ss;
566	char				 s_hostname[MAXHOSTNAMELEN];
567	struct event			 s_ev;
568	struct bufferevent		*s_bev;
569	struct listener			*s_l;
570	struct smtpd			*s_env;
571	void				*s_ssl;
572	u_char				*s_buf;
573	int				 s_buflen;
574	struct timeval			 s_tv;
575	struct message			 s_msg;
576};
577
578struct smtpd {
579#define SMTPD_OPT_VERBOSE			 0x00000001
580#define SMTPD_OPT_NOACTION			 0x00000002
581	u_int32_t				 sc_opts;
582#define SMTPD_CONFIGURING			 0x00000001
583#define SMTPD_EXITING				 0x00000002
584	u_int32_t				 sc_flags;
585	struct timeval				 sc_qintval;
586	struct event				 sc_ev;
587	int					 sc_pipes[PROC_COUNT]
588						    [PROC_COUNT][2];
589	struct imsgbuf				*sc_ibufs[PROC_COUNT];
590	struct passwd				*sc_pw;
591	char					 sc_hostname[MAXHOSTNAMELEN];
592	TAILQ_HEAD(listenerlist, listener)	 sc_listeners;
593	TAILQ_HEAD(maplist, map)		*sc_maps;
594	TAILQ_HEAD(rulelist, rule)		*sc_rules;
595	SPLAY_HEAD(sessiontree, session)	 sc_sessions;
596	SPLAY_HEAD(msgtree, message)		 sc_messages;
597	SPLAY_HEAD(ssltree, ssl)		 sc_ssl;
598
599	SPLAY_HEAD(batchtree, batch)		batch_queue;
600	SPLAY_HEAD(mdaproctree, mdaproc)	mdaproc_queue;
601};
602
603struct submit_status {
604	u_int64_t			 id;
605	int				 code;
606	union submit_path {
607		struct path		 path;
608		char			 msgid[MAXPATHLEN];
609		char			 errormsg[MAX_LINE_SIZE];
610	}				 u;
611	enum message_flags		 flags;
612	struct sockaddr_storage		 ss;
613};
614
615struct message_recipient {
616	u_int64_t			 id;
617	struct sockaddr_storage		 ss;
618	enum message_flags		 flags;
619	struct path			 path;
620};
621
622
623/* aliases.c */
624int aliases_exist(struct smtpd *, char *);
625int aliases_get(struct smtpd *, struct aliaseslist *, char *);
626int aliases_virtual_exist(struct smtpd *, struct path *);
627int aliases_virtual_get(struct smtpd *, struct aliaseslist *, struct path *);
628int alias_parse(struct alias *, char *);
629
630
631/* log.c */
632void		log_init(int);
633void		log_warn(const char *, ...)
634    __attribute__ ((format (printf, 1, 2)));
635void		log_warnx(const char *, ...)
636    __attribute__ ((format (printf, 1, 2)));
637void		log_info(const char *, ...)
638    __attribute__ ((format (printf, 1, 2)));
639void		log_debug(const char *, ...)
640    __attribute__ ((format (printf, 1, 2)));
641__dead void	fatal(const char *);
642__dead void	fatalx(const char *);
643
644
645/* buffer.c */
646struct buf	*buf_open(size_t);
647struct buf	*buf_dynamic(size_t, size_t);
648int		 buf_add(struct buf *, void *, size_t);
649void		*buf_reserve(struct buf *, size_t);
650int		 buf_close(struct msgbuf *, struct buf *);
651void		 buf_free(struct buf *);
652void		 msgbuf_init(struct msgbuf *);
653void		 msgbuf_clear(struct msgbuf *);
654int		 msgbuf_write(struct msgbuf *);
655
656
657/* dns.c */
658size_t getmxbyname(char *, char ***);
659
660
661/* forward.c */
662int forwards_get(struct aliaseslist *, char *);
663
664
665/* imsg.c */
666void	 imsg_init(struct imsgbuf *, int, void (*)(int, short, void *));
667ssize_t	 imsg_read(struct imsgbuf *);
668ssize_t	 imsg_get(struct imsgbuf *, struct imsg *);
669int	 imsg_compose(struct imsgbuf *, enum imsg_type, u_int32_t, pid_t,
670	    int, void *, u_int16_t);
671int	 imsg_composev(struct imsgbuf *, enum imsg_type, u_int32_t,
672	    pid_t, int, const struct iovec *, int);
673int	 imsg_compose_fds(struct imsgbuf *, enum imsg_type, u_int32_t, pid_t,
674	    void *, u_int16_t, int, ...);
675struct buf *imsg_create(struct imsgbuf *, enum imsg_type, u_int32_t, pid_t,
676	    u_int16_t);
677int	 imsg_add(struct buf *, void *, u_int16_t);
678int	 imsg_append(struct imsgbuf *, struct buf *);
679int	 imsg_close(struct imsgbuf *, struct buf *);
680void	 imsg_free(struct imsg *);
681void	 imsg_event_add(struct imsgbuf *); /* needs to be provided externally */
682int	 imsg_get_fd(struct imsgbuf *, struct imsg *);
683int	 imsg_flush(struct imsgbuf *);
684void	 imsg_clear(struct imsgbuf *);
685
686/* lka.c */
687pid_t		 lka(struct smtpd *);
688
689/* mfa.c */
690pid_t		 mfa(struct smtpd *);
691int		 msg_cmp(struct message *, struct message *);
692SPLAY_PROTOTYPE(msgtree, message, nodes, msg_cmp);
693
694/* queue.c */
695pid_t		 queue(struct smtpd *);
696u_int64_t	 queue_generate_id(void);
697int		 batch_cmp(struct batch *, struct batch *);
698struct batch    *batch_by_id(struct smtpd *, u_int64_t);
699struct message	*message_by_id(struct smtpd *, struct batch *, u_int64_t);
700int		 queue_remove_batch_message(struct smtpd *, struct batch *, struct message *);
701
702/* mda.c */
703pid_t		 mda(struct smtpd *);
704int		 mdaproc_cmp(struct mdaproc *, struct mdaproc *);
705SPLAY_PROTOTYPE(mdaproctree, mdaproc, mdaproc_nodes, mdaproc_cmp);
706
707/* mta.c */
708pid_t		 mta(struct smtpd *);
709
710/* control.c */
711pid_t		 control(struct smtpd *);
712void		 session_socket_blockmode(int, enum blockmodes);
713
714/* runner.c */
715pid_t		 runner(struct smtpd *);
716SPLAY_PROTOTYPE(batchtree, batch, b_nodes, batch_cmp);
717
718
719/* smtp.c */
720pid_t		 smtp(struct smtpd *);
721void		 smtp_listener_setup(struct smtpd *, struct listener *);
722
723/* smtp_session.c */
724void		 session_init(struct listener *, struct session *);
725int		 session_cmp(struct session *, struct session *);
726void		 session_pickup(struct session *, struct submit_status *);
727void		 session_destroy(struct session *);
728SPLAY_PROTOTYPE(sessiontree, session, s_nodes, session_cmp);
729
730/* store.c */
731int store_write_header(struct batch *, struct message *, FILE *);
732int store_write_message(struct batch *, struct message *);
733int store_write_daemon(struct batch *, struct message *);
734int store_message(struct batch *, struct message *,
735    int (*)(struct batch *, struct message *));
736
737/* config.c */
738#define		 PURGE_LISTENERS	0x01
739#define		 PURGE_MAPS		0x02
740#define		 PURGE_RULES		0x04
741#define		 PURGE_SSL		0x08
742#define		 PURGE_EVERYTHING	0xff
743void		 purge_config(struct smtpd *, u_int8_t);
744void		 unconfigure(struct smtpd *);
745void		 configure(struct smtpd *);
746void		 init_peers(struct smtpd *);
747void		 config_peers(struct smtpd *, struct peer *, u_int);
748
749/* parse.y */
750int		 parse_config(struct smtpd *, const char *, int);
751int		 cmdline_symset(char *);
752
753/* ssl.c */
754void	 ssl_init(void);
755void	 ssl_transaction(struct session *);
756
757void	 ssl_session_init(struct session *);
758void	 ssl_session_destroy(struct session *);
759int	 ssl_load_certfile(struct smtpd *, const char *);
760void	 ssl_setup(struct smtpd *, struct listener *);
761int	 ssl_cmp(struct ssl *, struct ssl *);
762SPLAY_PROTOTYPE(ssltree, ssl, ssl_nodes, ssl_cmp);
763
764/* ssl_privsep.c */
765int	 ssl_ctx_use_private_key(void *, char *, off_t);
766int	 ssl_ctx_use_certificate_chain(void *, char *, off_t);
767
768/* smtpd.c */
769struct map	*map_find(struct smtpd *, objid_t);
770struct map	*map_findbyname(struct smtpd *, const char *);
771
772/* util.c */
773int		bsnprintf(char *, size_t, const char *, ...)
774    __attribute__ ((format (printf, 3, 4)));
775int		safe_fclose(FILE *);
776