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