xref: /onnv-gate/usr/src/cmd/sendmail/libmilter/main.c (revision 11440:802724e2906a)
10Sstevel@tonic-gate /*
24518Sjbeck  *  Copyright (c) 1999-2003, 2006, 2007 Sendmail, Inc. and its suppliers.
30Sstevel@tonic-gate  *	All rights reserved.
40Sstevel@tonic-gate  *
50Sstevel@tonic-gate  * By using this file, you agree to the terms and conditions set
60Sstevel@tonic-gate  * forth in the LICENSE file which can be found at the top level of
70Sstevel@tonic-gate  * the sendmail distribution.
80Sstevel@tonic-gate  *
90Sstevel@tonic-gate  */
100Sstevel@tonic-gate 
110Sstevel@tonic-gate #include <sm/gen.h>
12*11440SJohn.Beck@Sun.COM SM_RCSID("@(#)$Id: main.c,v 8.84 2008/09/02 05:37:06 ca Exp $")
130Sstevel@tonic-gate 
140Sstevel@tonic-gate #define _DEFINE	1
150Sstevel@tonic-gate #include "libmilter.h"
160Sstevel@tonic-gate #include <fcntl.h>
170Sstevel@tonic-gate #include <sys/stat.h>
180Sstevel@tonic-gate 
190Sstevel@tonic-gate 
200Sstevel@tonic-gate static smfiDesc_ptr smfi = NULL;
210Sstevel@tonic-gate 
220Sstevel@tonic-gate /*
230Sstevel@tonic-gate **  SMFI_REGISTER -- register a filter description
240Sstevel@tonic-gate **
250Sstevel@tonic-gate **	Parameters:
260Sstevel@tonic-gate **		smfilter -- description of filter to register
270Sstevel@tonic-gate **
280Sstevel@tonic-gate **	Returns:
290Sstevel@tonic-gate **		MI_SUCCESS/MI_FAILURE
300Sstevel@tonic-gate */
310Sstevel@tonic-gate 
320Sstevel@tonic-gate int
smfi_register(smfilter)330Sstevel@tonic-gate smfi_register(smfilter)
340Sstevel@tonic-gate 	smfiDesc_str smfilter;
350Sstevel@tonic-gate {
360Sstevel@tonic-gate 	size_t len;
370Sstevel@tonic-gate 
380Sstevel@tonic-gate 	if (smfi == NULL)
390Sstevel@tonic-gate 	{
400Sstevel@tonic-gate 		smfi = (smfiDesc_ptr) malloc(sizeof *smfi);
410Sstevel@tonic-gate 		if (smfi == NULL)
420Sstevel@tonic-gate 			return MI_FAILURE;
430Sstevel@tonic-gate 	}
440Sstevel@tonic-gate 	(void) memcpy(smfi, &smfilter, sizeof *smfi);
450Sstevel@tonic-gate 	if (smfilter.xxfi_name == NULL)
460Sstevel@tonic-gate 		smfilter.xxfi_name = "Unknown";
470Sstevel@tonic-gate 
480Sstevel@tonic-gate 	len = strlen(smfilter.xxfi_name) + 1;
490Sstevel@tonic-gate 	smfi->xxfi_name = (char *) malloc(len);
500Sstevel@tonic-gate 	if (smfi->xxfi_name == NULL)
510Sstevel@tonic-gate 		return MI_FAILURE;
520Sstevel@tonic-gate 	(void) sm_strlcpy(smfi->xxfi_name, smfilter.xxfi_name, len);
530Sstevel@tonic-gate 
540Sstevel@tonic-gate 	/* compare milter version with hard coded version */
55*11440SJohn.Beck@Sun.COM 	if ((SM_LM_VRS_MAJOR(smfi->xxfi_version) != SM_LM_VRS_MAJOR(SMFI_VERSION) ||
56*11440SJohn.Beck@Sun.COM 	     SM_LM_VRS_MINOR(smfi->xxfi_version) != SM_LM_VRS_MINOR(SMFI_VERSION)) &&
574518Sjbeck 	    smfi->xxfi_version != 2 &&
584518Sjbeck 	    smfi->xxfi_version != 3 &&
594518Sjbeck 	    smfi->xxfi_version != 4)
600Sstevel@tonic-gate 	{
610Sstevel@tonic-gate 		/* hard failure for now! */
620Sstevel@tonic-gate 		smi_log(SMI_LOG_ERR,
630Sstevel@tonic-gate 			"%s: smfi_register: version mismatch application: %d != milter: %d",
640Sstevel@tonic-gate 			smfi->xxfi_name, smfi->xxfi_version,
650Sstevel@tonic-gate 			(int) SMFI_VERSION);
660Sstevel@tonic-gate 
670Sstevel@tonic-gate 		/* XXX how about smfi? */
680Sstevel@tonic-gate 		free(smfi->xxfi_name);
690Sstevel@tonic-gate 		return MI_FAILURE;
700Sstevel@tonic-gate 	}
710Sstevel@tonic-gate 
720Sstevel@tonic-gate 	return MI_SUCCESS;
730Sstevel@tonic-gate }
740Sstevel@tonic-gate 
750Sstevel@tonic-gate /*
760Sstevel@tonic-gate **  SMFI_STOP -- stop milter
770Sstevel@tonic-gate **
780Sstevel@tonic-gate **	Parameters:
790Sstevel@tonic-gate **		none.
800Sstevel@tonic-gate **
810Sstevel@tonic-gate **	Returns:
820Sstevel@tonic-gate **		success.
830Sstevel@tonic-gate */
840Sstevel@tonic-gate 
850Sstevel@tonic-gate int
smfi_stop()860Sstevel@tonic-gate smfi_stop()
870Sstevel@tonic-gate {
880Sstevel@tonic-gate 	mi_stop_milters(MILTER_STOP);
890Sstevel@tonic-gate 	return MI_SUCCESS;
900Sstevel@tonic-gate }
910Sstevel@tonic-gate 
920Sstevel@tonic-gate /*
930Sstevel@tonic-gate **  Default values for some variables.
940Sstevel@tonic-gate **	Most of these can be changed with the functions below.
950Sstevel@tonic-gate */
960Sstevel@tonic-gate 
970Sstevel@tonic-gate static int dbg = 0;
980Sstevel@tonic-gate static char *conn = NULL;
990Sstevel@tonic-gate static int timeout = MI_TIMEOUT;
1000Sstevel@tonic-gate static int backlog = MI_SOMAXCONN;
1010Sstevel@tonic-gate 
1020Sstevel@tonic-gate /*
1030Sstevel@tonic-gate **  SMFI_OPENSOCKET -- try the socket setup to make sure we'll be
1040Sstevel@tonic-gate **		       able to start up
1050Sstevel@tonic-gate **
1060Sstevel@tonic-gate **	Parameters:
1070Sstevel@tonic-gate **		rmsocket -- if true, instructs libmilter to attempt
1080Sstevel@tonic-gate **			to remove the socket before creating it;
1090Sstevel@tonic-gate **			only applies for "local:" or "unix:" sockets
1100Sstevel@tonic-gate **
1110Sstevel@tonic-gate **	Return:
1120Sstevel@tonic-gate **		MI_SUCCESS/MI_FAILURE
1130Sstevel@tonic-gate */
1140Sstevel@tonic-gate 
1150Sstevel@tonic-gate int
smfi_opensocket(rmsocket)1160Sstevel@tonic-gate smfi_opensocket(rmsocket)
1170Sstevel@tonic-gate 	bool rmsocket;
1180Sstevel@tonic-gate {
1190Sstevel@tonic-gate 	if (smfi == NULL || conn == NULL)
1200Sstevel@tonic-gate 		return MI_FAILURE;
1210Sstevel@tonic-gate 
1220Sstevel@tonic-gate 	return mi_opensocket(conn, backlog, dbg, rmsocket, smfi);
1230Sstevel@tonic-gate }
1240Sstevel@tonic-gate 
1250Sstevel@tonic-gate /*
1260Sstevel@tonic-gate **  SMFI_SETDBG -- set debug level.
1270Sstevel@tonic-gate **
1280Sstevel@tonic-gate **	Parameters:
1290Sstevel@tonic-gate **		odbg -- new debug level.
1300Sstevel@tonic-gate **
1310Sstevel@tonic-gate **	Returns:
1320Sstevel@tonic-gate **		MI_SUCCESS
1330Sstevel@tonic-gate */
1340Sstevel@tonic-gate 
1350Sstevel@tonic-gate int
smfi_setdbg(odbg)1360Sstevel@tonic-gate smfi_setdbg(odbg)
1370Sstevel@tonic-gate 	int odbg;
1380Sstevel@tonic-gate {
1390Sstevel@tonic-gate 	dbg = odbg;
1400Sstevel@tonic-gate 	return MI_SUCCESS;
1410Sstevel@tonic-gate }
1420Sstevel@tonic-gate 
1430Sstevel@tonic-gate /*
1440Sstevel@tonic-gate **  SMFI_SETTIMEOUT -- set timeout (for read/write).
1450Sstevel@tonic-gate **
1460Sstevel@tonic-gate **	Parameters:
1470Sstevel@tonic-gate **		otimeout -- new timeout.
1480Sstevel@tonic-gate **
1490Sstevel@tonic-gate **	Returns:
1500Sstevel@tonic-gate **		MI_SUCCESS
1510Sstevel@tonic-gate */
1520Sstevel@tonic-gate 
1530Sstevel@tonic-gate int
smfi_settimeout(otimeout)1540Sstevel@tonic-gate smfi_settimeout(otimeout)
1550Sstevel@tonic-gate 	int otimeout;
1560Sstevel@tonic-gate {
1570Sstevel@tonic-gate 	timeout = otimeout;
1580Sstevel@tonic-gate 	return MI_SUCCESS;
1590Sstevel@tonic-gate }
1600Sstevel@tonic-gate 
1610Sstevel@tonic-gate /*
1620Sstevel@tonic-gate **  SMFI_SETCONN -- set connection information (socket description)
1630Sstevel@tonic-gate **
1640Sstevel@tonic-gate **	Parameters:
1650Sstevel@tonic-gate **		oconn -- new connection information.
1660Sstevel@tonic-gate **
1670Sstevel@tonic-gate **	Returns:
1680Sstevel@tonic-gate **		MI_SUCCESS/MI_FAILURE
1690Sstevel@tonic-gate */
1700Sstevel@tonic-gate 
1710Sstevel@tonic-gate int
smfi_setconn(oconn)1720Sstevel@tonic-gate smfi_setconn(oconn)
1730Sstevel@tonic-gate 	char *oconn;
1740Sstevel@tonic-gate {
1750Sstevel@tonic-gate 	size_t l;
1760Sstevel@tonic-gate 
1770Sstevel@tonic-gate 	if (oconn == NULL || *oconn == '\0')
1780Sstevel@tonic-gate 		return MI_FAILURE;
1790Sstevel@tonic-gate 	l = strlen(oconn) + 1;
1800Sstevel@tonic-gate 	if ((conn = (char *) malloc(l)) == NULL)
1810Sstevel@tonic-gate 		return MI_FAILURE;
1820Sstevel@tonic-gate 	if (sm_strlcpy(conn, oconn, l) >= l)
1830Sstevel@tonic-gate 		return MI_FAILURE;
1840Sstevel@tonic-gate 	return MI_SUCCESS;
1850Sstevel@tonic-gate }
1860Sstevel@tonic-gate 
1870Sstevel@tonic-gate /*
1880Sstevel@tonic-gate **  SMFI_SETBACKLOG -- set backlog
1890Sstevel@tonic-gate **
1900Sstevel@tonic-gate **	Parameters:
1910Sstevel@tonic-gate **		obacklog -- new backlog.
1920Sstevel@tonic-gate **
1930Sstevel@tonic-gate **	Returns:
1940Sstevel@tonic-gate **		MI_SUCCESS/MI_FAILURE
1950Sstevel@tonic-gate */
1960Sstevel@tonic-gate 
1970Sstevel@tonic-gate int
smfi_setbacklog(obacklog)1980Sstevel@tonic-gate smfi_setbacklog(obacklog)
1990Sstevel@tonic-gate 	int obacklog;
2000Sstevel@tonic-gate {
2010Sstevel@tonic-gate 	if (obacklog <= 0)
2020Sstevel@tonic-gate 		return MI_FAILURE;
2030Sstevel@tonic-gate 	backlog = obacklog;
2040Sstevel@tonic-gate 	return MI_SUCCESS;
2050Sstevel@tonic-gate }
2060Sstevel@tonic-gate 
2070Sstevel@tonic-gate 
2080Sstevel@tonic-gate /*
2090Sstevel@tonic-gate **  SMFI_MAIN -- setup milter connnection and start listener.
2100Sstevel@tonic-gate **
2110Sstevel@tonic-gate **	Parameters:
2120Sstevel@tonic-gate **		none.
2130Sstevel@tonic-gate **
2140Sstevel@tonic-gate **	Returns:
2150Sstevel@tonic-gate **		MI_SUCCESS/MI_FAILURE
2160Sstevel@tonic-gate */
2170Sstevel@tonic-gate 
2180Sstevel@tonic-gate int
smfi_main()2190Sstevel@tonic-gate smfi_main()
2200Sstevel@tonic-gate {
2210Sstevel@tonic-gate 	int r;
2220Sstevel@tonic-gate 
2230Sstevel@tonic-gate 	(void) signal(SIGPIPE, SIG_IGN);
2240Sstevel@tonic-gate 	if (conn == NULL)
2250Sstevel@tonic-gate 	{
2260Sstevel@tonic-gate 		smi_log(SMI_LOG_FATAL, "%s: missing connection information",
2270Sstevel@tonic-gate 			smfi->xxfi_name);
2280Sstevel@tonic-gate 		return MI_FAILURE;
2290Sstevel@tonic-gate 	}
2300Sstevel@tonic-gate 
2310Sstevel@tonic-gate 	(void) atexit(mi_clean_signals);
2320Sstevel@tonic-gate 	if (mi_control_startup(smfi->xxfi_name) != MI_SUCCESS)
2330Sstevel@tonic-gate 	{
2340Sstevel@tonic-gate 		smi_log(SMI_LOG_FATAL,
2350Sstevel@tonic-gate 			"%s: Couldn't start signal thread",
2360Sstevel@tonic-gate 			smfi->xxfi_name);
2370Sstevel@tonic-gate 		return MI_FAILURE;
2380Sstevel@tonic-gate 	}
2393544Sjbeck 	r = MI_MONITOR_INIT();
2400Sstevel@tonic-gate 
2410Sstevel@tonic-gate 	/* Startup the listener */
2420Sstevel@tonic-gate 	if (mi_listener(conn, dbg, smfi, timeout, backlog) != MI_SUCCESS)
2430Sstevel@tonic-gate 		r = MI_FAILURE;
2440Sstevel@tonic-gate 
2450Sstevel@tonic-gate 	return r;
2460Sstevel@tonic-gate }
2470Sstevel@tonic-gate 
248