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