164562Sgshapiro/*
2261194Sgshapiro * Copyright (c) 1999-2003, 2006 Proofpoint, Inc. and its suppliers.
364562Sgshapiro *	All rights reserved.
464562Sgshapiro *
564562Sgshapiro * By using this file, you agree to the terms and conditions set
664562Sgshapiro * forth in the LICENSE file which can be found at the top level of
764562Sgshapiro * the sendmail distribution.
864562Sgshapiro */
964562Sgshapiro
1064562Sgshapiro/*
1164562Sgshapiro**  LIBMILTER.H -- include file for mail filter library functions
1264562Sgshapiro*/
1364562Sgshapiro
1464562Sgshapiro#ifndef _LIBMILTER_H
1564562Sgshapiro# define _LIBMILTER_H	1
1690792Sgshapiro
1790792Sgshapiro#include <sm/gen.h>
1890792Sgshapiro
1964562Sgshapiro#ifdef _DEFINE
2064562Sgshapiro# define EXTERN
2164562Sgshapiro# define INIT(x)	= x
22266527SgshapiroSM_IDSTR(MilterlId, "@(#)$Id: libmilter.h,v 8.78 2013-11-22 20:51:36 ca Exp $")
23363466Sgshapiro#else
2464562Sgshapiro# define EXTERN extern
2564562Sgshapiro# define INIT(x)
26363466Sgshapiro#endif
2764562Sgshapiro
2864562Sgshapiro
29168515Sgshapiro#include "sm/tailq.h"
30168515Sgshapiro
3164562Sgshapiro#define NOT_SENDMAIL	1
3264562Sgshapiro#define _SOCK_ADDR	union bigsockaddr
3364562Sgshapiro#include "sendmail.h"
3464562Sgshapiro
35168515Sgshapiro#ifdef SM_ASSERT
36168515Sgshapiro#undef SM_ASSERT
37168515Sgshapiro#endif
38168515Sgshapiro#ifndef SM_ASSERT
39168515Sgshapiro#include <assert.h>
40168515Sgshapiro#define SM_ASSERT(x) assert(x)
41168515Sgshapiro#endif
42168515Sgshapiro
4364562Sgshapiro#include "libmilter/milter.h"
4464562Sgshapiro
45168515Sgshapiro#define MAX_MACROS_ENTRIES	7	/* max size of macro pointer array */
46168515Sgshapiro
47168515Sgshapirotypedef SM_TAILQ_HEAD(, smfi_str)	smfi_hd_T;
48168515Sgshapirotypedef struct smfi_str smfi_str_S;
49168515Sgshapiro
50168515Sgshapiro/*
51168515Sgshapiro**  Context for one milter session.
52168515Sgshapiro**
53168515Sgshapiro**  Notes:
54168515Sgshapiro**	There is a 1-1 correlation between a sendmail SMTP server process,
55168515Sgshapiro**	an SMTP session, and an milter context. Due to the nature of SMTP
56168515Sgshapiro**	session handling in sendmail 8, this libmilter implementation deals
57168515Sgshapiro**	only with a single SMTP session per MTA - libmilter connection.
58168515Sgshapiro**
59168515Sgshapiro**	There is no "global" context for libmilter, global variables are
60168515Sgshapiro**	just that (they are not "collected" in a context).
61168515Sgshapiro**
62168515Sgshapiro**  Implementation hint:
63168515Sgshapiro**  macros are stored in mac_buf[] as sequence of:
64168515Sgshapiro**  macro_name \0 macro_value
65168515Sgshapiro**  (just as read from the MTA)
66168515Sgshapiro**  mac_ptr is a list of pointers into mac_buf to the beginning of each
67168515Sgshapiro**  entry, i.e., macro_name, macro_value, ...
68168515Sgshapiro*/
69168515Sgshapiro
70168515Sgshapirostruct smfi_str
71168515Sgshapiro{
72168515Sgshapiro	sthread_t	ctx_id;		/* thread id */
73168515Sgshapiro	socket_t	ctx_sd;		/* socket descriptor */
74168515Sgshapiro	int		ctx_dbg;	/* debug level */
75168515Sgshapiro	time_t		ctx_timeout;	/* timeout */
76168515Sgshapiro	int		ctx_state;	/* state */
77168515Sgshapiro	smfiDesc_ptr	ctx_smfi;	/* filter description */
78168515Sgshapiro
79168515Sgshapiro	int		ctx_prot_vers;	/* libmilter protocol version */
80168515Sgshapiro	unsigned long	ctx_aflags;	/* milter action flags */
81168515Sgshapiro
82168515Sgshapiro	unsigned long	ctx_pflags;	/* milter protocol flags */
83168515Sgshapiro
84168515Sgshapiro	/*
85168515Sgshapiro	**  milter protocol flags that are sent to the MTA;
86168515Sgshapiro	**  this is the same as ctx_pflags except for those flags that
87168515Sgshapiro	**  are not offered by the MTA but emulated in libmilter.
88168515Sgshapiro	*/
89168515Sgshapiro
90168515Sgshapiro	unsigned long	ctx_pflags2mta;
91168515Sgshapiro
92168515Sgshapiro	/*
93168515Sgshapiro	**  milter protocol version that is sent to the MTA;
94168515Sgshapiro	**  this is the same as ctx_prot_vers unless the
95168515Sgshapiro	**  MTA protocol version (ctx_mta_prot_vers) is smaller
96168515Sgshapiro	**  but still "acceptable".
97168515Sgshapiro	*/
98168515Sgshapiro
99168515Sgshapiro	int		ctx_prot_vers2mta;
100168515Sgshapiro
101168515Sgshapiro	char		**ctx_mac_ptr[MAX_MACROS_ENTRIES];
102168515Sgshapiro	char		*ctx_mac_buf[MAX_MACROS_ENTRIES];
103168515Sgshapiro	char		*ctx_mac_list[MAX_MACROS_ENTRIES];
104168515Sgshapiro	char		*ctx_reply;	/* reply code */
105168515Sgshapiro	void		*ctx_privdata;	/* private data */
106168515Sgshapiro
107168515Sgshapiro	int		ctx_mta_prot_vers;	/* MTA protocol version */
108168515Sgshapiro	unsigned long	ctx_mta_pflags;	/* MTA protocol flags */
109168515Sgshapiro	unsigned long	ctx_mta_aflags;	/* MTA action flags */
110168515Sgshapiro
111168515Sgshapiro#if _FFR_THREAD_MONITOR
112168515Sgshapiro	time_t		ctx_start;	/* start time of thread */
113168515Sgshapiro	SM_TAILQ_ENTRY(smfi_str)	ctx_mon_link;
114363466Sgshapiro#endif
115168515Sgshapiro
116168515Sgshapiro#if _FFR_WORKERS_POOL
117168515Sgshapiro	long		ctx_sid;	/* session identifier */
118168515Sgshapiro	int		ctx_wstate;	/* state of the session (worker pool) */
119168515Sgshapiro	int		ctx_wait;	/* elapsed time waiting for sm cmd */
120168515Sgshapiro	SM_TAILQ_ENTRY(smfi_str)	ctx_link;
121168515Sgshapiro#endif /* _FFR_WORKERS_POOL */
122168515Sgshapiro};
123168515Sgshapiro
12464562Sgshapiro# define ValidSocket(sd)	((sd) >= 0)
12590792Sgshapiro# define INVALID_SOCKET		(-1)
12690792Sgshapiro# define closesocket		close
12790792Sgshapiro# define MI_SOCK_READ(s, b, l)	read(s, b, l)
12890792Sgshapiro# define MI_SOCK_READ_FAIL(x)	((x) < 0)
12990792Sgshapiro# define MI_SOCK_WRITE(s, b, l)	write(s, b, l)
13064562Sgshapiro
13164562Sgshapiro# define thread_create(ptid,wr,arg) pthread_create(ptid, NULL, wr, arg)
13264562Sgshapiro# define sthread_get_id()	pthread_self()
13364562Sgshapiro
13471345Sgshapirotypedef pthread_mutex_t smutex_t;
13571345Sgshapiro# define smutex_init(mp)	(pthread_mutex_init(mp, NULL) == 0)
13671345Sgshapiro# define smutex_destroy(mp)	(pthread_mutex_destroy(mp) == 0)
13771345Sgshapiro# define smutex_lock(mp)	(pthread_mutex_lock(mp) == 0)
13871345Sgshapiro# define smutex_unlock(mp)	(pthread_mutex_unlock(mp) == 0)
13971345Sgshapiro# define smutex_trylock(mp)	(pthread_mutex_trylock(mp) == 0)
14071345Sgshapiro
141168515Sgshapiro#if _FFR_WORKERS_POOL
142168515Sgshapiro/* SM_CONF_POLL shall be defined with _FFR_WORKERS_POOL */
143168515Sgshapiro# if !SM_CONF_POLL
144168515Sgshapiro#  define SM_CONF_POLL 1
145363466Sgshapiro# endif
146168515Sgshapiro#endif /* _FFR_WORKERS_POOL */
147168515Sgshapiro
148168515Sgshapirotypedef pthread_cond_t scond_t;
149168515Sgshapiro#define scond_init(cp)			pthread_cond_init(cp, NULL)
150168515Sgshapiro#define scond_destroy(cp)		pthread_cond_destroy(cp)
151168515Sgshapiro#define scond_wait(cp, mp)		pthread_cond_wait(cp, mp)
152168515Sgshapiro#define scond_signal(cp)		pthread_cond_signal(cp)
153168515Sgshapiro#define scond_broadcast(cp)		pthread_cond_broadcast(cp)
154168515Sgshapiro#define scond_timedwait(cp, mp, to)					\
155168515Sgshapiro	do								\
156168515Sgshapiro	{								\
157168515Sgshapiro		struct timespec timeout;				\
158168515Sgshapiro		struct timeval now;					\
159168515Sgshapiro		gettimeofday(&now, NULL);				\
160168515Sgshapiro		timeout.tv_sec = now.tv_sec + to;			\
161168515Sgshapiro		timeout.tv_nsec = now.tv_usec / 1000;			\
162168515Sgshapiro		r = pthread_cond_timedwait(cp,mp,&timeout);		\
163168515Sgshapiro		if (r != 0 && r != ETIMEDOUT)				\
164168515Sgshapiro			smi_log(SMI_LOG_ERR,				\
165168515Sgshapiro				"pthread_cond_timedwait error %d", r);	\
166168515Sgshapiro	} while (0)
167168515Sgshapiro
168168515Sgshapiro
169132943Sgshapiro#if SM_CONF_POLL
170111823Sgshapiro
171111823Sgshapiro# include <poll.h>
172111823Sgshapiro# define MI_POLLSELECT  "poll"
173111823Sgshapiro
174111823Sgshapiro# define MI_POLL_RD_FLAGS (POLLIN | POLLPRI)
175111823Sgshapiro# define MI_POLL_WR_FLAGS (POLLOUT)
176363466Sgshapiro# define MI_MS(timeout) (((timeout)->tv_sec * 1000) + (((timeout)->tv_usec) / 1000))
177111823Sgshapiro
178111823Sgshapiro# define FD_RD_VAR(rds, excs) struct pollfd rds
179111823Sgshapiro# define FD_WR_VAR(wrs) struct pollfd wrs
180111823Sgshapiro
181111823Sgshapiro# define FD_RD_INIT(sd, rds, excs)			\
182111823Sgshapiro		(rds).fd = (sd);			\
183111823Sgshapiro		(rds).events = MI_POLL_RD_FLAGS;	\
184111823Sgshapiro		(rds).revents = 0
185111823Sgshapiro
186111823Sgshapiro# define FD_WR_INIT(sd, wrs)				\
187111823Sgshapiro		(wrs).fd = (sd);			\
188111823Sgshapiro		(wrs).events = MI_POLL_WR_FLAGS;	\
189111823Sgshapiro		(wrs).revents = 0
190111823Sgshapiro
191111823Sgshapiro# define FD_IS_RD_EXC(sd, rds, excs)	\
192111823Sgshapiro		(((rds).revents & (POLLERR | POLLHUP | POLLNVAL)) != 0)
193111823Sgshapiro
194111823Sgshapiro# define FD_IS_WR_RDY(sd, wrs)		\
195111823Sgshapiro		(((wrs).revents & MI_POLL_WR_FLAGS) != 0)
196111823Sgshapiro
197111823Sgshapiro# define FD_IS_RD_RDY(sd, rds, excs)			\
198111823Sgshapiro		(((rds).revents & MI_POLL_RD_FLAGS) != 0)
199111823Sgshapiro
200363466Sgshapiro# define FD_WR_READY(sd, wrs, timeout)	\
201111823Sgshapiro		poll(&(wrs), 1, MI_MS(timeout))
202111823Sgshapiro
203111823Sgshapiro# define FD_RD_READY(sd, rds, excs, timeout)	\
204111823Sgshapiro		poll(&(rds), 1, MI_MS(timeout))
205111823Sgshapiro
206132943Sgshapiro#else /* SM_CONF_POLL */
207111823Sgshapiro
208111823Sgshapiro# include <sm/fdset.h>
209111823Sgshapiro# define MI_POLLSELECT  "select"
210111823Sgshapiro
211111823Sgshapiro# define FD_RD_VAR(rds, excs) fd_set rds, excs
212111823Sgshapiro# define FD_WR_VAR(wrs) fd_set wrs
213111823Sgshapiro
214111823Sgshapiro# define FD_RD_INIT(sd, rds, excs)			\
215111823Sgshapiro		FD_ZERO(&(rds));			\
216111823Sgshapiro		FD_SET((unsigned int) (sd), &(rds));	\
217111823Sgshapiro		FD_ZERO(&(excs));			\
218111823Sgshapiro		FD_SET((unsigned int) (sd), &(excs))
219111823Sgshapiro
220111823Sgshapiro# define FD_WR_INIT(sd, wrs)			\
221111823Sgshapiro		FD_ZERO(&(wrs));			\
222157001Sgshapiro		FD_SET((unsigned int) (sd), &(wrs))
223111823Sgshapiro
224111823Sgshapiro# define FD_IS_RD_EXC(sd, rds, excs) FD_ISSET(sd, &(excs))
225111823Sgshapiro# define FD_IS_WR_RDY(sd, wrs) FD_ISSET((sd), &(wrs))
226111823Sgshapiro# define FD_IS_RD_RDY(sd, rds, excs) FD_ISSET((sd), &(rds))
227111823Sgshapiro
228111823Sgshapiro# define FD_WR_READY(sd, wrs, timeout)	\
229111823Sgshapiro		select((sd) + 1, NULL, &(wrs), NULL, (timeout))
230111823Sgshapiro# define FD_RD_READY(sd, rds, excs, timeout)	\
231111823Sgshapiro		select((sd) + 1, &(rds), NULL, &(excs), (timeout))
232111823Sgshapiro
233132943Sgshapiro#endif /* SM_CONF_POLL */
234111823Sgshapiro
23564562Sgshapiro#include <sys/time.h>
23664562Sgshapiro
23764562Sgshapiro/* some defaults */
23877349Sgshapiro#define MI_TIMEOUT	7210		/* default timeout for read/write */
23964562Sgshapiro#define MI_CHK_TIME	5		/* checking whether to terminate */
24064562Sgshapiro
24190792Sgshapiro#ifndef MI_SOMAXCONN
24290792Sgshapiro# if SOMAXCONN > 20
24390792Sgshapiro#  define MI_SOMAXCONN	SOMAXCONN
244363466Sgshapiro# else
24590792Sgshapiro#  define MI_SOMAXCONN	20
246363466Sgshapiro# endif
24790792Sgshapiro#endif /* ! MI_SOMAXCONN */
24866494Sgshapiro
24964562Sgshapiro/* maximum number of repeated failures in mi_listener() */
25064562Sgshapiro#define MAX_FAILS_M	16	/* malloc() */
25164562Sgshapiro#define MAX_FAILS_T	16	/* thread creation */
25277349Sgshapiro#define MAX_FAILS_A	16	/* accept() */
25390792Sgshapiro#define MAX_FAILS_S	16	/* select() */
25464562Sgshapiro
25564562Sgshapiro/* internal "commands", i.e., error codes */
25664562Sgshapiro#define SMFIC_TIMEOUT	((char) 1)	/* timeout */
25764562Sgshapiro#define SMFIC_SELECT	((char) 2)	/* select error */
25864562Sgshapiro#define SMFIC_MALLOC	((char) 3)	/* malloc error */
25964562Sgshapiro#define SMFIC_RECVERR	((char) 4)	/* recv() error */
26064562Sgshapiro#define SMFIC_EOF	((char) 5)	/* eof */
26164562Sgshapiro#define SMFIC_UNKNERR	((char) 6)	/* unknown error */
26264562Sgshapiro#define SMFIC_TOOBIG	((char) 7)	/* body chunk too big */
26364562Sgshapiro#define SMFIC_VALIDCMD	' '		/* first valid command */
26464562Sgshapiro
26564562Sgshapiro/* hack */
26664562Sgshapiro#define smi_log		syslog
267120256Sgshapiro#define sm_dprintf	(void) printf
26864562Sgshapiro#define milter_ret	int
26964562Sgshapiro#define SMI_LOG_ERR	LOG_ERR
27064562Sgshapiro#define SMI_LOG_FATAL	LOG_ERR
27164562Sgshapiro#define SMI_LOG_WARN	LOG_WARNING
27264562Sgshapiro#define SMI_LOG_INFO	LOG_INFO
27364562Sgshapiro#define SMI_LOG_DEBUG	LOG_DEBUG
27464562Sgshapiro
27564562Sgshapiro/* stop? */
27664562Sgshapiro#define MILTER_CONT	0
27764562Sgshapiro#define MILTER_STOP	1
27864562Sgshapiro#define MILTER_ABRT	2
27964562Sgshapiro
28064562Sgshapiro/* functions */
28164562Sgshapiroextern int	mi_handle_session __P((SMFICTX_PTR));
28264562Sgshapiroextern int	mi_engine __P((SMFICTX_PTR));
28366494Sgshapiroextern int	mi_listener __P((char *, int, smfiDesc_ptr, time_t, int));
28464562Sgshapiroextern void	mi_clr_macros __P((SMFICTX_PTR, int));
285203004Sgshapiroextern void	mi_clr_ctx __P((SMFICTX_PTR));
28664562Sgshapiroextern int	mi_stop __P((void));
28764562Sgshapiroextern int	mi_control_startup __P((char *));
28864562Sgshapiroextern void	mi_stop_milters __P((int));
28964562Sgshapiroextern void	mi_clean_signals __P((void));
29064562Sgshapiroextern struct hostent *mi_gethostbyname __P((char *, int));
29190792Sgshapiroextern int	mi_inet_pton __P((int, const char *, void *));
29266494Sgshapiroextern void	mi_closener __P((void));
293125820Sgshapiroextern int	mi_opensocket __P((char *, int, int, bool, smfiDesc_ptr));
29464562Sgshapiro
29564562Sgshapiro/* communication functions */
29664562Sgshapiroextern char	*mi_rd_cmd __P((socket_t, struct timeval *, char *, size_t *, char *));
29764562Sgshapiroextern int	mi_wr_cmd __P((socket_t, struct timeval *, int, char *, size_t));
29864562Sgshapiroextern bool	mi_sendok __P((SMFICTX_PTR, int));
29964562Sgshapiro
30090792Sgshapiro
301168515Sgshapiro#if _FFR_THREAD_MONITOR
302168515Sgshapiroextern bool Monitor;
303168515Sgshapiro
304168515Sgshapiro#define MI_MONITOR_INIT()	mi_monitor_init()
305168515Sgshapiro#define MI_MONITOR_BEGIN(ctx, cmd)			\
306168515Sgshapiro	do						\
307168515Sgshapiro	{						\
308168515Sgshapiro		if (Monitor)				\
309168515Sgshapiro			mi_monitor_work_begin(ctx, cmd);\
310168515Sgshapiro	} while (0)
311168515Sgshapiro
312168515Sgshapiro#define MI_MONITOR_END(ctx, cmd)			\
313168515Sgshapiro	do						\
314168515Sgshapiro	{						\
315168515Sgshapiro		if (Monitor)				\
316168515Sgshapiro			mi_monitor_work_end(ctx, cmd);	\
317168515Sgshapiro	} while (0)
318168515Sgshapiro
319168515Sgshapiroint mi_monitor_init __P((void));
320168515Sgshapiroint mi_monitor_work_begin __P((SMFICTX_PTR, int));
321168515Sgshapiroint mi_monitor_work_end __P((SMFICTX_PTR, int));
322168515Sgshapiro
323168515Sgshapiro#else /* _FFR_THREAD_MONITOR */
324168515Sgshapiro#define MI_MONITOR_INIT()	MI_SUCCESS
325168515Sgshapiro#define MI_MONITOR_BEGIN(ctx, cmd)
326168515Sgshapiro#define MI_MONITOR_END(ctx, cmd)
327168515Sgshapiro#endif /* _FFR_THREAD_MONITOR */
328168515Sgshapiro
329168515Sgshapiro#if _FFR_WORKERS_POOL
330168515Sgshapiroextern int mi_pool_manager_init __P((void));
331168515Sgshapiroextern int mi_pool_controller_init __P((void));
332168515Sgshapiroextern int mi_start_session __P((SMFICTX_PTR));
333168515Sgshapiro#endif /* _FFR_WORKERS_POOL */
334168515Sgshapiro
335110560Sgshapiro#endif /* ! _LIBMILTER_H */
336