/*
* Copyright (c) 2002-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: smar.h,v 1.112 2007/11/14 06:03:09 ca Exp $
*/
#ifndef SMAR_H
#define SMAR_H 1
#include "sm/generic.h"
#include "sm/net.h"
#include "sm/evthr.h"
#include "sm/rpool.h"
#include "sm/rcb.h"
#include "sm/rcbl.h"
#include "sm/rcbcomm.h"
#include "sm/queue.h"
#include "sm/bhtable.h"
#include "sm/pthread.h"
#include "sm/mta.h"
#include "sm/map.h"
#include "sm/log.h"
#include "sm/smar.h"
#include "smarstr.h"
#include "sm/sm-conf.h"
#include "sm/smarcnf.h"
#include "sm/rfc2821.h"
#include "sm/greyctl.h"
/* access map required? */
#define SMAR_LT_ACCESS (SMARA_LT_CERT_RELAY|\
SMARA_LT_CLT_A_ACC|SMARA_LT_CLT_N_ACC|\
SMARA_LT_RVRS_N_ACC|\
SMARA_LT_EHLO_ACC|\
SMARA_LT_MAIL_ACC|\
SMARA_LT_RCPT_ACC|SMARA_LT_RCPT_PROT)
#ifndef SMAR_USE_DNS
# define SMAR_USE_DNS 1
#endif
/*
** Limits for (currently compile time only)
** number of MX records per domain
** number of A records per MX record
*/
#ifndef SM_DNS_MX_MAX
# define SM_DNS_MX_MAX 50
#endif
#ifndef SM_DNS_A_PER_MX_MAX
# define SM_DNS_A_PER_MX_MAX 50
#endif
#ifndef SMAR_TEST
# define SMAR_TEST 1
#endif
#ifndef SM_ALIASES_LARGE
# define SM_ALIASES_LARGE 1
#endif
#if SMAR_USE_DNS
# include "sm/dns.h"
# include "sm/dns-int.h"
# include "sm/dnstsk.h"
#endif /* SMAR_USE_DNS */
#if SM_ALIASES_LARGE
# define DNS_MGR_HTSIZE 4993u
# define DNS_MGR_HTMAX 29989u
#else /* SM_ALIASES_LARGE */
# define DNS_MGR_HTSIZE 0u
# define DNS_MGR_HTMAX 0u
#endif /* SM_ALIASES_LARGE */
#ifndef SMAR_DEBUG
# define SMAR_DEBUG 1
#endif
#if SMAR_DEBUG
# include "sm/io.h"
uint smar_debug;
# define SMAR_DEBFP smioerr
# define SMAR_LEV_DPRINTF(lev, x) do \
{ \
if ((lev) < smar_debug) \
{ \
sm_io_fprintf x; \
sm_io_flush(SMAR_DEBFP); \
} \
} while (0)
# define SMAR_DPRINTF(x) sm_io_fprintf x
#else /* SMAR_DEBUG */
# define SMAR_DPRINTF(x)
# define SMAR_LEV_DPRINTF(lev, x)
#endif /* SMAR_DEBUG */
#if SM_HEAP_CHECK
extern SM_DEBUG_T SmHeapCheck;
# define HEAP_CHECK (SmHeapCheck > 0)
#else
# define HEAP_CHECK 0
#endif
#define SMAR_RHS_SEP_C ' ' /* seperate entries in the host list */
#define SMAR_RHS_PORT_C '^' /* separate port from protocol */
#define SMAR_RHS_PROT_C ':' /* separate protocol from host list */
#define SMAR_DEFAULT_TTL 3600
#ifndef SMAR_MAXRHS
# define SMAR_MAXRHS 1024
#endif
#define RHS_ERROR "error:"
#define RHS_ERROR_LEN 6
#define RHS_ERROR_4 "error:4"
#define RHS_ERROR_4_LEN 7
#define RHS_QUICK "quick:"
#define RHS_QUICK_LEN 6
#define RHS_DELAY "delay:"
#define RHS_DELAY_LEN 6
/* XXX use LEN(x) (sizeof(x) - 1) ??? */
/*
** Maximum number of SMAR clients; this should be dynamic!
** However, the value must not exceed the number of bits in smar_clt_used.
*/
#define SMAR_MAX_CLTS 32
/* Client context type for SMAR */
struct smar_clt_ctx_S
{
sm_magic_T sm_magic;
#if 0
pthread_mutex_t smac_mutex;
#endif
int smac_status; /* see below, SMAR_ST_* */
/* info about connections? */
uint32_t smac_bit; /* bit for smar_clt_used */
uint32_t smac_idx; /* index (MUST be unsigned) */
uint32_t smac_cl_flags; /* client flags */
smar_ctx_P smac_ar_ctx; /* pointer back to main ctx */
rcbcom_ctx_T smac_com_ctx; /* communication context */
};
/* SMAC status */
#define SMAC_ST_NONE 0x00 /* not yet OK */
#define SMAC_ST_INIT 0x01 /* initialized */
/* Main context type for SMAR */
struct smar_ctx_S
{
sm_magic_T sm_magic;
pthread_mutex_t smar_mutex;
smar_cnf_T smar_cnf;
sm_str_P smar_hostname;
uint smar_status; /* see below, SMAR_ST_* */
uint smar_flags; /* see below, SMAR_FL_* */
/* info about connections? */
sm_evthr_ctx_P smar_ev_ctx; /* event thread context */
#if SMAR_MAX_CLTS > 32
ERROR: _SMAR_MAX_CLTS > 32
value must not exceed number of bits in smar_clt_used
#endif
uint32_t smar_clt_used; /* bitmask for used elements */
smar_clt_ctx_P smar_clt_ctx[SMAR_MAX_CLTS]; /* communication tasks */
/* max number of concurrent requests from a client */
uint32_t smar_clt_reqs[SMAR_MAX_CLTS];
uint32_t smar_max_reqs;
uint32_t smar_max_thrds_s;
uint32_t smar_max_thrds_h;
sm_log_ctx_P smar_lctx;
#if SMAR_USE_DNS
uint smar_dns_ntsks;
ipv4_T smar_nameserveripv4s[SM_DNS_MAX_TSKS];
dns_mgr_ctx_P smar_dns_mgr_ctx;
#endif
sm_map_P smar_mt_map; /* "mailertable" (HACK) */
sm_maps_P smar_maps; /* map system context */
sm_map_P smar_aliases; /* alias map */
sm_map_P smar_access; /* access map */
sm_map_P smar_lum; /* map of local users */
sm_cstr_P smar_strmaptype;
uint smar_alias_lfl; /* alias lookup flags */
uint smar_lum_lfl; /* local user map lookup flags */
uint smar_mt_lfl; /* mailertable map lookup flags */
greyctx_P smar_greyctx;
#if SMAR_TEST
long smar_rand_err;
#endif
};
/* SMAR status */
#define SMAR_ST_NONE 0x00 /* not yet OK */
#define SMAR_ST_INIT 0x01 /* initialized */
#define SMAR_ST_CONF 0x02 /* configured */
#define SMAR_ST_START 0x04 /* started */
#define SMAR_ST_OK 0x10 /* initialized, running normal */
#define SMAR_ST_SLOW 0x20 /* slow down */
/* Notice: this must be ordered, see smar_is_stop() below */
#define SMAR_ST_SH_DOWN 0x80 /* shutting down */
#define SMAR_ST_STOPPED 0x81 /* stopped: almost terminated */
#define smar_is_stop(smar_ctx) ((smar_ctx)->smar_status >= SMAR_ST_SH_DOWN)
/* SMAR flags */
#define SMAR_FL_NONE 0x0000
#define SMAR_FL_HASACCESS 0x0001
#define SMAR_FL_HASDNSBL 0x0002
#define SMAR_FL_HASGREY 0x0004
#define SMAR_FL_HASALIAS 0x0008
#define SMAR_FL_ACCESSCOMPL 0x0010 /* complained about access */
#define SMAR_FL_DNSBLCOMPL 0x0020 /* complained about dnsbl */
#define SMAR_FL_GREYCOMPL 0x0040 /* complained about greylisting */
#define SMAR_FL_ALIASCOMPL 0x0080 /* complained about aliases */
#define SMAR_FL_REQACCESS 0x0100 /* requires access map */
#define SMAR_FL_REQALIAS 0x0800 /* requires aliases map */
/* complained about protected_rcpts misconfiguration for client_ip */
#define SMAR_FL_PROTIPCOMPL 0x1000
/* complained about protected_rcpts misconfiguration for sender */
#define SMAR_FL_PROTMAILCOMPL 0x2000
#define SMAR_SET_FLAG(smar_ctx, fl) (smar_ctx)->smar_flags |= (fl)
#define SMAR_CLR_FLAG(smar_ctx, fl) (smar_ctx)->smar_flags &= ~(fl)
#define SMAR_IS_FLAG(smar_ctx, fl) (((smar_ctx)->smar_flags & (fl)) != 0)
struct smar_dns_S
{
uint ardns_ttl; /* TTL from DNS */
ushort ardns_pref; /* preference from DNS */
sm_cstr_P ardns_name; /* name from DNS (RHS of MX RR) */
int ardns_n_A; /* number of A records */
/* XXX missing TTL for individual A records */
/* pointer to list of A records [0 to ardns_n_A-1] */
ipv4_T *ardns_A_rrs;
};
struct smar_rcpt_S
{
sm_magic_T sm_magic;
sm_str_P arr_pa; /* printable addr */
rcpt_id_T arr_id; /* rcpt id */
rcpt_idx_T arr_idx; /* (local) rcpt idx */
sm_str_P arr_owner_pa; /* owner: printable addr */
rcpt_idx_T arr_owner_idx; /* (local) owner idx */
short arr_port; /* port for all addresses, 0: use default */
sm_str_P arr_domain_pa;
sm_str_P arr_user_pa; /* user without +detail */
sm_str_P arr_detail_pa; /* detail */
uchar arr_delim; /* used delimiter */
uint32_t arr_flags; /* status of address resolving */
sm_ret_T arr_ret; /* result of address resolving */
uint arr_timeout; /* timeout */
uint32_t arr_rqflags; /* request flags */
uint32_t arr_da; /* DA */
/*
** Number of A queries sent (= Number of MX records).
** For each MX record one query for the A records is sent.
*/
int arr_A_qsent;
/* Number of responses received for A queries */
int arr_A_rrcvd;
/*
** Total number of A records (each A record query can return multiple
** A records).
*/
int arr_n_A;
/*
** array of results [0 to arr_A_qsent-1]; the array can be bigger,
** but only arr_A_qsent entries are used.
*/
smar_dns_T *arr_res; /* array of results */
ipv4_T arr_ipv4; /* single A record */
uint32_t arr_cnf_lfl;
sm_ret_T arr_maprescnf;
sm_str_P arr_rhs_conf;
smar_rcpts_P arr_rcpts; /* pointer back to recipient list */
TAILQ_ENTRY(smar_rcpt_S) arr_next;
};
/* SMAR RCPT flags (A4: asked for) */
#define SMARR_FL_NONE 0x00000000 /* not yet OK */
#define SMARR_FL_INIT 0x00000001 /* initialized */
#define SMARR_FL_A4MT 0x00000002 /* check in mailertable */
/* XXX this needs more states if RHS in mailertable can be a hostname... */
#define SMARR_FL_GOTMT 0x00000004 /* got mailertable IP */
#define SMARR_FL_NOMT 0x00000008 /* no mailertable entry */
#define SMARR_FL_A4MX 0x00000010 /* asked for MX records */
#define SMARR_FL_GOTMX 0x00000020 /* got MX records */
#define SMARR_FL_A4A 0x00000040 /* asked for A records */
#define SMARR_FL_GOTA 0x00000080 /* got A records */
#define SMARR_FL_TEMP 0x00000100 /* temporary error */
#define SMARR_FL_EXPD 0x00000200 /* alias expansion performed */
#define SMARR_FL_ALIAS 0x00000400 /* 1-1 alias expansion performed */
#define SMARR_FL_LU 0x00000800 /* is local user */
#define SMARR_FL_FREEIT 0x00001000 /* something failed, free smar_rcpt */
#define SMARR_FL_INRLST 0x00002000 /* smar_rcpt is in smar_rcpts rcpt list */
#define SMARR_FL_INHT 0x00004000 /* smar_rcpt is in smar_rcpts hash table */
#define SMARR_FL_ORCPT 0x00008000 /* smar_rcpt is smar_rcpts->arrs_rcpt */
/* smar_rcpt_expand() to take responsibility (add to list or free it) */
#define SMARR_FL_TAKEIT 0x00010000
#define SMARR_FL_ISALIAS 0x00020000 /* found in alias map */
#define SMARR_FL_C_MX 0x00100000 /* got a CNAME record for MX */
#define SMARR_FL_C_A 0x00200000 /* got a CNAME record for A */
/* XXX maybe use counters instead of flags? */
#define SMARR_FL_C_MX_L 0x00400000 /* CNAME loop for MX */
#define SMARR_FL_C_A_L 0x00800000 /* CNAME loop for A */
#define SMARR_FL_ISOWN 0x01000000 /* address is owner- alias */
#define SMARR_FL_INOWNLST 0x02000000 /* smar_rcpt is in smar_rcpts owner list */
#define SMARR_FL_ISVERP 0x04000000 /* address is verp- alias */
#define SMARR_FL_HASVERP 0x08000000 /* address has verp- alias */
#define SMARR_FL_HASDET 0x10000000 /* address has +detail */
#define SMARR_SET_FLAG(smar_rcpt, fl) (smar_rcpt)->arr_flags |= (fl)
#define SMARR_CLR_FLAG(smar_rcpt, fl) (smar_rcpt)->arr_flags &= ~(fl)
#define SMARR_IS_FLAG(smar_rcpt, fl) (((smar_rcpt)->arr_flags & (fl)) != 0)
#define SMARRQ_SET_FLAG(smar_rcpt, fl) (smar_rcpt)->arr_rqflags |= (fl)
#define SMARRQ_CLR_FLAG(smar_rcpt, fl) (smar_rcpt)->arr_rqflags &= ~(fl)
#define SMARRQ_IS_FLAG(smar_rcpt, fl) (((smar_rcpt)->arr_rqflags & (fl)) != 0)
/* return codes from SMAR modules that decode/handle requests */
#define SMAR_R_WAITQ SM_SUCCESS /* default: put back in waitq */
#define SMAR_R_ASYNC 1 /* do nothing, task has been put in waitq */
typedef TAILQ_HEAD(smar_rcptshd_S, smar_rcpt_S) smar_rcptshd_T, *smar_rcptshd_P;
/* callback function to return result */
typedef sm_ret_T (smar_rcpts_cb_F)(smar_rcpts_P, void *);
struct smar_rcpts_S
{
sm_magic_T sm_magic;
#if 0
/*
** It seems this mutex isn't needed because the callback function
** (which can be called asynchronously) is protected using
** smar_ctx->smar_mutex
*/
pthread_mutex_t arrs_mutex;
#endif /* 0 */
smar_rcpt_P arrs_rcpt; /* original recipient */
rcpt_id_T arrs_rcpt_id; /* original rcpt id */
uint32_t arrs_flags; /* status of address resolving */
sm_ret_T arrs_ret; /* result of address resolving */
rcpt_idx_T arrs_idx; /* running counter for recipients */
bht_P arrs_rcpts; /* hash table of recipients */
smar_rcptshd_T arrs_rcpthd; /* list of recipients */
smar_rcptshd_T arrs_ownerhd; /* list of owner addresses */
uint arrs_ht_n; /* number of entries (in hash table) */
uint arrs_lst_n; /* number of entries (in list) */
rcpt_idx_T arrs_owners_n; /* number of owner aliases */
uint arrs_resolved; /* resolved entries */
sm_rcbe_P arrs_rcbe; /* RCB to write back result */
smar_ctx_P arrs_smar_ctx; /* pointer back to SMAR context */
smar_clt_ctx_P arrs_smar_clt_ctx; /* pointer back to client context */
sm_str_P arrs_pa; /* address to check against elements */
smar_addr_P arrs_addr;
smar_rcpts_cb_F *arrs_cbf; /* callback fct to invoke to return result */
void *arrs_cb_ctx; /* context for callback function */
};
#define SMARRS_FL_NONE 0x0000 /* not yet OK */
#define SMARRS_FL_ERCB 0x0001 /* writing to RCB failed, return an error */
#define SMARRS_FL_TEMP 0x0002 /* temporary error (ENOMEM), return error */
#define SMARRS_FL_FAIL 0x0004 /* last attempt to write result failed */
#define SMARRS_FL_INITRE 0x0008 /* initialized reply (RCB) */
#define SMARRS_FL_NOSEND 0x0010 /* do not send data */
#define SMARRS_FL_NOFREE 0x0020 /* do not free context */
#define SMARRS_FL_NOREC 0x0100 /* no recursion */
#define SMARRS_FL_NOADD 0x0200 /* do not add elements to hash table */
#define SMARRS_FL_COMP 0x0400 /* compare elements against address arrs_addr */
#define SMARRS_FL_FOUND 0x1000 /* found arrs_pa */
#define SMARRS_SET_FLAG(smar_rcpts, fl) (smar_rcpts)->arrs_flags |= (fl)
#define SMARRS_CLR_FLAG(smar_rcpts, fl) (smar_rcpts)->arrs_flags &= ~(fl)
#define SMARRS_IS_FLAG(smar_rcpts, fl) (((smar_rcpts)->arrs_flags & (fl)) != 0)
/* prototypes */
sm_ret_T smar_rcpts_new(smar_ctx_P _smar_ctx, smar_clt_ctx_P _smar_clt_ctx, smar_rcpts_P *_psmar_rcpts);
sm_ret_T smar_rcpts_free(smar_rcpts_P _smar_rcpts);
sm_ret_T smar_rcpt_expand(smar_rcpts_P _smar_rcpts, smar_rcpt_P _smar_rcpt, rcpt_idx_T _owner_idx, uint _flags, uint _level);
sm_ret_T smar_rcpts_t2l(smar_rcpts_P _smar_rcpts);
#define SM_IS_SMAR_RCPTS(smar_rcpts) SM_REQUIRE_ISA((smar_rcpts), SM_SMAR_RCPTS_MAGIC)
#define RCPTS_INIT(smar_rcpts) TAILQ_INIT(&((smar_rcpts)->arrs_rcpthd))
#define RCPTS_FIRST(smar_rcpts) TAILQ_FIRST(&((smar_rcpts)->arrs_rcpthd))
#define RCPTS_END(smar_rcpts) TAILQ_END(&((smar_rcpts)->arrs_rcpthd))
#define RCPTS_EMPTY(smar_rcpts) TAILQ_EMPTY(&((smar_rcpts)->arrs_rcpthd))
#define RCPTS_NEXT(smar_rcpt) TAILQ_NEXT(smar_rcpt, arr_next)
#define RCPTS_APP(smar_rcpts, smar_rcpt) TAILQ_INSERT_TAIL(&((smar_rcpts)->arrs_rcpthd), smar_rcpt, arr_next)
#define RCPTS_REMOVE(smar_rcpts, smar_rcpt) TAILQ_REMOVE(&((smar_rcpts)->arrs_rcpthd), smar_rcpt, arr_next)
#define OWNER_INIT(smar_rcpts) TAILQ_INIT(&((smar_rcpts)->arrs_ownerhd))
#define OWNER_FIRST(smar_rcpts) TAILQ_FIRST(&((smar_rcpts)->arrs_ownerhd))
#define OWNER_END(smar_rcpts) TAILQ_END(&((smar_rcpts)->arrs_ownerhd))
#define OWNER_EMPTY(smar_rcpts) TAILQ_EMPTY(&((smar_rcpts)->arrs_ownerhd))
#define OWNER_NEXT(smar_rcpt) TAILQ_NEXT(smar_rcpt, arr_next)
#define OWNER_APP(smar_rcpts, smar_rcpt) TAILQ_INSERT_TAIL(&((smar_rcpts)->arrs_ownerhd), smar_rcpt, arr_next)
#define OWNER_REMOVE(smar_rcpts, smar_rcpt) TAILQ_REMOVE(&((smar_rcpts)->arrs_ownerhd), smar_rcpt, arr_next)
/* DNS BL result */
struct smar_dnsblres_S
{
ipv4_T sdbr_ipv4; /* IPv4 address returned */
sm_ret_T sbdr_res; /* result of lookup */
ipv4_T *sdbr_ipv4s; /* IPv4 addresses returned */
uint sdbr_n; /* size of array */
};
/* result values (+ usual error code) */
#define SM_DNSBL_RES_INIT 0 /* initialized */
#define SM_DNSBL_RES_WAIT 1 /* waiting for result */
#define SM_DNSBL_RES_OK 2 /* result is OK (found A record) */
/*
** Recipient/Sender address context for map lookups or other checks.
**
** Should this allow for multiple tests per invocation?
** If yes, it would be necessary to send back multiple results.
** For now, it can be multiple tests, but there is only one result, i.e.,
** some order is fixed in the algorithm.
*/
struct smar_addr_S
{
sm_magic_T sm_magic;
sessta_id_T ara_taid; /* transaction id */
int ara_id; /* SMTPS id */
smar_clt_ctx_P ara_smar_clt_ctx; /* pointer back to client context */
sm_str_P ara_pa; /* printable addr */
sm_str_P ara_pa2; /* another printable addr */
sm_str_P ara_rhs; /* rewritten address/result of lookup */
sm_str_P ara_str; /* various purposes */
sm_str_P ara_tag; /* tag */
sm_str_P ara_detail;
sm_str_P ara_domain_pa; /* domain part */
uchar ara_delim; /* used delimiter */
rcpt_idx_T ara_rcpt_idx; /* only valid for recipients */
ipv4_T ara_ipv4; /* IPv4 address */
sm_str_P ara_ipv4_str; /* IPv4 address in ASCII */
sm_map_P ara_str_map; /* str map */
time_t ara_conn_time; /* connection time (greylisting) */
/*
** Parts of ara_pa2 (if necessary).
** Note: ara_rhs2 is used for protected_rcpts
** and in smar_rcpt_expand()
*/
sm_str_P ara_user2;
sm_str_P ara_detail2;
sm_str_P ara_domain_pa2;
sm_str_P ara_rhs2;
uchar ara_delim2; /* used delimiter */
/*
** Note: it might be useful to have a "cache" of these instead of
** of opening and closing them all the time.
*/
sm_a2821_T ara_a_rcpt;
/*
** What is the relation between lookup flags and lookup types?
** E.g., RCPT_LOCAL and RCPT_ACC: should that really be two
** lookup types? Why not RCPT with lookup flags: LOCAL, ACC?
** Should it be:
** type: This is an MAIL/RCPT address, a hostname, an IP address
** flags: perform the following tests:
** access map (tag determined by type)
** with "subflags": lookup exactly, lookup subdomains, ...
** check whether RCPT is local
** check whether MAIL is deliverable
** Note: the last two apply to exactly one type, so it doesn't
** seem to make much sense to have them as generic flags.
*/
uint32_t ara_lflags; /* lookup flags */
uint32_t ara_ltype; /* lookup type */
uint32_t ara_flags; /* various flags */
/* return value of map lookup function */
sm_ret_T ara_mapres;
/* status of lookup, e.g., (interpreted) RHS if lookup succeeded */
uint32_t ara_status;
uint32_t ara_rflags; /* result flags */
/* these values will be combined into one return value */
/* record type for status return, i.e., what does ara_status refer to */
uint32_t ara_which_status;
uint ara_rhstagoff; /* offset in RHS to return text */
/* 2nd return value of map lookup function, result in ara_rhs2 */
sm_ret_T ara_mapres2;
int ara_c_MX;
int ara_c_A;
int ara_c_dnsbl;
smar_rcpt_P ara_rcpt;
smar_rcpts_P ara_rcpts;
/* result of dns (reverse/recipient) lookup */
sm_ret_T ara_dns_ret;
sm_cstr_P ara_rvrs_hostname; /* name from DNS (reverse lookup) */
int ara_res_cnt; /* result counter */
smar_rvrs_P ara_rvrs;
smar_dnsblres_T ara_dnsblres[SM_MAX_DNSBL];
/*
** ara_mutex protects access to ara_dns_ret, ara_rvrs_hostname,
** ara_dnsblres, and ara_res_cnt. Currently it does not protect
** ara_flags even though some are modified in the callback/notify
** functions (see algorithm descriptions; it might be better to
** use "inline" signaling via the result variables because those
** are protected by the mutex).
** ara_cond is used to signal that those variables have valid content.
*/
pthread_mutex_t ara_mutex;
pthread_cond_t ara_cond;
sm_rcbe_P ara_rcbe; /* RCB to write back result */
sm_rpool_P ara_rpool; /* for this context? */
sm_ret_T ara_maprescnf;
sm_str_P ara_rhs_conf;
};
#define SM_IS_SMAR_ADDR(smar_addr) SM_REQUIRE_ISA((smar_addr), SM_SMAR_ADDR_MAGIC)
/*
** values for ara_dns_ret to signal between caller and callee
** Algorithm:
** Caller:
** status = init; * initialize status *
** ... * do something *
** lock * acquire mutex for v etc *
** if (status == init) { * is it still the initial value? *
** status = wait; * indicate that caller is waiting *
** while (status == wait)
** cond_wait
** }
** unlock
**
** Callee:
** lock * acquire mutex *
** notify = (status == wait); * is caller waiting? *
** v = v_new * set new value *
** status = sent; * result is available *
** if (notify)
** cond_signal * notify caller if it is waiting *
** unlock * done *
**
** Explanation: see docs
*/
/* SMAR addr flags */
#define SMARA_FL_NONE 0x00000000
#define SMARA_FL_HASMUT 0x00000001 /* mutex is initialized */
#define SMARA_FL_HASCOND 0x00000002 /* condition is initialized */
#define SMARA_FL_A4RVRS 0x00000004 /* asked for reverse lookup */
#define SMARA_FL_A4RCPT 0x00000008 /* asked for recipient lookup */
#define SMARA_FL_A4DNSBL 0x00000010 /* asked for DNS BL lookup */
#define SMARA_FL_GOTRVRS 0x00000020 /* got reverse DNS lookup result */
#define SMARA_FL_GOTDNSBL 0x00000040 /* got DNS BL result */
#define SMARA_FL_FAILDNS 0x00000080 /* failed to get DNS result */
#define SMARA_FL_GOTRCPT 0x00000100 /* got recipient DNS lookup result */
#define SMARA_FL_2ND 0x00000200 /* second lookup result is valid */
#define SMARA_FL_STOP 0x00000400 /* don't perform more lookups */
#define SMARA_FL_DIDLOOKUP 0x00000800 /* did lookup: check result */
#define SMARA_FL_RFC2821 0x00001000 /* RFC 2821 address */
#define SMARA_FL_GOTCERTISS 0x00002000 /* checked cert issuer */
#define SMARA_FL_GOTCERTSUB 0x00004000 /* checked cert subject */
#define SMARA_FL_GOTRCPTPROT 0x00008000 /* checked protected rcpt */
#define SMARA_FL_RP_ANALYSE 0x00010000
/* need to "analyse" protected rcpt lookup result */
#define SMARA_FL_INIT 0x00020000 /* all data initialized */
#define SMARA_FL_GOTGREY 0x00040000 /* greylisting check done */
#define SMARA_FL_GOTRVRSA 0x00080000 /* got reverse lookup result */
#define SMARA_FL_GOTRVRSN 0x00100000 /* resolved hostname checked */
#define SMARA_FL_RCVDIPV4 0x00200000 /* ara_ipv4 is valid */
#define SMARA_FL_PA2EMPTY 0x00400000 /* ara_pa2 is <> */
#define SMARA_FL_GOT2821ACC 0x00800000 /*did RFC2821 address access map lookup*/
#define SMARA_FL_GOTIPV4ACC 0x01000000 /* did IPv4 access map lookup */
/* flags for algorithm described above (AF: Asynchronous Function) */
#define SMARA_FL_AFWAIT 0x02000000 /* status==wait */
#define SMARA_FL_GOTSSSECONF 0x08000000 /* got smtps session conf */
#define SMARA_SET_FLAG(smar_addr, fl) (smar_addr)->ara_flags |= (fl)
#define SMARA_CLR_FLAG(smar_addr, fl) (smar_addr)->ara_flags &= ~(fl)
#define SMARA_IS_FLAG(smar_addr, fl) (((smar_addr)->ara_flags & (fl)) != 0)
#define SMARA_SET_LFLAG(smar_addr, fl) (smar_addr)->ara_lflags |= (fl)
#define SMARA_CLR_LFLAG(smar_addr, fl) (smar_addr)->ara_lflags &= ~(fl)
#define SMARA_IS_LFLAG(smar_addr, fl) (((smar_addr)->ara_lflags & (fl)) != 0)
/* see sm/smar.h: SMAR_R_* */
#define SMAR_SET_RFL(smar_addr, flags) (smar_addr)->ara_rflags |= (flags)
#define SMAR_CLR_RFL(smar_addr, flags) (smar_addr)->ara_rflags &= ~(flags)
#define SMAR_IS_RFL(smar_addr, flags) (((smar_addr)->ara_rflags & (flags)) != 0)
/* assertions */
#define SM_IS_SMAR_CTX(smar_ctx) SM_REQUIRE_ISA((smar_ctx), SM_SMAR_CTX_MAGIC)
#define SM_IS_SMAR_CLT_CTX(smac_ctx) SM_REQUIRE_ISA((smac_ctx), SM_SMAC_CTX_MAGIC)
#define SM_IS_SMAR_RCPT(smar_rcpt) SM_REQUIRE_ISA((smar_rcpt), SM_SMAR_RCPT_MAGIC)
/* prototypes */
sm_ret_T smar_init0(smar_ctx_P _smar_ctx);
sm_ret_T smar_init1(smar_ctx_P _smar_ctx);
sm_ret_T smar_init_map_lfl(smar_ctx_P _smar_ctx, uint _lfl_conf, uint *_plflags);
sm_ret_T smar_rdcf(smar_ctx_P _smar_ctx, int _argc, char *_argv[]);
sm_ret_T smar_read_cnf(smar_ctx_P _smar_ctx, const char *_fn, sm_conf_T **_psmc);
sm_ret_T smar_mt_init(smar_ctx_P _smar_ctx);
sm_ret_T smar_start(smar_ctx_P _smar_ctx);
sm_ret_T smar_stop(smar_ctx_P _smar_ctx);
sm_ret_T smar_clt_new(smar_ctx_P _smar_ctx, smar_clt_ctx_P *_psmar_clt_ctx);
sm_ret_T smar_clt_free(smar_clt_ctx_P _smar_clt_ctx);
sm_ret_T smar_li(sm_evthr_task_P _tsk);
sm_ret_T smar_clt(sm_evthr_task_P _tsk);
sm_ret_T smar_rcpt_rslv(smar_ctx_P _smar_ctx, smar_rcpts_P _smar_rcpts);
sm_ret_T smar_rcpt_new(smar_rcpt_P *_psmar_rcpt);
sm_ret_T smar_rcpt_free(smar_rcpt_P _smar_rcpt, smar_rcpts_P _smar_rcpts);
sm_ret_T smar_addr_new(smar_clt_ctx_P _smar_clt_ctx, smar_addr_P *_psmar_addr);
sm_ret_T smar_addr_free(smar_addr_P _smar_addr);
sm_ret_T smar_addr_check(smar_ctx_P _smar_ctx, smar_addr_P _smar_addr);
sm_ret_T smar_addr_chk(smar_ctx_P _smar_ctx, smar_addr_P _smar_addr);
sm_ret_T smar_addr_lu(smar_ctx_P _smar_ctx, sm_str_P _user, uchar _delim, sm_str_P _detail, sm_str_P _domain, sm_str_P _rhs, uint32_t *_pstatus);
sm_ret_T smar_addr_re(smar_addr_P _smar_addr, uint _offset);
#define SM_CONST_LEN(str) (sizeof(str) - 1)
#define CLT_A_TAG "cltaddr:"
#define CLT_A_TAG_LEN SM_CONST_LEN(CLT_A_TAG)
#define CLT_N_TAG "cltname:"
#define CLT_N_TAG_LEN SM_CONST_LEN(CLT_N_TAG)
#define MAIL_TAG "from:"
#define MAIL_TAG_LEN SM_CONST_LEN(MAIL_TAG)
#define RCPT_TAG "to:"
#define RCPT_TAG_LEN SM_CONST_LEN(RCPT_TAG)
#define CERT_ISSUER_TAG "certissuer:"
#define CERT_ISSUER_TAG_LEN SM_CONST_LEN(CERT_ISSUER_TAG)
#define CERT_SUBJECT_TAG "certsubject:"
#define CERT_SUBJECT_TAG_LEN SM_CONST_LEN(CERT_SUBJECT_TAG)
#define PROT_RCPT_TAG "protectedrcpt:"
#define PROT_RCPT_TAG_LEN SM_CONST_LEN(PROT_RCPT_TAG)
#define RHS_LIST_TAG "list:"
#define RHS_LIST_TAG_LEN SM_CONST_LEN(RHS_LIST_TAG)
#define EHLO_TAG "ehlo:"
#define SS_SE_CONF_A_TAG "smtps_session_conf:"
#define SC_SE_CONF_TAG "smtpc_session_conf:"
#define SC_RCPT_CONF_TAG "smtpc_rcpt_conf:"
sm_ret_T smar_map2acc(sm_ret_T _rv);
sm_ret_T smar_access_re(smar_addr_P _smar_addr, uint32_t _which_status, uint _off);
sm_ret_T smar_access_check(smar_ctx_P _smar_ctx, smar_addr_P _smar_addr);
sm_ret_T smar_access_chk(smar_ctx_P _smar_ctx, smar_addr_P _smar_addr);
sm_ret_T smar_prot_chk(smar_ctx_P _smar_ctx, smar_addr_P _smar_addr);
sm_ret_T smar_prot_rhs(smar_ctx_P _smar_ctx, smar_addr_P _smar_addr);
/* should mailertable use the "full" address for lookups? */
#define SMAR_MT_FULL_LOOKUP(smar_ctx) (SMMAP_LFL_MT != (smar_ctx)->smar_mt_lfl)
#endif /* SMAR_H */
syntax highlighted by Code2HTML, v. 0.9.1