/*
* Copyright (c) 1999-2006 Sendmail, Inc. and its suppliers.
* All rights reserved.
*
* By using this file, you agree to the terms and conditions set
* forth in the LICENSE file which can be found at the top level of
* the sendmail distribution.
*
* $Id: pmfapi.h,v 1.37 2007/02/16 02:39:09 ca Exp $
*/
/*
** PMFAPI.H -- Global definitions for policy mail filter library
** and policy mail filters.
*/
#ifndef PMFAPI_H
#define PMFAPI_H 1
/* libpmilter version */
#define LPMILTER_VERSION_MAJOR 0x01
#define LPMILTER_VERSION_MINOR 0x0000
#define LPMILTER_VERSION_PL 0x00
#define LPMILTER_VERSION ((LPMILTER_VERSION_MAJOR << 24) + \
(LPMILTER_VERSION_MINOR << 8) + \
LPMILTER_VERSION_PL)
#define SM_PM_VRS_MAJOR(v) (((v) & 0x7f000000) >> 24)
#define SM_PM_VRS_MINOR(v) (((v) & 0x007fff00) >> 8)
#define SM_PM_VRS_PLVL(v) ((v) & 0x0000007f)
#ifdef WIN32
# include <winsock2.h>
#endif
#include "sm/pmfdef.h"
#ifdef WIN32
/*
** The following ifdef block is the standard way of creating macros which make
** exporting from a DLL simpler. All files within this DLL are compiled with
** the LIBMILTER_EXPORTS symbol defined. LIBMILTER_EXPORTS should not be
** defined on any project that uses this DLL. This way any other project whose
** source files include this file see LIBSASL_API functions as being imported
** from a DLL, wheras this DLL sees symbols defined with this macro as being
** exported.
** Under UNIX, life is simpler: we just need to mark library functions
** as extern. (Technically, we don't even have to do that.)
*/
# ifdef WIN32_DLL
# ifdef LIBMILTER_EXPORTS
# define LIBMILTER_API __declspec( dllexport )
# else
# define LIBMILTER_API __declspec( dllimport )
# endif
# else
# define LIBMILTER_API extern
# endif
#else /* WIN32 */
# define LIBMILTER_API extern
#endif /* WIN32 */
#ifdef WIN32
/*
** Disable warning messages for differences in parameter lists.
** The Microsoft compiler spits out a warning message if a
** function pointer is assigned to another function pointer,
** but the formal parameter lists of the functions do not agree.
** The assignments are compiled without modification though,
** so it's safe to disable this warning message.
*/
#pragma warning( disable : 4113 )
#endif /* WIN32 */
/* Only need to export C interface if used by C++ source code */
#ifdef __cplusplus
extern "C" {
#endif
#ifndef SM_NET_H
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <sys/un.h>
/*
** generic sockaddr structure for sendmail
** make parts of this conditional, compare sendmail8/sendmail/sendmail.h
*/
union sm_sockaddr_U
{
struct sockaddr sa; /* general version */
struct sockaddr_un sunix; /* UNIX family */
struct sockaddr_in sin; /* INET family */
};
typedef union sm_sockaddr_U sm_sockaddr_T, *sm_sockaddr_P;
#endif /* SM_NET_H */
/*
** libmilter functions return SM_PMI_SUCCESS to indicate success;
** a value < 0 indicates an error.
*/
#define SM_PMI_SUCCESS 0
#define SM_PMI_FAILURE (-1)
/*
** Type which callbacks should return to indicate message status.
** This may take on one of the SMFIS_* values listed below.
*/
typedef int sfsistat_T;
/* XREF: must be smaller than QSS_RC_MAXSZ, see sm/qmgrcomm.h */
#define PMILTER_CHUNK_SIZE (256 * 1024)
#if defined(QSS_RC_MAXSZ) && QSS_RC_MAXSZ < PMILTER_CHUNK_SIZE
ERROR: _QSS_RC_MAXSZ >= _PMILTER_CHUNK_SIZE
#endif
/*
** Filter Routine Details
*/
/*
** PMFI_NEGOTIATE -- check whether server capabilities and functions are
** acceptable/sufficient
*/
typedef sm_ret_T (*pmfi_negotiate_F)(pmss_ctx_P _pmss_ctx, uint32_t _srv_cap, uint32_t _srv_fct, uint32_t _srv_feat, uint32_t _srv_misc, uint32_t *_pm_cap, uint32_t *_pm_fct, uint32_t *_pm_feat, uint32_t *_pm_misc);
/*
** PMFI_CONNECT -- SMTP connection
**
** hostname -- Host domain name, as determined by a reverse lookup
** on the host address.
** hostaddr -- Host address, as determined by a getpeername
** call on the SMTP socket.
*/
typedef sfsistat_T (*pmfi_connect_F)(pmse_ctx_P _pmse_ctx, const char *_hostname, sm_sockaddr_T *_hostaddr);
/*
** PMFI_HELO -- SMTP HELO/EHLO command
**
** helohost -- Value passed to HELO/EHLO command, which should be
** the domain name of the sending host (but is, in practice,
** anything the sending host wants to send).
** ehlo -- was EHLO used?
*/
typedef sfsistat_T (*pmfi_helo_F)(pmse_ctx_P _pmse_ctx, const char *_helohost, bool _ehlo);
/*
** PMFI_STARTTLS -- STARTTLS
*/
typedef sfsistat_T (*pmfi_starttls_F)(pmse_ctx_P _pmse_ctx);
/*
** PMFI_AUTH -- AUTH
*/
typedef sfsistat_T (*pmfi_auth_F)(pmse_ctx_P _pmse_ctx, const char *_arg);
/*
** PMFI_MAIL -- envelope MAIL From
**
** argv -- Null-terminated SMTP command arguments;
*/
typedef sfsistat_T (*pmfi_mail_F)(pmse_ctx_P _pmse_ctx, const char *_mail, char **_argv);
/*
** PMFI_RCPT -- envelope recipient
**
** char **argv -- Null-terminated SMTP command arguments;
*/
typedef sfsistat_T (*pmfi_rcpt_F)(pmse_ctx_P _pmse_ctx, const char *_rcpt, char **_argv);
/*
** PMFI_DATA -- DATA
*/
typedef sfsistat_T (*pmfi_data_F)(pmse_ctx_P _pmse_ctx);
/*
** PMFI_UNKNOWN -- unknown/not implemented SMTP command
**
** cmd -- Null-terminated SMTP command
*/
typedef sfsistat_T (*pmfi_unknown_F)(pmse_ctx_P _pmse_ctx, const char *_cmd);
/*
** PMFI_MSG -- message chunk
** There may be multiple message chunks passed to the filter. End-of-lines are
** represented as received from SMTP (normally Carriage-Return/Line-Feed).
**
** msgp -- Pointer to message data
** msglen -- Length of message data
*/
typedef sfsistat_T (*pmfi_msg_F)(pmse_ctx_P _pmse_ctx, unsigned char *_msgp, size_t _msglen);
/*
** PMFI_EOM -- end of message.
*/
typedef sfsistat_T (*pmfi_eom_F)(pmse_ctx_P _pmse_ctx);
/*
** PMFI_MSG_RPLC -- message replacement: send one chunk
*/
typedef sfsistat_T (*pmfi_msg_rplc_F)(pmse_ctx_P _pmse_ctx, const unsigned char **_pmsgchunk, size_t *_pmsglen);
/*
** PMFI_MSG_RPLC_STAT -- message replacement status
*/
typedef sfsistat_T (*pmfi_msg_rplc_stat_F)(pmse_ctx_P _pmse_ctx, sm_ret_T _status);
/*
** PMFI_ABORT -- message is aborted outside of the control of
** the filter, for example, if the SMTP sender issues an RSET command. If
** pmfi_abort is called, pmfi_eom will not be called and vice versa.
*/
typedef sm_ret_T (*pmfi_abort_F)(pmse_ctx_P _pmse_ctx);
/*
** PMFI_CLOSE -- end of the connection. This is called on
** close even if the previous mail transaction was aborted.
*/
typedef sm_ret_T (*pmfi_close_F)(pmse_ctx_P _pmse_ctx);
/* XXX which context? */
typedef sm_ret_T (*pmfi_signal_F)(pmg_ctx_P _pmg_ctx, int _sig);
/*
** structure describing one milter
*/
struct pmilter_S
{
char *pmfi_name; /* filter name */
uint32_t pmfi_version; /* version code -- do not change */
/* what does the milter want by default? */
uint32_t pmfi_dfl_cap; /* capabilities */
uint32_t pmfi_dfl_fct; /* functions */
uint32_t pmfi_dfl_feat; /* features */
uint32_t pmfi_dfl_misc; /* misc. */
/* negotiate */
pmfi_negotiate_F pmfi_negotiate;
/* connect */
pmfi_connect_F pmfi_connect;
/* HELO/EHLO */
pmfi_helo_F pmfi_helo;
/* MAIL */
pmfi_mail_F pmfi_mail;
/* RCPT */
pmfi_rcpt_F pmfi_rcpt;
/* DATA */
pmfi_data_F pmfi_data;
/* msg block */
pmfi_msg_F pmfi_msg;
/* end of message */
pmfi_eom_F pmfi_eom;
/* message aborted */
pmfi_abort_F pmfi_abort;
/* connection cleanup */
pmfi_close_F pmfi_close;
/* any unrecognized or unimplemented command filter */
pmfi_unknown_F pmfi_unknown;
pmfi_signal_F pmfi_signal;
/* STARTTLS */
pmfi_starttls_F pmfi_starttls;
/* AUTH */
pmfi_auth_F pmfi_auth;
pmfi_msg_rplc_F pmfi_msg_rplc;
pmfi_msg_rplc_stat_F pmfi_msg_rplc_stat;
char pmfi_unused[64];
};
LIBMILTER_API sm_ret_T sm_pmfi_init(pmg_ctx_P *_pmg_ctx);
LIBMILTER_API sm_ret_T sm_pmfi_version(pmg_ctx_P _pmg_ctx, uint32_t *_major, uint32_t *_minor, uint32_t *_patchlevel);
LIBMILTER_API sm_ret_T sm_pmfi_setconn(pmg_ctx_P _pmg_ctx, const char *_path);
LIBMILTER_API sm_ret_T sm_pmfi_start(pmg_ctx_P _pmg_ctx, pmilter_P _pmilter);
LIBMILTER_API sm_ret_T sm_pmfi_setdbg(pmg_ctx_P _pmg_ctx, unsigned int _debuglevel);
LIBMILTER_API sm_ret_T sm_pmfi_stop(pmg_ctx_P _pmg_ctx);
#if 0
/* not yet implemented */
LIBMILTER_API sm_ret_T sm_pmfi_setbacklog(pmg_ctx_P _pmg_ctx, int _backlog);
LIBMILTER_API sm_ret_T sm_pmfi_settimeout(pmg_ctx_P _pmg_ctx, int _timeout);
/* is this needed?? */
LIBMILTER_API sm_ret_T sm_pmfi_opensocket(pmg_ctx_P _pmg_ctx, bool _rmsocket);
/*
not needed
LIBMILTER_API sm_ret_T sm_pmfi_register(pmg_ctx_P _pmg_ctx, pmilter_P _pmilter);
*/
#endif
/*
** set/get pmilter contexts
*/
/* "global" pmilter context: one per process */
LIBMILTER_API sm_ret_T sm_pmfi_set_ctx_g(pmg_ctx_P _pmg_ctx, void *_pmilter_g_ctx);
LIBMILTER_API void *sm_pmfi_get_ctx_g(pmg_ctx_P _pmg_ctx);
/* pmilter context per SMTP server */
LIBMILTER_API sm_ret_T sm_pmfi_set_ctx_ss(pmss_ctx_P _pmss_ctx, void *_pmilter_ss_ctx);
LIBMILTER_API void *sm_pmfi_get_ctx_ss(pmss_ctx_P _pmss_ctx);
/* get "global" context from ss context */
LIBMILTER_API void *sm_pmfi_get_ctx_g_ss(pmss_ctx_P _pmss_ctx);
/* pmilter context per SMTP session */
LIBMILTER_API sm_ret_T sm_pmfi_set_ctx_se(pmse_ctx_P _pmse_ctx, void *_pmilter_se_ctx);
LIBMILTER_API void *sm_pmfi_get_ctx_se(pmse_ctx_P _pmse_ctx);
/* get ss context from session context */
LIBMILTER_API void *sm_pmfi_get_ctx_ss_se(pmse_ctx_P _pmse_ctx);
/*
** Continue processing message/connection.
*/
#define SMFIS_CONTINUE SMTP_R_OK
/*
** Reject the message/connection.
** No further routines will be called for this message
** (or connection, if returned from a connection-oriented routine).
*/
#define SMFIS_REJECT SMTP_R_REJECT
/*
** Accept the command, but silently discard it.
** No further routines will be called for this message.
** This is only meaningful from message-oriented routines.
*/
#define SMFIS_DISCARD SMTP_R_DISCARD
/*
** Accept the message/connection.
** No further routines will be called for this message
** (or connection, if returned from a connection-oriented routine;
** in this case, it causes all messages on this connection
** to be accepted without filtering).
*/
#define SMFIS_ACCEPT SMTP_R_SET_QUICK(SMTP_R_OK)
/*
** Return a temporary failure, i.e.,
** the corresponding SMTP command will return a 4xx status code.
** In some cases this may prevent further routines from
** being called on this message or connection,
** although in other cases (e.g., when processing an envelope
** recipient) processing of the message will continue.
*/
#define SMFIS_TEMPFAIL SMTP_R_TEMP
/*
** Additional information is passed in to the vendor filter routines using
** symbols. Symbols correspond closely to sendmail macros. The symbols
** defined depend on the context. The value of a symbol is accessed using:
*/
/*
** Set list of macros that should be sent by MTA
**
** pmss_ctx -- Opaque context structure
** where -- Which stage? (PM_SMST_*, see pmfdef.h)
** macro -- The symbols to send (PMM_*, see pmfdef.h),
** must end with PMM_END
*/
LIBMILTER_API sm_ret_T sm_pmfi_setmaclist(pmss_ctx_P _pmss_ctx, uint _where, ...);
/*
** Get value of a symbol.
**
** pmse_ctx_P ctx -- Opaque context structure
** macro -- The symbol to access (PMM_*, see pmfdef.h)
** value -- (pointer to) value of symbol
*/
LIBMILTER_API sm_ret_T sm_pmfi_getmac(pmse_ctx_P _pmse_ctx, uint32_t _macro, char **_pvalue);
/*
** Set the specific reply code to be used in response to the active
** command. If not specified, a generic reply code is used.
**
** pmse_ctx -- Opaque context structure
** reply -- The text part of the SMTP reply (including error codes).
*/
LIBMILTER_API sm_ret_T sm_pmfi_setreply(pmse_ctx_P _pmse_ctx, const char *_reply);
/*
** Set reply codes to be used in response to the active command if multiple
** replies are required.
**
** pmse_ctx -- Opaque context structure
** nreplies -- number of replies
** rcodes -- array of nreplies reply codes
** rtexts -- array of nreplies reply texts
*/
LIBMILTER_API sm_ret_T sm_pmfi_setreplies(pmse_ctx_P _pmse_ctx, uint _nreplies, int *_rcodes, const char **_rtexts);
/*
** Get status of current SMTP command as set by SMTPS.
** Currently only available for RCPT (if requested)
**
** pmse_ctx -- Opaque context structure
** pstatus -- (pointer to) status (output)
*/
LIBMILTER_API sm_ret_T sm_pmfi_getstatus(pmse_ctx_P _pmse_ctx, sfsistat_T *_pstatus);
/*
** Get index of current RCPT command as set by SMTPS.
**
** pmse_ctx -- Opaque context structure
** prcpt_idx -- (pointer to) recipient index (output)
*/
LIBMILTER_API sm_ret_T sm_pmfi_getrcpt_idx(pmse_ctx_P _pmse_ctx, rcpt_idx_T *_prcpt_idx);
/*
** header modification request
**
** pmse_ctx -- Opaque context structure
** type -- type of modification
** pos -- header position
** header -- complete header field (name and value)
*/
LIBMILTER_API sm_ret_T sm_pmfi_hdr_mod(pmse_ctx_P _pmse_ctx, uint _type, uint _pos, const unsigned char *_header);
/*
** recipient addition request
**
** pmse_ctx -- Opaque context structure
** rcpt_pa -- recipient address to add (RFC 2821 format)
** argv -- list of SMTP parameter for RCPT, NULL terminated list.
** argv == NULL: use original
** argv[0] == NULL: no parameters
*/
LIBMILTER_API sm_ret_T sm_pmfi_rcpt_add(pmse_ctx_P _pmse_ctx, const char *_rcpt_pa, char **_argv);
/*
** recipient deletion request
**
** pmse_ctx -- Opaque context structure
** rcpt_pa -- recipient address to delete (RFC 2821 format)
** rcpt_idx -- index of recipient address to delete
*/
LIBMILTER_API sm_ret_T sm_pmfi_rcpt_del(pmse_ctx_P _pmse_ctx, const char *_rcpt_pa, rcpt_idx_T _rcpt_idx);
/*
** MAIL replacement request
**
** pmse_ctx -- Opaque context structure
** mail_pa -- mail address to use instead of original (RFC 2821 format)
** args -- ESMTP parameters for MAIL
** args == NULL: use original
** args[0] == NUL: no parameters
*/
LIBMILTER_API sm_ret_T sm_pmfi_mail_rplc(pmse_ctx_P _pmse_ctx, const char *_mail_pa, char *_argv);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* ! PMFAPI_H */
syntax highlighted by Code2HTML, v. 0.9.1