/*
* 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.
*/
#include "sm/generic.h"
SM_RCSID("@(#)$Id: smar_init.c,v 1.79 2007/11/05 05:50:13 ca Exp $")
#include "sm/error.h"
#include "sm/assert.h"
#include "sm/memops.h"
#include "sm/misc.h"
#include "smar.h"
#include "sm/evthr.h"
#include "sm/maps.h"
#include "sm/map.h"
#include "sm/bdb.h"
#include "sm/hostname.h"
#include "sm/qmgrcomm.h"
#include "sm/smardef.h"
#include "sm/confsetpath.h"
#define SMAR_LOG_DEFINES 1
#include "log.h"
/*
* XREF: See also t-init-0.c: t_smar_0_init() if you change something here!
*/
/*
** SMAR_INIT0 -- initialize SMAR (before reading configuration)
**
** Parameters:
** smar_ctx -- SMAR context
**
** Returns:
** usual sm_error code
*/
sm_ret_T
smar_init0(smar_ctx_P smar_ctx)
{
int r;
sm_ret_T ret;
#if SMAR_USE_DNS
dns_mgr_ctx_P dns_mgr_ctx;
#endif
/* should we allocate the context here? */
SM_REQUIRE(smar_ctx != NULL);
/* clear out data */
sm_memzero(smar_ctx, sizeof(*smar_ctx));
/*
* needs to be set here because it's checked in smar_stop()
* which can be invoked rather "directly" on error.
*/
smar_ctx->sm_magic = SM_SMAR_CTX_MAGIC;
/* set default values */
smar_ctx->smar_cnf.smar_cnf_loglevel = SM_LOG_LEVEL;
smar_ctx->smar_cnf.smar_cnf_addr_delim = SM_ADDR_DELIM;
smar_ctx->smar_cnf.smar_cnf_minthr = SMAR_CNF_MINTHR;
smar_ctx->smar_cnf.smar_cnf_maxthr = SMAR_CNF_MAXTHR;
smar_ctx->smar_cnf.smar_cnf_maxfd = SMAR_CNF_MAXFD;
smar_ctx->smar_max_thrds_s = SMAR_CNF_MAXTHR;
smar_ctx->smar_max_thrds_h = SMAR_CNF_MAXTHR * 2;
smar_ctx->smar_cnf.smar_cnf_alias_fl = SMARCNF_FL_MAP_LP
|SMARCNF_FL_MAP_DETPLUS
|SMARCNF_FL_MAP_DETSTAR
|SMARCNF_FL_MAP_STAR
|SMARCNF_FL_MAP_FULL
;
smar_ctx->smar_alias_lfl = SMMAP_LFL_ALIAS;
smar_ctx->smar_cnf.smar_cnf_lum_fl = SMARCNF_FL_MAP_LP
|SMARCNF_FL_MAP_DETPLUS
|SMARCNF_FL_MAP_DETSTAR
|SMARCNF_FL_MAP_STAR
|SMARCNF_FL_MAP_DOTSUBDOM
|SMARCNF_FL_MAP_FULL
;
smar_ctx->smar_lum_lfl = SMMAP_LFL_ALIAS;
smar_ctx->smar_cnf.smar_cnf_mt_fl = SMARCNF_FL_MAP_DOMAIN
|SMARCNF_FL_MAP_DOTSUBDOM
|SMARCNF_FL_MAP_DOT
;
smar_ctx->smar_mt_lfl = SMMAP_LFL_MT;
smar_ctx->smar_cnf.smar_cnf_dns_flags = DNS_USE_RSLVCNF;
if (NULL == smar_ctx->smar_hostname) {
ret = sm_myhostname(&smar_ctx->smar_hostname);
if (sm_is_err(ret)) {
sm_io_fprintf(smioerr,
"sev=ERROR, func=smar_init, sm_myhostname=%m\n"
, ret);
goto error;
}
}
ret = sm_bdbversionok();
if (sm_is_err(ret)) goto error;
smar_ctx->smar_cnf.smar_cnf_sock = smarsock;
ret = sm_maps_init(&smar_ctx->smar_maps);
if (NULL == smar_ctx->smar_maps) {
ret = sm_error_temp(SM_EM_AR, ENOMEM);
goto error;
}
ret = sm_maps_create(smar_ctx->smar_maps);
if (sm_is_err(ret)) goto error;
#if SMAR_USE_DNS
dns_mgr_ctx = NULL;
ret = dns_rslv_new(41);
if (sm_is_err(ret)) goto error;
ret = dns_mgr_ctx_new(0, DNS_TIMEOUT, DNS_MGR_HTSIZE, DNS_MGR_HTMAX,
&dns_mgr_ctx);
if (sm_is_err(ret)) goto error;
dns_mgr_ctx->dnsmgr_lctx = smar_ctx->smar_lctx;
smar_ctx->smar_dns_mgr_ctx = dns_mgr_ctx;
smar_ctx->smar_nameserveripv4s[0] = (ipv4_T) htonl(LOCALHOST_IP);
smar_ctx->smar_dns_ntsks = 0;
#endif /* SMAR_USE_DNS */
ret = thr_init();
if (sm_is_err(ret)) goto err1;
r = pthread_mutex_init(&smar_ctx->smar_mutex, SM_PTHREAD_MUTEXATTR);
if (r != 0) {
ret = sm_error_perm(SM_EM_AR, r);
goto err2;
}
smar_ctx->smar_cnf.sm_magic = SM_SMAR_CNF_MAGIC;
#if 0
ret = sm_rcbcom_open(&smar_ctx->smar_qmgr_com);
if (sm_is_err(ret)) goto err3;
#endif /* 0 */
for (r = 0; r < SMAR_MAX_CLTS; r++)
{
ret = smar_clt_new(smar_ctx, &(smar_ctx->smar_clt_ctx[r]));
if (sm_is_err(ret)) goto err3;
}
ret = sm_log_create(NULL, &smar_ctx->smar_lctx, NULL);
if (sm_is_err(ret)) goto err4;
ret = sm_log_setfp_fd(smar_ctx->smar_lctx, smiolog, SMIOLOG_FILENO);
if (sm_is_err(ret)) goto err5;
ret = sm_log_setdebuglevel(smar_ctx->smar_lctx, smar_ctx->smar_cnf.smar_cnf_loglevel);
if (sm_is_err(ret)) goto err5;
#if SMAR_USE_DNS
/* HACK this shouldn't access the structure directly */
dns_mgr_ctx->dnsmgr_lctx = smar_ctx->smar_lctx;
#endif
smar_ctx->smar_status = SMAR_ST_INIT;
return SM_SUCCESS;
err5:
(void) sm_log_destroy(smar_ctx->smar_lctx);
err4:
err3:
(void) pthread_mutex_destroy(&smar_ctx->smar_mutex);
err2:
(void) thr_stop();
err1:
#if SMAR_USE_DNS
if (dns_mgr_ctx != NULL)
dns_mgr_ctx_del(dns_mgr_ctx);
smar_ctx->smar_dns_mgr_ctx = NULL;
#endif /* SMAR_USE_DNS */
error:
if (smar_ctx->smar_maps != NULL) {
(void) sm_maps_term(smar_ctx->smar_maps);
smar_ctx->smar_maps = NULL;
}
smar_ctx->sm_magic = SM_MAGIC_NULL;
smar_ctx->smar_cnf.sm_magic = SM_MAGIC_NULL;
return ret;
}
/*
** SMAR_INIT1 -- initialize SMAR (after reading configuration)
**
** Parameters:
** smar_ctx -- SMAR context
**
** Returns:
** usual sm_error code
*/
sm_ret_T
smar_init1(smar_ctx_P smar_ctx)
{
sm_ret_T ret;
sm_cstr_P mtype, mname;
const char *mpath;
char confdir[PATH_MAX];
SM_REQUIRE(smar_ctx != NULL);
mtype = mname = NULL;
ret = sm_log_setdebuglevel(smar_ctx->smar_lctx,
smar_ctx->smar_cnf.smar_cnf_loglevel);
ret = sm_dirname(smar_ctx->smar_cnf.smar_cnf_conffile, confdir,
sizeof(confdir));
if (sm_is_err(ret)) goto error;
if (smar_ctx->smar_cnf.smar_cnf_lum_name != NULL) {
ret = sm_mapname_findc(smar_ctx->smar_maps,
smar_ctx->smar_cnf.smar_cnf_lum_name,
&smar_ctx->smar_lum);
if (sm_is_err(ret)) {
sm_log_write(smar_ctx->smar_lctx,
AR_LCAT_RESOLVER, AR_LMOD_RESOLVER,
SM_LOG_ERR, 4,
"sev=ERROR, func=smar_init1, local_user_map_name=%.256s, open_local_user_map=%m"
, smar_ctx->smar_cnf.smar_cnf_lum_name, ret);
smar_ctx->smar_lum = NULL;
goto error;
}
}
ret = sm_gen_conf_path(smar_ctx->smar_cnf.smar_cnf_cdb_base,
smar_ctx->smar_cnf.smar_cnf_sock, smarsock,
&smar_ctx->smar_cnf.smar_cnf_sock_abs, NULL);
if (sm_is_err(ret))
goto error;
if (smar_ctx->smar_cnf.smar_cnf_mt_name != NULL) {
ret = sm_mapname_findc(smar_ctx->smar_maps,
smar_ctx->smar_cnf.smar_cnf_mt_name,
&smar_ctx->smar_mt_map);
if (sm_is_err(ret)) {
sm_log_write(smar_ctx->smar_lctx,
AR_LCAT_RESOLVER, AR_LMOD_RESOLVER,
SM_LOG_ERR, 4,
"sev=ERROR, func=smar_init1, mt_name=%.256s, open_map=%m"
, smar_ctx->smar_cnf.smar_cnf_mt_name, ret);
smar_ctx->smar_mt_map = NULL;
goto error;
}
}
else {
mtype = sm_cstr_scpyn0((const uchar *)SMAR_MT_TYPE, strlen(SMAR_MT_TYPE));
if (NULL == mtype) {
ret = sm_error_temp(SM_EM_AR, ENOMEM);
goto error;
}
mname = sm_cstr_scpyn0((const uchar *)SMAR_MT_NAME, strlen(SMAR_MT_NAME));
if (NULL == mname) {
ret = sm_error_temp(SM_EM_AR, ENOMEM);
goto error;
}
smar_ctx->smar_mt_map = NULL;
ret = sm_map_open(smar_ctx->smar_maps, mname, mtype, 0, NULL
, SMAP_MODE_RDONLY, &smar_ctx->smar_mt_map
, SMPO_HASH_NELEM, 1023, SMPO_MAX_ELEM, 0
, SMPO_INIT_CB, smar_mt_init, smar_ctx
, SMPO_END);
if (sm_is_err(ret)) {
sm_log_write(smar_ctx->smar_lctx,
AR_LCAT_INIT, AR_LMOD_CONFIG, SM_LOG_ERROR, 0,
"sev=ERROR, func=smar_init1, sm_map_open=%m, map=%C, type=%C"
, ret, mname, mtype);
smar_ctx->smar_mt_map = NULL;
goto error;
}
SM_CSTR_FREE(mname);
SM_CSTR_FREE(mtype);
}
/* aliases */
if (smar_ctx->smar_cnf.smar_cnf_alias_name != NULL) {
ret = sm_mapname_findc(smar_ctx->smar_maps,
smar_ctx->smar_cnf.smar_cnf_alias_name,
&smar_ctx->smar_aliases);
if (sm_is_err(ret)) {
sm_log_write(smar_ctx->smar_lctx,
AR_LCAT_RESOLVER, AR_LMOD_RESOLVER,
SM_LOG_ERR, 4,
"sev=ERROR, func=smar_init1, aliases_name=%.256s, find_map=%m"
, smar_ctx->smar_cnf.smar_cnf_alias_name, ret);
smar_ctx->smar_aliases = NULL;
goto error;
}
SMAR_SET_FLAG(smar_ctx, SMAR_FL_HASALIAS);
}
else {
mtype = sm_cstr_scpyn0((const uchar *)SMAR_ALIASES_TYPE, strlen(SMAR_ALIASES_TYPE));
if (NULL == mtype) {
ret = sm_error_temp(SM_EM_AR, ENOMEM);
goto error;
}
mname = sm_cstr_scpyn0((const uchar *)SMAR_ALIASES_NAME, strlen(SMAR_ALIASES_NAME));
if (NULL == mname) {
ret = sm_error_temp(SM_EM_AR, ENOMEM);
goto error;
}
SM_GEN_MAP_PATH(mpath, smar_ctx->smar_cnf.smar_cnf_alias_path,
confdir, smar_ctx->smar_cnf.smar_cnf_alias_fn,
SMAR_ALIASES_FILE, error);
smar_ctx->smar_aliases = NULL;
ret = sm_map_open(smar_ctx->smar_maps, mname, mtype, 0,
mpath, SMAP_MODE_RDONLY,
&smar_ctx->smar_aliases, SMPO_END);
SM_CSTR_FREE(mname);
SM_CSTR_FREE(mtype);
if (sm_is_err(ret)) {
bool required;
required = SMAR_IS_FLAG(smar_ctx, SMAR_FL_REQALIAS);
sm_log_write(smar_ctx->smar_lctx,
AR_LCAT_INIT, AR_LMOD_CONFIG,
required ? SM_LOG_ERROR : SM_LOG_WARN, 3,
"sev=%s, func=smar_init1, map=%s, type=%s, open=%m"
, required ? "ERROR" : "WARN"
, mpath, SMAR_ALIASES_TYPE, ret);
smar_ctx->smar_aliases = NULL;
if (required)
goto error;
ret = SM_SUCCESS;
}
else
SMAR_SET_FLAG(smar_ctx, SMAR_FL_HASALIAS);
}
/* access map */
if (smar_ctx->smar_cnf.smar_cnf_access_name != NULL) {
ret = sm_mapname_findc(smar_ctx->smar_maps,
smar_ctx->smar_cnf.smar_cnf_access_name,
&smar_ctx->smar_access);
if (sm_is_err(ret)) {
sm_log_write(smar_ctx->smar_lctx,
AR_LCAT_RESOLVER, AR_LMOD_RESOLVER,
SM_LOG_ERR, 4,
"sev=ERROR, func=smar_init1, access_name=%.256s, find_map=%m"
, smar_ctx->smar_cnf.smar_cnf_access_name, ret);
smar_ctx->smar_access = NULL;
goto error;
}
SMAR_SET_FLAG(smar_ctx, SMAR_FL_HASACCESS);
}
else {
mtype = sm_cstr_scpyn0((const uchar *)SMAR_ACCESS_TYPE, strlen(SMAR_ACCESS_TYPE));
if (NULL == mtype) {
ret = sm_error_temp(SM_EM_AR, ENOMEM);
goto error;
}
mname = sm_cstr_scpyn0((const uchar *)SMAR_ACCESS_NAME, strlen(SMAR_ACCESS_NAME));
if (NULL == mname) {
ret = sm_error_temp(SM_EM_AR, ENOMEM);
goto error;
}
SM_GEN_MAP_PATH(mpath, smar_ctx->smar_cnf.smar_cnf_access_path,
confdir, smar_ctx->smar_cnf.smar_cnf_access_fn,
SMAR_ACCESS_FILE, error);
smar_ctx->smar_access = NULL;
ret = sm_map_open(smar_ctx->smar_maps, mname, mtype, 0,
mpath, SMAP_MODE_RDONLY,
&smar_ctx->smar_access, SMPO_END);
SM_CSTR_FREE(mname);
SM_CSTR_FREE(mtype);
if (sm_is_err(ret)) {
smar_ctx->smar_access = NULL;
if (SMAR_IS_FLAG(smar_ctx, SMAR_FL_REQACCESS)) {
sm_log_write(smar_ctx->smar_lctx,
AR_LCAT_INIT, AR_LMOD_CONFIG,
SM_LOG_ERROR, 3,
"sev=ERROR, func=smar_init1, map=%s, type=%s, open=%m"
, mpath, SMAR_ACCESS_TYPE, ret);
goto error;
}
ret = SM_SUCCESS;
}
else
SMAR_SET_FLAG(smar_ctx, SMAR_FL_HASACCESS);
}
#define MAPC_STYPE "strmap"
mtype = sm_cstr_scpyn0((const uchar *)MAPC_STYPE, strlen(MAPC_STYPE));
if (NULL == mtype) {
ret = sm_error_temp(SM_EM_AR, ENOMEM);
goto error;
}
smar_ctx->smar_strmaptype = mtype;
mtype = NULL;
ret = smar_init_map_lfl(smar_ctx, smar_ctx->smar_cnf.smar_cnf_alias_fl,
&smar_ctx->smar_alias_lfl);
if (sm_is_err(ret)) goto error;
ret = smar_init_map_lfl(smar_ctx, smar_ctx->smar_cnf.smar_cnf_lum_fl,
&smar_ctx->smar_lum_lfl);
if (sm_is_err(ret)) goto error;
ret = smar_init_map_lfl(smar_ctx, smar_ctx->smar_cnf.smar_cnf_mt_fl,
&smar_ctx->smar_mt_lfl);
if (sm_is_err(ret)) goto error;
#if SMAR_USE_DNS
smar_ctx->smar_dns_mgr_ctx->dnsmgr_retries =
smar_ctx->smar_cnf.smar_cnf_dns_retries;
#endif
/* initialize event threads system */
smar_ctx->smar_max_thrds_s = smar_ctx->smar_cnf.smar_cnf_maxthr;
smar_ctx->smar_max_thrds_h = smar_ctx->smar_max_thrds_s * 2;
if (smar_ctx->smar_max_thrds_s > smar_ctx->smar_max_thrds_h)
smar_ctx->smar_max_thrds_h = UINT_MAX;
ret = evthr_init(&smar_ctx->smar_ev_ctx,
smar_ctx->smar_cnf.smar_cnf_minthr,
smar_ctx->smar_max_thrds_s,
smar_ctx->smar_cnf.smar_cnf_maxfd);
if (sm_is_err(ret)) goto error;
ret = evthr_set_max_h(smar_ctx->smar_ev_ctx, smar_ctx->smar_max_thrds_h);
if (sm_is_err(ret)) goto error;
#if SMAR_DEBUG
evthr_set_dbglvl(smar_ctx->smar_ev_ctx, smar_debug);
#endif
if (smar_ctx->smar_greyctx != NULL) {
ret = sm_greyctl_open(smar_ctx->smar_greyctx, &smar_ctx->smar_cnf.smar_cnf_grey);
if (sm_is_err(ret)) {
sm_log_write(smar_ctx->smar_lctx,
AR_LCAT_RESOLVER, AR_LMOD_RESOLVER,
SM_LOG_ERR, 4,
"sev=ERROR, func=smar_init1, sm_greyctl_open=%m"
, ret);
goto error;
}
}
return ret;
error:
SM_CSTR_FREE(mname);
SM_CSTR_FREE(mtype);
return ret;
}
syntax highlighted by Code2HTML, v. 0.9.1