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