/** Iterate through raw view data and apply the view-specific respip * configuration; at this point we should have already seen all the views, * so if any of the views that respip data refer to does not exist, that's * an error. This additional iteration through view configuration data * is expected to not have significant performance impact (or rather, its * performance impact is not expected to be prohibitive in the configuration * processing phase). */ int respip_views_apply_cfg(struct views* vs, struct config_file* cfg, int* have_view_respip_cfg) { struct config_view* cv; struct view* v; int ret; for(cv = cfg->views; cv; cv = cv->next) { /** if no respip config for this view then there's * nothing to do; note that even though respip data must go * with respip action, we're checking for both here because * we want to catch the case where the respip action is missing * while the data is present */ if(!cv->respip_actions && !cv->respip_data) continue; if(!(v = views_find_view(vs, cv->name, 1))) { log_err("view '%s' unexpectedly missing", cv->name); return 0; } if(!v->respip_set) { v->respip_set = respip_set_create(); if(!v->respip_set) { log_err("out of memory"); lock_rw_unlock(&v->lock); return 0; } } ret = respip_set_apply_cfg(v->respip_set, NULL, 0, NULL, cv->respip_actions, cv->respip_data); lock_rw_unlock(&v->lock); if(!ret) { log_err("Error while applying respip configuration " "for view '%s'", cv->name); return 0; } *have_view_respip_cfg = (*have_view_respip_cfg || v->respip_set->ip_tree.count); cv->respip_actions = NULL; cv->respip_data = NULL; } return 1; }
void daemon_fork(struct daemon* daemon) { int have_view_respip_cfg = 0; log_assert(daemon); if(!(daemon->views = views_create())) fatal_exit("Could not create views: out of memory"); /* create individual views and their localzone/data trees */ if(!views_apply_cfg(daemon->views, daemon->cfg)) fatal_exit("Could not set up views"); if(!acl_list_apply_cfg(daemon->acl, daemon->cfg, daemon->views)) fatal_exit("Could not setup access control list"); if(daemon->cfg->dnscrypt) { #ifdef USE_DNSCRYPT daemon->dnscenv = dnsc_create(); if (!daemon->dnscenv) fatal_exit("dnsc_create failed"); dnsc_apply_cfg(daemon->dnscenv, daemon->cfg); #else fatal_exit("dnscrypt enabled in config but unbound was not built with " "dnscrypt support"); #endif } /* create global local_zones */ if(!(daemon->local_zones = local_zones_create())) fatal_exit("Could not create local zones: out of memory"); if(!local_zones_apply_cfg(daemon->local_zones, daemon->cfg)) fatal_exit("Could not set up local zones"); /* process raw response-ip configuration data */ if(!(daemon->respip_set = respip_set_create())) fatal_exit("Could not create response IP set"); if(!respip_global_apply_cfg(daemon->respip_set, daemon->cfg)) fatal_exit("Could not set up response IP set"); if(!respip_views_apply_cfg(daemon->views, daemon->cfg, &have_view_respip_cfg)) fatal_exit("Could not set up per-view response IP sets"); daemon->use_response_ip = !respip_set_is_empty(daemon->respip_set) || have_view_respip_cfg; /* read auth zonefiles */ if(!auth_zones_apply_cfg(daemon->env->auth_zones, daemon->cfg, 1)) fatal_exit("auth_zones could not be setup"); /* setup modules */ daemon_setup_modules(daemon); /* response-ip-xxx options don't work as expected without the respip * module. To avoid run-time operational surprise we reject such * configuration. */ if(daemon->use_response_ip && modstack_find(&daemon->mods, "respip") < 0) fatal_exit("response-ip options require respip module"); /* first create all the worker structures, so we can pass * them to the newly created threads. */ daemon_create_workers(daemon); #if defined(HAVE_EV_LOOP) || defined(HAVE_EV_DEFAULT_LOOP) /* in libev the first inited base gets signals */ if(!worker_init(daemon->workers[0], daemon->cfg, daemon->ports[0], 1)) fatal_exit("Could not initialize main thread"); #endif /* Now create the threads and init the workers. * By the way, this is thread #0 (the main thread). */ daemon_start_others(daemon); /* Special handling for the main thread. This is the thread * that handles signals and remote control. */ #if !(defined(HAVE_EV_LOOP) || defined(HAVE_EV_DEFAULT_LOOP)) /* libevent has the last inited base get signals (or any base) */ if(!worker_init(daemon->workers[0], daemon->cfg, daemon->ports[0], 1)) fatal_exit("Could not initialize main thread"); #endif signal_handling_playback(daemon->workers[0]); if (!shm_main_init(daemon)) log_warn("SHM has failed"); /* Start resolver service on main thread. */ #ifdef HAVE_SYSTEMD sd_notify(0, "READY=1"); #endif log_info("start of service (%s).", PACKAGE_STRING); worker_work(daemon->workers[0]); #ifdef HAVE_SYSTEMD sd_notify(0, "STOPPING=1"); #endif log_info("service stopped (%s).", PACKAGE_STRING); /* we exited! a signal happened! Stop other threads */ daemon_stop_others(daemon); /* Shutdown SHM */ shm_main_shutdown(daemon); daemon->need_to_exit = daemon->workers[0]->need_to_exit; }