/** 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 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))) { seed = 0; ub_randfree(ctx->seed_rnd); free(ctx); errno = ENOMEM; return NULL; } seed = 0; 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; } 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; }
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); 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); 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 }
/** delete libworker env */ static void libworker_delete_env(struct libworker* w) { if(w->env) { outside_network_quit_prepare(w->back); mesh_delete(w->env->mesh); context_release_alloc(w->ctx, w->env->alloc, !w->is_bg || w->is_bg_thread); sldns_buffer_free(w->env->scratch_buffer); regional_destroy(w->env->scratch); forwards_delete(w->env->fwds); hints_delete(w->env->hints); ub_randfree(w->env->rnd); free(w->env); } #ifdef HAVE_SSL SSL_CTX_free(w->sslctx); #endif outside_network_delete(w->back); }
/** delete libworker struct */ static void libworker_delete(struct libworker* w) { if(!w) return; if(w->env) { outside_network_quit_prepare(w->back); mesh_delete(w->env->mesh); context_release_alloc(w->ctx, w->env->alloc, !w->is_bg || w->is_bg_thread); ldns_buffer_free(w->env->scratch_buffer); regional_destroy(w->env->scratch); forwards_delete(w->env->fwds); ub_randfree(w->env->rnd); free(w->env); } SSL_CTX_free(w->sslctx); outside_network_delete(w->back); comm_base_delete(w->base); free(w); }
void ub_ctx_delete(struct ub_ctx* ctx) { struct alloc_cache* a, *na; if(!ctx) return; /* stop the bg thread */ lock_basic_lock(&ctx->cfglock); if(ctx->created_bg) { uint8_t* msg; uint32_t len; uint32_t cmd = UB_LIBCMD_QUIT; lock_basic_unlock(&ctx->cfglock); lock_basic_lock(&ctx->qqpipe_lock); (void)tube_write_msg(ctx->qq_pipe, (uint8_t*)&cmd, (uint32_t)sizeof(cmd), 0); lock_basic_unlock(&ctx->qqpipe_lock); lock_basic_lock(&ctx->rrpipe_lock); while(tube_read_msg(ctx->rr_pipe, &msg, &len, 0)) { /* discard all results except a quit confirm */ if(context_serial_getcmd(msg, len) == UB_LIBCMD_QUIT) { free(msg); break; } free(msg); } lock_basic_unlock(&ctx->rrpipe_lock); /* if bg worker is a thread, wait for it to exit, so that all * resources are really gone. */ lock_basic_lock(&ctx->cfglock); if(ctx->dothread) { lock_basic_unlock(&ctx->cfglock); ub_thread_join(ctx->bg_tid); } else { lock_basic_unlock(&ctx->cfglock); } } else { lock_basic_unlock(&ctx->cfglock); } 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); 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 }
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 }