1/*
2 *  Copyright (c) 1999-2003, 2006, 2007 Sendmail, Inc. and its suppliers.
3 *	All rights reserved.
4 *
5 * By using this file, you agree to the terms and conditions set
6 * forth in the LICENSE file which can be found at the top level of
7 * the sendmail distribution.
8 *
9 */
10
11#include <sm/gen.h>
12SM_RCSID("@(#)$Id: main.c,v 8.84 2008/09/02 05:37:06 ca Exp $")
13
14#define _DEFINE	1
15#include "libmilter.h"
16#include <fcntl.h>
17#include <sys/stat.h>
18
19
20static smfiDesc_ptr smfi = NULL;
21
22/*
23**  SMFI_REGISTER -- register a filter description
24**
25**	Parameters:
26**		smfilter -- description of filter to register
27**
28**	Returns:
29**		MI_SUCCESS/MI_FAILURE
30*/
31
32int
33smfi_register(smfilter)
34	smfiDesc_str smfilter;
35{
36	size_t len;
37
38	if (smfi == NULL)
39	{
40		smfi = (smfiDesc_ptr) malloc(sizeof *smfi);
41		if (smfi == NULL)
42			return MI_FAILURE;
43	}
44	(void) memcpy(smfi, &smfilter, sizeof *smfi);
45	if (smfilter.xxfi_name == NULL)
46		smfilter.xxfi_name = "Unknown";
47
48	len = strlen(smfilter.xxfi_name) + 1;
49	smfi->xxfi_name = (char *) malloc(len);
50	if (smfi->xxfi_name == NULL)
51		return MI_FAILURE;
52	(void) sm_strlcpy(smfi->xxfi_name, smfilter.xxfi_name, len);
53
54	/* compare milter version with hard coded version */
55	if ((SM_LM_VRS_MAJOR(smfi->xxfi_version) != SM_LM_VRS_MAJOR(SMFI_VERSION) ||
56	     SM_LM_VRS_MINOR(smfi->xxfi_version) != SM_LM_VRS_MINOR(SMFI_VERSION)) &&
57	    smfi->xxfi_version != 2 &&
58	    smfi->xxfi_version != 3 &&
59	    smfi->xxfi_version != 4)
60	{
61		/* hard failure for now! */
62		smi_log(SMI_LOG_ERR,
63			"%s: smfi_register: version mismatch application: %d != milter: %d",
64			smfi->xxfi_name, smfi->xxfi_version,
65			(int) SMFI_VERSION);
66
67		/* XXX how about smfi? */
68		free(smfi->xxfi_name);
69		return MI_FAILURE;
70	}
71
72	return MI_SUCCESS;
73}
74
75/*
76**  SMFI_STOP -- stop milter
77**
78**	Parameters:
79**		none.
80**
81**	Returns:
82**		success.
83*/
84
85int
86smfi_stop()
87{
88	mi_stop_milters(MILTER_STOP);
89	return MI_SUCCESS;
90}
91
92/*
93**  Default values for some variables.
94**	Most of these can be changed with the functions below.
95*/
96
97static int dbg = 0;
98static char *conn = NULL;
99static int timeout = MI_TIMEOUT;
100static int backlog = MI_SOMAXCONN;
101
102/*
103**  SMFI_OPENSOCKET -- try the socket setup to make sure we'll be
104**		       able to start up
105**
106**	Parameters:
107**		rmsocket -- if true, instructs libmilter to attempt
108**			to remove the socket before creating it;
109**			only applies for "local:" or "unix:" sockets
110**
111**	Return:
112**		MI_SUCCESS/MI_FAILURE
113*/
114
115int
116smfi_opensocket(rmsocket)
117	bool rmsocket;
118{
119	if (smfi == NULL || conn == NULL)
120		return MI_FAILURE;
121
122	return mi_opensocket(conn, backlog, dbg, rmsocket, smfi);
123}
124
125/*
126**  SMFI_SETDBG -- set debug level.
127**
128**	Parameters:
129**		odbg -- new debug level.
130**
131**	Returns:
132**		MI_SUCCESS
133*/
134
135int
136smfi_setdbg(odbg)
137	int odbg;
138{
139	dbg = odbg;
140	return MI_SUCCESS;
141}
142
143/*
144**  SMFI_SETTIMEOUT -- set timeout (for read/write).
145**
146**	Parameters:
147**		otimeout -- new timeout.
148**
149**	Returns:
150**		MI_SUCCESS
151*/
152
153int
154smfi_settimeout(otimeout)
155	int otimeout;
156{
157	timeout = otimeout;
158	return MI_SUCCESS;
159}
160
161/*
162**  SMFI_SETCONN -- set connection information (socket description)
163**
164**	Parameters:
165**		oconn -- new connection information.
166**
167**	Returns:
168**		MI_SUCCESS/MI_FAILURE
169*/
170
171int
172smfi_setconn(oconn)
173	char *oconn;
174{
175	size_t l;
176
177	if (oconn == NULL || *oconn == '\0')
178		return MI_FAILURE;
179	l = strlen(oconn) + 1;
180	if ((conn = (char *) malloc(l)) == NULL)
181		return MI_FAILURE;
182	if (sm_strlcpy(conn, oconn, l) >= l)
183		return MI_FAILURE;
184	return MI_SUCCESS;
185}
186
187/*
188**  SMFI_SETBACKLOG -- set backlog
189**
190**	Parameters:
191**		obacklog -- new backlog.
192**
193**	Returns:
194**		MI_SUCCESS/MI_FAILURE
195*/
196
197int
198smfi_setbacklog(obacklog)
199	int obacklog;
200{
201	if (obacklog <= 0)
202		return MI_FAILURE;
203	backlog = obacklog;
204	return MI_SUCCESS;
205}
206
207
208/*
209**  SMFI_MAIN -- setup milter connnection and start listener.
210**
211**	Parameters:
212**		none.
213**
214**	Returns:
215**		MI_SUCCESS/MI_FAILURE
216*/
217
218int
219smfi_main()
220{
221	int r;
222
223	(void) signal(SIGPIPE, SIG_IGN);
224	if (conn == NULL)
225	{
226		smi_log(SMI_LOG_FATAL, "%s: missing connection information",
227			smfi->xxfi_name);
228		return MI_FAILURE;
229	}
230
231	(void) atexit(mi_clean_signals);
232	if (mi_control_startup(smfi->xxfi_name) != MI_SUCCESS)
233	{
234		smi_log(SMI_LOG_FATAL,
235			"%s: Couldn't start signal thread",
236			smfi->xxfi_name);
237		return MI_FAILURE;
238	}
239	r = MI_MONITOR_INIT();
240
241	/* Startup the listener */
242	if (mi_listener(conn, dbg, smfi, timeout, backlog) != MI_SUCCESS)
243		r = MI_FAILURE;
244
245	return r;
246}
247
248