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