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