void dnscore_init() { if(dnscore_init_done) { return; } dnscore_init_done = TRUE; dnscore_arch_checkup(); //random_init(time(NULL)); thread_pool_setup_random_ctx(); random_ctx rnd = thread_pool_get_random_ctx(); // random NEEDS to work. { u32 r0 = random_next(rnd); u32 r1 = random_next(rnd); u32 r2 = random_next(rnd); u32 r3 = random_next(rnd); if( ((r0 == 0) && (r1 == 0) && (r2 == 0) && (r3 == 0)) || ((r0 == r1) && (r1 == r2) && (r2 == r3)) ) { printf("panic: random generation fails. (%08x,%08x,%08x,%08x)\n", r0, r1, r2, r3); exit(-1); } } rfc_init(); format_class_init(); dnsformat_class_init(); stdstream_init(); logger_init(); dnscore_register_errors(); #if HAS_TSIG_SUPPORT tsig_register_algorithms(); #endif atexit(dnscore_finalize); dnscore_reset_timer(); }
static ya_result xfr_query_callback(void* data) { xfr_query_schedule_param *xqsp = (xfr_query_schedule_param*)data; ya_result return_value; ya_result scheduler_status; u32 refreshed_time = 0; u32 retried_time = time(NULL); /* * Zone refresh will be enabled (again) here. * * xfr_query_mark_zone_loaded * */ if(ISOK(xqsp->return_value)) { /* success but type == 0 => transfer done */ if(xqsp->type != 0) { log_info("slave: %{dnstype}: proceeding with transfer of %{dnsname}", &xqsp->type, xqsp->origin); } } else { log_err("slave: %{dnstype}: transfer of %{dnsname} failed: %r", &xqsp->type, xqsp->origin, xqsp->return_value); /* * Here (?) put the invalid zone placeholder if it is not there yet */ } switch(xqsp->type) { case TYPE_AXFR: { /* * Load the axfr */ if(ISOK(xqsp->return_value)) { axfr_query_axfr_load_param *aqalp; MALLOC_OR_DIE(axfr_query_axfr_load_param*, aqalp, sizeof(axfr_query_axfr_load_param), GENERIC_TAG); log_info("slave: opening AXFR for %{dnsname} %d", xqsp->origin, xqsp->loaded_serial); if(ISOK(return_value = zone_axfr_reader_open_with_serial(g_config->xfr_path, xqsp->origin, xqsp->loaded_serial, &aqalp->zr))) { /* * The system is ready to load an AXFR * A zone is already in place (by design), there may be an old zone that is now irrelevant. * At this point ... * * If the serial are not the same * MT the old zone must be destroyed (if it exist) * then * MT The new zone has to be created (loaded from the AXFR file) * Else * ST The new zone is actually the old zone, and the old zone is non-existent * EndIf * * then * * ST The new zone and the placeholder zone have to be swapped, then the placeholder has to be destroyed * */ zdb_zone *zone = zdb_zone_find_from_dnsname((zdb*)xqsp->db, xqsp->origin, CLASS_IN); if(zone != NULL) { zdb_zone_truncate_invalidate(zone); } /** * schedule the axfr load */ aqalp->old_zone = NULL; /* old zone */ aqalp->new_zone = NULL; aqalp->db = xqsp->db; aqalp->origin = dnsname_dup(xqsp->origin); scheduler_status = SCHEDULER_TASK_PROGRESS; thread_pool_schedule_job(xfr_query_axfr_load_thread, aqalp, NULL, "axfr load"); break; } } /** * @todo If the "old_zone" exists, then ... (destroy ? swap back ? expired ?) * */ /* * An issue occurred (AXFR transfer, load) */ log_err("slave: unable to load the axfr (retry set in %d seconds)", g_config->axfr_retry_delay); alarm_event_node *event = alarm_event_alloc(); event->epoch = time(NULL) + g_config->axfr_retry_delay; if(g_config->axfr_retry_jitter > 0) { random_ctx rndctx = thread_pool_get_random_ctx(); u32 jitter = random_next(rndctx) % g_config->axfr_retry_jitter; event->epoch += jitter; } event->function = scheduler_axfr_query_alarm; event->args = xqsp; event->key = ALARM_KEY_ZONE_AXFR_QUERY; event->flags = ALARM_DUP_NOP; event->text = "scheduler_axfr_query_alarm"; zdb *db = (zdb*)xqsp->db; alarm_set(db->alarm_handle, event); /* DO NOT FREE xqsp, SO DO NOT BREAK : return now */ return SCHEDULER_TASK_FINISHED; } case TYPE_IXFR: { /** * Load the ixfr (single thread, zone locked) */ scheduler_status = SCHEDULER_TASK_FINISHED; if(ISOK(xqsp->return_value)) { zdb_zone *dbzone = zdb_zone_find_from_dnsname((zdb*)xqsp->db, xqsp->origin, CLASS_IN); if(dbzone == NULL) { log_err("slave: zone %{dnsname} journal has vanished", xqsp->origin); break; } log_info("slave: opening journal for '%{dnsname}'", xqsp->origin); zdb_zone_lock(dbzone, ZDB_ZONE_MUTEX_XFR); if(ISOK(return_value = zdb_icmtl_replay(dbzone, g_config->xfr_path, xqsp->serial_start_offset, xqsp->loaded_serial, ZDB_ICMTL_REPLAY_SERIAL_OFFSET|ZDB_ICMTL_REPLAY_SERIAL_LIMIT))) { log_info("slave: replayed %d records changes", return_value); dbzone->apex->flags &= ~ZDB_RR_LABEL_INVALID_ZONE; refreshed_time = time(NULL); } else { log_err("slave: replay error: %r this is bad: invalidate the zone and ask for an AXFR", return_value); /** @todo INVALIDATE AND AXFR */ } /** @todo invalitate if retried_time > expired_time */ zdb_zone_unlock(dbzone, ZDB_ZONE_MUTEX_XFR); } log_info("slave: journal transfer done"); xfr_query_mark_zone_loaded((zdb*)g_config->database, xqsp->origin, refreshed_time, retried_time); scheduler_status = SCHEDULER_TASK_FINISHED; break; } default: { refreshed_time = time(NULL); log_info("slave: transfer done"); xfr_query_mark_zone_loaded((zdb*)g_config->database, xqsp->origin, refreshed_time, retried_time); scheduler_status = SCHEDULER_TASK_FINISHED; break; } } /* switch return_value */