/* * Copyright (c) 2002-2005 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_start.c,v 1.51 2007/06/18 04:42:31 ca Exp $") #include "sm/error.h" #include "sm/assert.h" #include "sm/map.h" #include "smar.h" #include "sm/unixsock.h" #include "sm/signal.h" #include "sm/misc.h" #include "log.h" /* ** SMAR_STLI -- start SMAR listeners ** ** Parameters: ** smar_ctx -- SMAR context ** ** Returns: ** usual sm_error code ** ** Question: should we store "task" in smar_ctx? */ static sm_ret_T smar_stli(smar_ctx_P smar_ctx) { int lfd, r; sm_ret_T ret; sm_evthr_task_P task; SM_IS_SMAR_CTX(smar_ctx); /* start listen connections */ /* these should be in smar_ctx after the configuration has been read */ /* QMGR */ (void) unlink(smar_ctx->smar_cnf.smar_cnf_sock_abs); lfd = unix_server_listen(smar_ctx->smar_cnf.smar_cnf_sock_abs, 10); if (!is_valid_fd(lfd)) { ret = sm_error_perm(SM_EM_AR, errno); sm_log_write(smar_ctx->smar_lctx, AR_LCAT_INIT, AR_LMOD_COMM, SM_LOG_ERROR, 1, "sev=ERROR, func=smar_start, socket=%.256s, server_listen=%m", smar_ctx->smar_cnf.smar_cnf_sock_abs, ret); goto error; } r = chmod(smar_ctx->smar_cnf.smar_cnf_sock_abs, 0660); if (r < 0 && errno != ENOENT) { ret = sm_error_perm(SM_EM_AR, errno); sm_log_write(smar_ctx->smar_lctx, AR_LCAT_INIT, AR_LMOD_COMM, SM_LOG_ERROR, 1, "sev=ERROR, func=smar_stli, socket=%.256s, chmod=%m", smar_ctx->smar_cnf.smar_cnf_sock_abs, ret); goto error; } #if 0 smar_ctx->smar_sslfd = lfd; #endif /* 0 */ ret = evthr_task_new(smar_ctx->smar_ev_ctx, &task, EVTHR_EV_LI, lfd, NULL, smar_li, (void *) smar_ctx); if (sm_is_err(ret)) goto error; return SM_SUCCESS; error: if (is_valid_fd(lfd)) close(lfd); return ret; } #if SMAR_USE_DNS /* ** SMAR_DNS_START -- start DNS system for SMAR ** ** Parameters: ** smar_ctx -- SMAR context ** ** Returns: ** usual sm_error code */ static sm_ret_T smar_dns_start(smar_ctx_P smar_ctx) { sm_ret_T ret; uint u; dns_tsk_P dns_tsk; for (u = 0; u < smar_ctx->smar_dns_ntsks; u++) { dns_tsk = NULL; ret = dns_tsk_new(smar_ctx->smar_dns_mgr_ctx, smar_ctx->smar_cnf.smar_cnf_dns_flags, smar_ctx->smar_nameserveripv4s[u], &dns_tsk); if (sm_is_err(ret)) goto error; dns_tsk->dnstsk_maxtimeouts = smar_ctx->smar_cnf.smar_cnf_dns_max_tmos; } ret = dns_tsk_start(smar_ctx->smar_dns_mgr_ctx, smar_ctx->smar_ev_ctx); if (sm_is_err(ret)) goto error; return SM_SUCCESS; error: /* XXX How to clean up? */ if (smar_ctx->smar_dns_mgr_ctx != NULL) { dns_mgr_ctx_del(smar_ctx->smar_dns_mgr_ctx); smar_ctx->smar_dns_mgr_ctx = NULL; } return ret; } #endif /* SMAR_USE_DNS */ /* ** SMAR_USR1 -- task handler for SIGUSR1 ** reopen maps ** ** Parameters: ** tsk -- evthr task ** ** Returns: ** usual sm_error code */ static sm_ret_T smar_usr1(sm_evthr_task_P tsk) { sm_ret_T ret; smar_ctx_P smar_ctx; char stats[256]; SM_IS_EVTHR_TSK(tsk); smar_ctx = (smar_ctx_P) tsk->evthr_t_actx; SM_IS_SMAR_CTX(smar_ctx); if (smar_ctx->smar_ev_ctx != NULL) { time_T now; now = evthr_time(smar_ctx->smar_ev_ctx); sm_io_fprintf(smioerr, "["); (void) sm_timestamp(now, smioerr); sm_io_fprintf(smioerr, "] sev=INFO, where=smar_usr1\n"); } #if SM_HEAP_CHECK if (HEAP_CHECK) sm_heap_report(smioerr, 3); #endif /* SM_HEAP_CHECK */ stats[0] = '\0'; bht_stats(smar_ctx->smar_dns_mgr_ctx->dnsmgr_req_ht, stats, sizeof(stats)); sm_io_fprintf(smioerr, "dns_ht_size=%u\n" "dns_ht_used=%u\n" "dns_ht_limit=%u\n" "%s" , smar_ctx->smar_dns_mgr_ctx->dnsmgr_req_ht->bht_size , smar_ctx->smar_dns_mgr_ctx->dnsmgr_req_ht->bht_used , smar_ctx->smar_dns_mgr_ctx->dnsmgr_req_ht->bht_limit , stats ); smar_prt_cnf(&smar_ctx->smar_cnf, smioerr, true); if (smar_ctx->smar_aliases != NULL) { ret = sm_map_reopen(smar_ctx->smar_aliases, 0, SMPO_END); if (sm_is_err(ret)) { sm_io_fprintf(smioerr, "sev=ERROR, func=smar_usr1, map=aliases, reopen=%m\n" , ret); /* XXX close map first? */ smar_ctx->smar_aliases = NULL; } } if (smar_ctx->smar_access != NULL) { ret = sm_map_reopen(smar_ctx->smar_access, 0, SMPO_END); if (sm_is_err(ret)) { sm_io_fprintf(smioerr, "sev=ERROR, func=smar_usr1, map=access, reopen=%m\n" , ret); /* XXX close map first? */ smar_ctx->smar_access = NULL; } } if (smar_ctx->smar_mt_map != NULL) { ret = sm_map_reopen(smar_ctx->smar_mt_map, 0, SMPO_END); if (sm_is_err(ret)) { sm_io_fprintf(smioerr, "sev=ERROR, func=smar_usr1, map=mt, reopen=%m\n" , ret); } } return EVTHR_WAITQ; } /* ** SMAR_USR2 -- task handler for SIGUSR2 ** ** Parameters: ** tsk -- evthr task ** ** Returns: ** usual sm_error code */ static sm_ret_T smar_usr2(sm_evthr_task_P tsk) { smar_ctx_P smar_ctx; SM_IS_EVTHR_TSK(tsk); smar_ctx = (smar_ctx_P) tsk->evthr_t_actx; SM_IS_SMAR_CTX(smar_ctx); (void) sm_log_reopen(smar_ctx->smar_lctx); return EVTHR_WAITQ; } /* ** SMAR_START -- start SMAR ** ** Parameters: ** smar_ctx -- SMAR context ** ** Returns: ** usual sm_error code */ sm_ret_T smar_start(smar_ctx_P smar_ctx) { sm_ret_T ret; sm_evthr_task_P task; SM_IS_SMAR_CTX(smar_ctx); #if SMAR_USE_DNS ret = smar_dns_start(smar_ctx); if (sm_is_err(ret)) { sm_log_write(smar_ctx->smar_lctx, AR_LCAT_INIT, AR_LMOD_COMM, SM_LOG_ERROR, 1, "sev=ERROR, func=smar_start, smar_dns_start=%m", ret); goto error; } #endif /* SMAR_USE_DNS */ ret = evthr_task_new(smar_ctx->smar_ev_ctx, &task, EVTHR_EV_SG, SIGUSR1, NULL, smar_usr1, (void *) smar_ctx); if (sm_is_err(ret)) { sm_log_write(smar_ctx->smar_lctx, AR_LCAT_INIT, AR_LMOD_COMM, SM_LOG_ERROR, 1, "sev=ERROR, func=smar_start, smar_usr1=%m", ret); goto error; } ret = evthr_task_new(smar_ctx->smar_ev_ctx, &task, EVTHR_EV_SG, SIGUSR2, NULL, smar_usr2, (void *) smar_ctx); if (sm_is_err(ret)) { sm_log_write(smar_ctx->smar_lctx, AR_LCAT_INIT, AR_LMOD_COMM, SM_LOG_ERROR, 1, "sev=ERROR, func=smar_start, smar_usr2=%m", ret); goto error; } ret = smar_stli(smar_ctx); if (sm_is_err(ret)) { sm_log_write(smar_ctx->smar_lctx, AR_LCAT_INIT, AR_LMOD_COMM, SM_LOG_ERROR, 1, "sev=ERROR, func=smar_start, smar_stli=%m", ret); goto error; } smar_ctx->smar_status = SMAR_ST_START; return SM_SUCCESS; error: return ret; }