/* * 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; }