164562Sgshapiro/* 2261194Sgshapiro * Copyright (c) 1999-2003, 2006 Proofpoint, Inc. and its suppliers. 364562Sgshapiro * All rights reserved. 464562Sgshapiro * 564562Sgshapiro * By using this file, you agree to the terms and conditions set 664562Sgshapiro * forth in the LICENSE file which can be found at the top level of 764562Sgshapiro * the sendmail distribution. 864562Sgshapiro */ 964562Sgshapiro 1064562Sgshapiro/* 1164562Sgshapiro** LIBMILTER.H -- include file for mail filter library functions 1264562Sgshapiro*/ 1364562Sgshapiro 1464562Sgshapiro#ifndef _LIBMILTER_H 1564562Sgshapiro# define _LIBMILTER_H 1 1690792Sgshapiro 1790792Sgshapiro#include <sm/gen.h> 1890792Sgshapiro 1964562Sgshapiro#ifdef _DEFINE 2064562Sgshapiro# define EXTERN 2164562Sgshapiro# define INIT(x) = x 22266527SgshapiroSM_IDSTR(MilterlId, "@(#)$Id: libmilter.h,v 8.78 2013-11-22 20:51:36 ca Exp $") 23363466Sgshapiro#else 2464562Sgshapiro# define EXTERN extern 2564562Sgshapiro# define INIT(x) 26363466Sgshapiro#endif 2764562Sgshapiro 2864562Sgshapiro 29168515Sgshapiro#include "sm/tailq.h" 30168515Sgshapiro 3164562Sgshapiro#define NOT_SENDMAIL 1 3264562Sgshapiro#define _SOCK_ADDR union bigsockaddr 3364562Sgshapiro#include "sendmail.h" 3464562Sgshapiro 35168515Sgshapiro#ifdef SM_ASSERT 36168515Sgshapiro#undef SM_ASSERT 37168515Sgshapiro#endif 38168515Sgshapiro#ifndef SM_ASSERT 39168515Sgshapiro#include <assert.h> 40168515Sgshapiro#define SM_ASSERT(x) assert(x) 41168515Sgshapiro#endif 42168515Sgshapiro 4364562Sgshapiro#include "libmilter/milter.h" 4464562Sgshapiro 45168515Sgshapiro#define MAX_MACROS_ENTRIES 7 /* max size of macro pointer array */ 46168515Sgshapiro 47168515Sgshapirotypedef SM_TAILQ_HEAD(, smfi_str) smfi_hd_T; 48168515Sgshapirotypedef struct smfi_str smfi_str_S; 49168515Sgshapiro 50168515Sgshapiro/* 51168515Sgshapiro** Context for one milter session. 52168515Sgshapiro** 53168515Sgshapiro** Notes: 54168515Sgshapiro** There is a 1-1 correlation between a sendmail SMTP server process, 55168515Sgshapiro** an SMTP session, and an milter context. Due to the nature of SMTP 56168515Sgshapiro** session handling in sendmail 8, this libmilter implementation deals 57168515Sgshapiro** only with a single SMTP session per MTA - libmilter connection. 58168515Sgshapiro** 59168515Sgshapiro** There is no "global" context for libmilter, global variables are 60168515Sgshapiro** just that (they are not "collected" in a context). 61168515Sgshapiro** 62168515Sgshapiro** Implementation hint: 63168515Sgshapiro** macros are stored in mac_buf[] as sequence of: 64168515Sgshapiro** macro_name \0 macro_value 65168515Sgshapiro** (just as read from the MTA) 66168515Sgshapiro** mac_ptr is a list of pointers into mac_buf to the beginning of each 67168515Sgshapiro** entry, i.e., macro_name, macro_value, ... 68168515Sgshapiro*/ 69168515Sgshapiro 70168515Sgshapirostruct smfi_str 71168515Sgshapiro{ 72168515Sgshapiro sthread_t ctx_id; /* thread id */ 73168515Sgshapiro socket_t ctx_sd; /* socket descriptor */ 74168515Sgshapiro int ctx_dbg; /* debug level */ 75168515Sgshapiro time_t ctx_timeout; /* timeout */ 76168515Sgshapiro int ctx_state; /* state */ 77168515Sgshapiro smfiDesc_ptr ctx_smfi; /* filter description */ 78168515Sgshapiro 79168515Sgshapiro int ctx_prot_vers; /* libmilter protocol version */ 80168515Sgshapiro unsigned long ctx_aflags; /* milter action flags */ 81168515Sgshapiro 82168515Sgshapiro unsigned long ctx_pflags; /* milter protocol flags */ 83168515Sgshapiro 84168515Sgshapiro /* 85168515Sgshapiro ** milter protocol flags that are sent to the MTA; 86168515Sgshapiro ** this is the same as ctx_pflags except for those flags that 87168515Sgshapiro ** are not offered by the MTA but emulated in libmilter. 88168515Sgshapiro */ 89168515Sgshapiro 90168515Sgshapiro unsigned long ctx_pflags2mta; 91168515Sgshapiro 92168515Sgshapiro /* 93168515Sgshapiro ** milter protocol version that is sent to the MTA; 94168515Sgshapiro ** this is the same as ctx_prot_vers unless the 95168515Sgshapiro ** MTA protocol version (ctx_mta_prot_vers) is smaller 96168515Sgshapiro ** but still "acceptable". 97168515Sgshapiro */ 98168515Sgshapiro 99168515Sgshapiro int ctx_prot_vers2mta; 100168515Sgshapiro 101168515Sgshapiro char **ctx_mac_ptr[MAX_MACROS_ENTRIES]; 102168515Sgshapiro char *ctx_mac_buf[MAX_MACROS_ENTRIES]; 103168515Sgshapiro char *ctx_mac_list[MAX_MACROS_ENTRIES]; 104168515Sgshapiro char *ctx_reply; /* reply code */ 105168515Sgshapiro void *ctx_privdata; /* private data */ 106168515Sgshapiro 107168515Sgshapiro int ctx_mta_prot_vers; /* MTA protocol version */ 108168515Sgshapiro unsigned long ctx_mta_pflags; /* MTA protocol flags */ 109168515Sgshapiro unsigned long ctx_mta_aflags; /* MTA action flags */ 110168515Sgshapiro 111168515Sgshapiro#if _FFR_THREAD_MONITOR 112168515Sgshapiro time_t ctx_start; /* start time of thread */ 113168515Sgshapiro SM_TAILQ_ENTRY(smfi_str) ctx_mon_link; 114363466Sgshapiro#endif 115168515Sgshapiro 116168515Sgshapiro#if _FFR_WORKERS_POOL 117168515Sgshapiro long ctx_sid; /* session identifier */ 118168515Sgshapiro int ctx_wstate; /* state of the session (worker pool) */ 119168515Sgshapiro int ctx_wait; /* elapsed time waiting for sm cmd */ 120168515Sgshapiro SM_TAILQ_ENTRY(smfi_str) ctx_link; 121168515Sgshapiro#endif /* _FFR_WORKERS_POOL */ 122168515Sgshapiro}; 123168515Sgshapiro 12464562Sgshapiro# define ValidSocket(sd) ((sd) >= 0) 12590792Sgshapiro# define INVALID_SOCKET (-1) 12690792Sgshapiro# define closesocket close 12790792Sgshapiro# define MI_SOCK_READ(s, b, l) read(s, b, l) 12890792Sgshapiro# define MI_SOCK_READ_FAIL(x) ((x) < 0) 12990792Sgshapiro# define MI_SOCK_WRITE(s, b, l) write(s, b, l) 13064562Sgshapiro 13164562Sgshapiro# define thread_create(ptid,wr,arg) pthread_create(ptid, NULL, wr, arg) 13264562Sgshapiro# define sthread_get_id() pthread_self() 13364562Sgshapiro 13471345Sgshapirotypedef pthread_mutex_t smutex_t; 13571345Sgshapiro# define smutex_init(mp) (pthread_mutex_init(mp, NULL) == 0) 13671345Sgshapiro# define smutex_destroy(mp) (pthread_mutex_destroy(mp) == 0) 13771345Sgshapiro# define smutex_lock(mp) (pthread_mutex_lock(mp) == 0) 13871345Sgshapiro# define smutex_unlock(mp) (pthread_mutex_unlock(mp) == 0) 13971345Sgshapiro# define smutex_trylock(mp) (pthread_mutex_trylock(mp) == 0) 14071345Sgshapiro 141168515Sgshapiro#if _FFR_WORKERS_POOL 142168515Sgshapiro/* SM_CONF_POLL shall be defined with _FFR_WORKERS_POOL */ 143168515Sgshapiro# if !SM_CONF_POLL 144168515Sgshapiro# define SM_CONF_POLL 1 145363466Sgshapiro# endif 146168515Sgshapiro#endif /* _FFR_WORKERS_POOL */ 147168515Sgshapiro 148168515Sgshapirotypedef pthread_cond_t scond_t; 149168515Sgshapiro#define scond_init(cp) pthread_cond_init(cp, NULL) 150168515Sgshapiro#define scond_destroy(cp) pthread_cond_destroy(cp) 151168515Sgshapiro#define scond_wait(cp, mp) pthread_cond_wait(cp, mp) 152168515Sgshapiro#define scond_signal(cp) pthread_cond_signal(cp) 153168515Sgshapiro#define scond_broadcast(cp) pthread_cond_broadcast(cp) 154168515Sgshapiro#define scond_timedwait(cp, mp, to) \ 155168515Sgshapiro do \ 156168515Sgshapiro { \ 157168515Sgshapiro struct timespec timeout; \ 158168515Sgshapiro struct timeval now; \ 159168515Sgshapiro gettimeofday(&now, NULL); \ 160168515Sgshapiro timeout.tv_sec = now.tv_sec + to; \ 161168515Sgshapiro timeout.tv_nsec = now.tv_usec / 1000; \ 162168515Sgshapiro r = pthread_cond_timedwait(cp,mp,&timeout); \ 163168515Sgshapiro if (r != 0 && r != ETIMEDOUT) \ 164168515Sgshapiro smi_log(SMI_LOG_ERR, \ 165168515Sgshapiro "pthread_cond_timedwait error %d", r); \ 166168515Sgshapiro } while (0) 167168515Sgshapiro 168168515Sgshapiro 169132943Sgshapiro#if SM_CONF_POLL 170111823Sgshapiro 171111823Sgshapiro# include <poll.h> 172111823Sgshapiro# define MI_POLLSELECT "poll" 173111823Sgshapiro 174111823Sgshapiro# define MI_POLL_RD_FLAGS (POLLIN | POLLPRI) 175111823Sgshapiro# define MI_POLL_WR_FLAGS (POLLOUT) 176363466Sgshapiro# define MI_MS(timeout) (((timeout)->tv_sec * 1000) + (((timeout)->tv_usec) / 1000)) 177111823Sgshapiro 178111823Sgshapiro# define FD_RD_VAR(rds, excs) struct pollfd rds 179111823Sgshapiro# define FD_WR_VAR(wrs) struct pollfd wrs 180111823Sgshapiro 181111823Sgshapiro# define FD_RD_INIT(sd, rds, excs) \ 182111823Sgshapiro (rds).fd = (sd); \ 183111823Sgshapiro (rds).events = MI_POLL_RD_FLAGS; \ 184111823Sgshapiro (rds).revents = 0 185111823Sgshapiro 186111823Sgshapiro# define FD_WR_INIT(sd, wrs) \ 187111823Sgshapiro (wrs).fd = (sd); \ 188111823Sgshapiro (wrs).events = MI_POLL_WR_FLAGS; \ 189111823Sgshapiro (wrs).revents = 0 190111823Sgshapiro 191111823Sgshapiro# define FD_IS_RD_EXC(sd, rds, excs) \ 192111823Sgshapiro (((rds).revents & (POLLERR | POLLHUP | POLLNVAL)) != 0) 193111823Sgshapiro 194111823Sgshapiro# define FD_IS_WR_RDY(sd, wrs) \ 195111823Sgshapiro (((wrs).revents & MI_POLL_WR_FLAGS) != 0) 196111823Sgshapiro 197111823Sgshapiro# define FD_IS_RD_RDY(sd, rds, excs) \ 198111823Sgshapiro (((rds).revents & MI_POLL_RD_FLAGS) != 0) 199111823Sgshapiro 200363466Sgshapiro# define FD_WR_READY(sd, wrs, timeout) \ 201111823Sgshapiro poll(&(wrs), 1, MI_MS(timeout)) 202111823Sgshapiro 203111823Sgshapiro# define FD_RD_READY(sd, rds, excs, timeout) \ 204111823Sgshapiro poll(&(rds), 1, MI_MS(timeout)) 205111823Sgshapiro 206132943Sgshapiro#else /* SM_CONF_POLL */ 207111823Sgshapiro 208111823Sgshapiro# include <sm/fdset.h> 209111823Sgshapiro# define MI_POLLSELECT "select" 210111823Sgshapiro 211111823Sgshapiro# define FD_RD_VAR(rds, excs) fd_set rds, excs 212111823Sgshapiro# define FD_WR_VAR(wrs) fd_set wrs 213111823Sgshapiro 214111823Sgshapiro# define FD_RD_INIT(sd, rds, excs) \ 215111823Sgshapiro FD_ZERO(&(rds)); \ 216111823Sgshapiro FD_SET((unsigned int) (sd), &(rds)); \ 217111823Sgshapiro FD_ZERO(&(excs)); \ 218111823Sgshapiro FD_SET((unsigned int) (sd), &(excs)) 219111823Sgshapiro 220111823Sgshapiro# define FD_WR_INIT(sd, wrs) \ 221111823Sgshapiro FD_ZERO(&(wrs)); \ 222157001Sgshapiro FD_SET((unsigned int) (sd), &(wrs)) 223111823Sgshapiro 224111823Sgshapiro# define FD_IS_RD_EXC(sd, rds, excs) FD_ISSET(sd, &(excs)) 225111823Sgshapiro# define FD_IS_WR_RDY(sd, wrs) FD_ISSET((sd), &(wrs)) 226111823Sgshapiro# define FD_IS_RD_RDY(sd, rds, excs) FD_ISSET((sd), &(rds)) 227111823Sgshapiro 228111823Sgshapiro# define FD_WR_READY(sd, wrs, timeout) \ 229111823Sgshapiro select((sd) + 1, NULL, &(wrs), NULL, (timeout)) 230111823Sgshapiro# define FD_RD_READY(sd, rds, excs, timeout) \ 231111823Sgshapiro select((sd) + 1, &(rds), NULL, &(excs), (timeout)) 232111823Sgshapiro 233132943Sgshapiro#endif /* SM_CONF_POLL */ 234111823Sgshapiro 23564562Sgshapiro#include <sys/time.h> 23664562Sgshapiro 23764562Sgshapiro/* some defaults */ 23877349Sgshapiro#define MI_TIMEOUT 7210 /* default timeout for read/write */ 23964562Sgshapiro#define MI_CHK_TIME 5 /* checking whether to terminate */ 24064562Sgshapiro 24190792Sgshapiro#ifndef MI_SOMAXCONN 24290792Sgshapiro# if SOMAXCONN > 20 24390792Sgshapiro# define MI_SOMAXCONN SOMAXCONN 244363466Sgshapiro# else 24590792Sgshapiro# define MI_SOMAXCONN 20 246363466Sgshapiro# endif 24790792Sgshapiro#endif /* ! MI_SOMAXCONN */ 24866494Sgshapiro 24964562Sgshapiro/* maximum number of repeated failures in mi_listener() */ 25064562Sgshapiro#define MAX_FAILS_M 16 /* malloc() */ 25164562Sgshapiro#define MAX_FAILS_T 16 /* thread creation */ 25277349Sgshapiro#define MAX_FAILS_A 16 /* accept() */ 25390792Sgshapiro#define MAX_FAILS_S 16 /* select() */ 25464562Sgshapiro 25564562Sgshapiro/* internal "commands", i.e., error codes */ 25664562Sgshapiro#define SMFIC_TIMEOUT ((char) 1) /* timeout */ 25764562Sgshapiro#define SMFIC_SELECT ((char) 2) /* select error */ 25864562Sgshapiro#define SMFIC_MALLOC ((char) 3) /* malloc error */ 25964562Sgshapiro#define SMFIC_RECVERR ((char) 4) /* recv() error */ 26064562Sgshapiro#define SMFIC_EOF ((char) 5) /* eof */ 26164562Sgshapiro#define SMFIC_UNKNERR ((char) 6) /* unknown error */ 26264562Sgshapiro#define SMFIC_TOOBIG ((char) 7) /* body chunk too big */ 26364562Sgshapiro#define SMFIC_VALIDCMD ' ' /* first valid command */ 26464562Sgshapiro 26564562Sgshapiro/* hack */ 26664562Sgshapiro#define smi_log syslog 267120256Sgshapiro#define sm_dprintf (void) printf 26864562Sgshapiro#define milter_ret int 26964562Sgshapiro#define SMI_LOG_ERR LOG_ERR 27064562Sgshapiro#define SMI_LOG_FATAL LOG_ERR 27164562Sgshapiro#define SMI_LOG_WARN LOG_WARNING 27264562Sgshapiro#define SMI_LOG_INFO LOG_INFO 27364562Sgshapiro#define SMI_LOG_DEBUG LOG_DEBUG 27464562Sgshapiro 27564562Sgshapiro/* stop? */ 27664562Sgshapiro#define MILTER_CONT 0 27764562Sgshapiro#define MILTER_STOP 1 27864562Sgshapiro#define MILTER_ABRT 2 27964562Sgshapiro 28064562Sgshapiro/* functions */ 28164562Sgshapiroextern int mi_handle_session __P((SMFICTX_PTR)); 28264562Sgshapiroextern int mi_engine __P((SMFICTX_PTR)); 28366494Sgshapiroextern int mi_listener __P((char *, int, smfiDesc_ptr, time_t, int)); 28464562Sgshapiroextern void mi_clr_macros __P((SMFICTX_PTR, int)); 285203004Sgshapiroextern void mi_clr_ctx __P((SMFICTX_PTR)); 28664562Sgshapiroextern int mi_stop __P((void)); 28764562Sgshapiroextern int mi_control_startup __P((char *)); 28864562Sgshapiroextern void mi_stop_milters __P((int)); 28964562Sgshapiroextern void mi_clean_signals __P((void)); 29064562Sgshapiroextern struct hostent *mi_gethostbyname __P((char *, int)); 29190792Sgshapiroextern int mi_inet_pton __P((int, const char *, void *)); 29266494Sgshapiroextern void mi_closener __P((void)); 293125820Sgshapiroextern int mi_opensocket __P((char *, int, int, bool, smfiDesc_ptr)); 29464562Sgshapiro 29564562Sgshapiro/* communication functions */ 29664562Sgshapiroextern char *mi_rd_cmd __P((socket_t, struct timeval *, char *, size_t *, char *)); 29764562Sgshapiroextern int mi_wr_cmd __P((socket_t, struct timeval *, int, char *, size_t)); 29864562Sgshapiroextern bool mi_sendok __P((SMFICTX_PTR, int)); 29964562Sgshapiro 30090792Sgshapiro 301168515Sgshapiro#if _FFR_THREAD_MONITOR 302168515Sgshapiroextern bool Monitor; 303168515Sgshapiro 304168515Sgshapiro#define MI_MONITOR_INIT() mi_monitor_init() 305168515Sgshapiro#define MI_MONITOR_BEGIN(ctx, cmd) \ 306168515Sgshapiro do \ 307168515Sgshapiro { \ 308168515Sgshapiro if (Monitor) \ 309168515Sgshapiro mi_monitor_work_begin(ctx, cmd);\ 310168515Sgshapiro } while (0) 311168515Sgshapiro 312168515Sgshapiro#define MI_MONITOR_END(ctx, cmd) \ 313168515Sgshapiro do \ 314168515Sgshapiro { \ 315168515Sgshapiro if (Monitor) \ 316168515Sgshapiro mi_monitor_work_end(ctx, cmd); \ 317168515Sgshapiro } while (0) 318168515Sgshapiro 319168515Sgshapiroint mi_monitor_init __P((void)); 320168515Sgshapiroint mi_monitor_work_begin __P((SMFICTX_PTR, int)); 321168515Sgshapiroint mi_monitor_work_end __P((SMFICTX_PTR, int)); 322168515Sgshapiro 323168515Sgshapiro#else /* _FFR_THREAD_MONITOR */ 324168515Sgshapiro#define MI_MONITOR_INIT() MI_SUCCESS 325168515Sgshapiro#define MI_MONITOR_BEGIN(ctx, cmd) 326168515Sgshapiro#define MI_MONITOR_END(ctx, cmd) 327168515Sgshapiro#endif /* _FFR_THREAD_MONITOR */ 328168515Sgshapiro 329168515Sgshapiro#if _FFR_WORKERS_POOL 330168515Sgshapiroextern int mi_pool_manager_init __P((void)); 331168515Sgshapiroextern int mi_pool_controller_init __P((void)); 332168515Sgshapiroextern int mi_start_session __P((SMFICTX_PTR)); 333168515Sgshapiro#endif /* _FFR_WORKERS_POOL */ 334168515Sgshapiro 335110560Sgshapiro#endif /* ! _LIBMILTER_H */ 336