struct ub_ctx* ub_ctx_create(void) { struct ub_ctx* ctx = ub_ctx_create_nopipe(); if(!ctx) return NULL; if((ctx->qq_pipe = tube_create()) == NULL) { int e = errno; ub_randfree(ctx->seed_rnd); config_delete(ctx->env->cfg); modstack_desetup(&ctx->mods, ctx->env); edns_known_options_delete(ctx->env); free(ctx->env); free(ctx); errno = e; return NULL; } if((ctx->rr_pipe = tube_create()) == NULL) { int e = errno; tube_delete(ctx->qq_pipe); ub_randfree(ctx->seed_rnd); config_delete(ctx->env->cfg); modstack_desetup(&ctx->mods, ctx->env); edns_known_options_delete(ctx->env); free(ctx->env); free(ctx); errno = e; return NULL; } return ctx; }
void ub_ctx_delete(struct ub_ctx* ctx) { struct alloc_cache* a, *na; int do_stop = 1; if(!ctx) return; /* see if bg thread is created and if threads have been killed */ /* no locks, because those may be held by terminated threads */ /* for processes the read pipe is closed and we see that on read */ #ifdef HAVE_PTHREAD if(ctx->created_bg && ctx->dothread) { if(pthread_kill(ctx->bg_tid, 0) == ESRCH) { /* thread has been killed */ do_stop = 0; } } #endif /* HAVE_PTHREAD */ if(do_stop) ub_stop_bg(ctx); libworker_delete_event(ctx->event_worker); modstack_desetup(&ctx->mods, ctx->env); a = ctx->alloc_list; while(a) { na = a->super; a->super = &ctx->superalloc; alloc_clear(a); free(a); a = na; } local_zones_delete(ctx->local_zones); lock_basic_destroy(&ctx->qqpipe_lock); lock_basic_destroy(&ctx->rrpipe_lock); lock_basic_destroy(&ctx->cfglock); tube_delete(ctx->qq_pipe); tube_delete(ctx->rr_pipe); if(ctx->env) { slabhash_delete(ctx->env->msg_cache); rrset_cache_delete(ctx->env->rrset_cache); infra_delete(ctx->env->infra_cache); config_delete(ctx->env->cfg); edns_known_options_delete(ctx->env); auth_zones_delete(ctx->env->auth_zones); free(ctx->env); } ub_randfree(ctx->seed_rnd); alloc_clear(&ctx->superalloc); traverse_postorder(&ctx->queries, delq, NULL); free(ctx); #ifdef USE_WINSOCK WSACleanup(); #endif }
/** create context functionality, but no pipes */ static struct ub_ctx* ub_ctx_create_nopipe(void) { struct ub_ctx* ctx; unsigned int seed; #ifdef USE_WINSOCK int r; WSADATA wsa_data; #endif checklock_start(); log_init(NULL, 0, NULL); /* logs to stderr */ log_ident_set("libunbound"); #ifdef USE_WINSOCK if((r = WSAStartup(MAKEWORD(2,2), &wsa_data)) != 0) { log_err("could not init winsock. WSAStartup: %s", wsa_strerror(r)); return NULL; } #endif verbosity = 0; /* errors only */ checklock_start(); ctx = (struct ub_ctx*)calloc(1, sizeof(*ctx)); if(!ctx) { errno = ENOMEM; return NULL; } alloc_init(&ctx->superalloc, NULL, 0); seed = (unsigned int)time(NULL) ^ (unsigned int)getpid(); if(!(ctx->seed_rnd = ub_initstate(seed, NULL))) { explicit_bzero(&seed, sizeof(seed)); ub_randfree(ctx->seed_rnd); free(ctx); errno = ENOMEM; return NULL; } explicit_bzero(&seed, sizeof(seed)); lock_basic_init(&ctx->qqpipe_lock); lock_basic_init(&ctx->rrpipe_lock); lock_basic_init(&ctx->cfglock); ctx->env = (struct module_env*)calloc(1, sizeof(*ctx->env)); if(!ctx->env) { ub_randfree(ctx->seed_rnd); free(ctx); errno = ENOMEM; return NULL; } ctx->env->cfg = config_create_forlib(); if(!ctx->env->cfg) { free(ctx->env); ub_randfree(ctx->seed_rnd); free(ctx); errno = ENOMEM; return NULL; } /* init edns_known_options */ if(!edns_known_options_init(ctx->env)) { config_delete(ctx->env->cfg); free(ctx->env); ub_randfree(ctx->seed_rnd); free(ctx); errno = ENOMEM; return NULL; } ctx->env->auth_zones = auth_zones_create(); if(!ctx->env->auth_zones) { edns_known_options_delete(ctx->env); config_delete(ctx->env->cfg); free(ctx->env); ub_randfree(ctx->seed_rnd); free(ctx); errno = ENOMEM; return NULL; } ctx->env->alloc = &ctx->superalloc; ctx->env->worker = NULL; ctx->env->need_to_validate = 0; modstack_init(&ctx->mods); rbtree_init(&ctx->queries, &context_query_cmp); return ctx; }
void daemon_delete(struct daemon* daemon) { size_t i; if(!daemon) return; modstack_desetup(&daemon->mods, daemon->env); daemon_remote_delete(daemon->rc); for(i = 0; i < daemon->num_ports; i++) listening_ports_free(daemon->ports[i]); free(daemon->ports); listening_ports_free(daemon->rc_ports); if(daemon->env) { slabhash_delete(daemon->env->msg_cache); rrset_cache_delete(daemon->env->rrset_cache); infra_delete(daemon->env->infra_cache); edns_known_options_delete(daemon->env); auth_zones_delete(daemon->env->auth_zones); } ub_randfree(daemon->rand); alloc_clear(&daemon->superalloc); acl_list_delete(daemon->acl); free(daemon->chroot); free(daemon->pidfile); free(daemon->env); #ifdef HAVE_SSL SSL_CTX_free((SSL_CTX*)daemon->listen_sslctx); SSL_CTX_free((SSL_CTX*)daemon->connect_sslctx); #endif free(daemon); #ifdef LEX_HAS_YYLEX_DESTROY /* lex cleanup */ ub_c_lex_destroy(); #endif /* libcrypto cleanup */ #ifdef HAVE_SSL # if defined(USE_GOST) && defined(HAVE_LDNS_KEY_EVP_UNLOAD_GOST) sldns_key_EVP_unload_gost(); # endif # if HAVE_DECL_SSL_COMP_GET_COMPRESSION_METHODS && HAVE_DECL_SK_SSL_COMP_POP_FREE # ifndef S_SPLINT_S # if OPENSSL_VERSION_NUMBER < 0x10100000 sk_SSL_COMP_pop_free(comp_meth, (void(*)())CRYPTO_free); # endif # endif # endif # ifdef HAVE_OPENSSL_CONFIG EVP_cleanup(); # if OPENSSL_VERSION_NUMBER < 0x10100000 ENGINE_cleanup(); # endif CONF_modules_free(); # endif # ifdef HAVE_CRYPTO_CLEANUP_ALL_EX_DATA CRYPTO_cleanup_all_ex_data(); /* safe, no more threads right now */ # endif # ifdef HAVE_ERR_FREE_STRINGS ERR_free_strings(); # endif # if OPENSSL_VERSION_NUMBER < 0x10100000 RAND_cleanup(); # endif # if defined(HAVE_SSL) && defined(OPENSSL_THREADS) && !defined(THREADS_DISABLED) ub_openssl_lock_delete(); # endif #ifndef HAVE_ARC4RANDOM _ARC4_LOCK_DESTROY(); #endif #elif defined(HAVE_NSS) NSS_Shutdown(); #endif /* HAVE_SSL or HAVE_NSS */ checklock_stop(); #ifdef USE_WINSOCK if(WSACleanup() != 0) { log_err("Could not WSACleanup: %s", wsa_strerror(WSAGetLastError())); } #endif }
struct daemon* daemon_init(void) { struct daemon* daemon = (struct daemon*)calloc(1, sizeof(struct daemon)); #ifdef USE_WINSOCK int r; WSADATA wsa_data; #endif if(!daemon) return NULL; #ifdef USE_WINSOCK r = WSAStartup(MAKEWORD(2,2), &wsa_data); if(r != 0) { fatal_exit("could not init winsock. WSAStartup: %s", wsa_strerror(r)); } #endif /* USE_WINSOCK */ signal_handling_record(); checklock_start(); #ifdef HAVE_SSL # ifdef HAVE_ERR_LOAD_CRYPTO_STRINGS ERR_load_crypto_strings(); # endif #if OPENSSL_VERSION_NUMBER < 0x10100000 || !defined(HAVE_OPENSSL_INIT_SSL) ERR_load_SSL_strings(); #endif # ifdef USE_GOST (void)sldns_key_EVP_load_gost_id(); # endif # if OPENSSL_VERSION_NUMBER < 0x10100000 || !defined(HAVE_OPENSSL_INIT_CRYPTO) OpenSSL_add_all_algorithms(); # else OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS | OPENSSL_INIT_ADD_ALL_DIGESTS | OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL); # endif # if HAVE_DECL_SSL_COMP_GET_COMPRESSION_METHODS /* grab the COMP method ptr because openssl leaks it */ comp_meth = (void*)SSL_COMP_get_compression_methods(); # endif # if OPENSSL_VERSION_NUMBER < 0x10100000 || !defined(HAVE_OPENSSL_INIT_SSL) (void)SSL_library_init(); # else (void)OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS, NULL); # endif # if defined(HAVE_SSL) && defined(OPENSSL_THREADS) && !defined(THREADS_DISABLED) if(!ub_openssl_lock_init()) fatal_exit("could not init openssl locks"); # endif #elif defined(HAVE_NSS) if(NSS_NoDB_Init(NULL) != SECSuccess) fatal_exit("could not init NSS"); #endif /* HAVE_SSL or HAVE_NSS */ #ifdef HAVE_TZSET /* init timezone info while we are not chrooted yet */ tzset(); #endif /* open /dev/random if needed */ ub_systemseed((unsigned)time(NULL)^(unsigned)getpid()^0xe67); daemon->need_to_exit = 0; modstack_init(&daemon->mods); if(!(daemon->env = (struct module_env*)calloc(1, sizeof(*daemon->env)))) { free(daemon); return NULL; } /* init edns_known_options */ if(!edns_known_options_init(daemon->env)) { free(daemon->env); free(daemon); return NULL; } alloc_init(&daemon->superalloc, NULL, 0); daemon->acl = acl_list_create(); if(!daemon->acl) { edns_known_options_delete(daemon->env); free(daemon->env); free(daemon); return NULL; } if(gettimeofday(&daemon->time_boot, NULL) < 0) log_err("gettimeofday: %s", strerror(errno)); daemon->time_last_stat = daemon->time_boot; if((daemon->env->auth_zones = auth_zones_create()) == 0) { acl_list_delete(daemon->acl); edns_known_options_delete(daemon->env); free(daemon->env); free(daemon); return NULL; } return daemon; }