static void engine_stop_drudgers(engine_type* engine) { #if HAVE_DRUDGERS size_t i = 0; #endif ods_log_assert(engine); ods_log_assert(engine->config); ods_log_debug("[%s] stop drudgers", engine_str); #if HAVE_DRUDGERS /* tell them to exit and wake up sleepyheads */ for (i=0; i < (size_t) engine->config->num_signer_threads; i++) { engine->drudgers[i]->need_to_exit = 1; } worker_notify_all(&engine->signq->q_lock, &engine->signq->q_threshold); /* head count */ for (i=0; i < (size_t) engine->config->num_signer_threads; i++) { ods_log_debug("[%s] join drudger %i", engine_str, i+1); ods_thread_join(engine->drudgers[i]->thread_id); engine->drudgers[i]->engine = NULL; } #endif return; }
/** * Make sure that no appointed jobs have failed. * */ static ods_status worker_check_jobs(worker_type* worker, task_type* task) { ods_log_assert(worker); ods_log_assert(task); lock_basic_lock(&worker->worker_lock); if (worker->jobs_failed) { ods_log_error("[%s[%i]] sign zone %s failed: %u RRsets failed", worker2str(worker->type), worker->thread_num, task_who2str(task), worker->jobs_failed); lock_basic_unlock(&worker->worker_lock); return ODS_STATUS_ERR; } else if (worker->jobs_completed != worker->jobs_appointed) { ods_log_error("[%s[%i]] sign zone %s failed: processed %u of %u " "RRsets", worker2str(worker->type), worker->thread_num, task_who2str(task), worker->jobs_completed, worker->jobs_appointed); lock_basic_unlock(&worker->worker_lock); return ODS_STATUS_ERR; } else if (worker->need_to_exit) { ods_log_debug("[%s[%i]] sign zone %s failed: worker needs to exit", worker2str(worker->type), worker->thread_num, task_who2str(task)); lock_basic_unlock(&worker->worker_lock); return ODS_STATUS_ERR; } else { ods_log_debug("[%s[%i]] sign zone %s ok: %u of %u RRsets " "succeeded", worker2str(worker->type), worker->thread_num, task_who2str(task), worker->jobs_completed, worker->jobs_appointed); ods_log_assert(worker->jobs_appointed == worker->jobs_completed); } lock_basic_unlock(&worker->worker_lock); return ODS_STATUS_OK; }
/** * (Create) and change ownership of directories * */ void ods_chown(const char* file, uid_t uid, gid_t gid, int getdir) { char* dir = NULL; if (!file) { ods_log_warning("[%s] no filename given for chown()", file_str); return; } if (!getdir) { ods_log_debug("[%s] create and chown %s with user=%ld group=%ld", file_str, file, (signed long) uid, (signed long) gid); if (chown(file, uid, gid) != 0) { ods_log_error("[%s] chown() %s failed: %s", file_str, file, strerror(errno)); } } else if ((dir = ods_dir_name(file)) != NULL) { ods_log_debug("[%s] create and chown %s with user=%ld group=%ld", file_str, dir, (signed long) uid, (signed long) gid); if (chown(dir, uid, gid) != 0) { ods_log_error("[%s] chown() %s failed: %s", file_str, dir, strerror(errno)); } free((void*) dir); } else { ods_log_warning("[%s] use of relative path: %s", file_str, file); } }
/** * Work. * */ void worker_start(worker_type* worker) { ods_log_assert(worker); while (worker->need_to_exit == 0) { ods_log_debug("[worker[%i]]: report for duty", worker->thread_num); /* When no task available this call blocks and waits for event. * Then it will return NULL; */ worker->task = schedule_pop_task(worker->engine->taskq); if (worker->task) { ods_log_debug("[worker[%i]] start working", worker->thread_num); worker_perform_task(worker); ods_log_debug("[worker[%i]] finished working", worker->thread_num); if (worker->task) { if (schedule_task(worker->engine->taskq, worker->task) != ODS_STATUS_OK) { ods_log_error("[worker[%i]] unable to schedule task", worker->thread_num); } worker->task = NULL; } } } }
/** * Process TSIG RR. * */ static ldns_pkt_rcode query_process_tsig(query_type* q) { if (!q || !q->tsig_rr) { return LDNS_RCODE_SERVFAIL; } if (q->tsig_rr->status == TSIG_ERROR) { return LDNS_RCODE_FORMERR; } if (q->tsig_rr->status == TSIG_OK) { if (!tsig_rr_lookup(q->tsig_rr)) { ods_log_debug("[%s] tsig unknown key/algorithm", query_str); return LDNS_RCODE_REFUSED; } buffer_set_limit(q->buffer, q->tsig_rr->position); buffer_pkt_set_arcount(q->buffer, buffer_pkt_arcount(q->buffer)-1); tsig_rr_prepare(q->tsig_rr); tsig_rr_update(q->tsig_rr, q->buffer, buffer_limit(q->buffer)); if (!tsig_rr_verify(q->tsig_rr)) { ods_log_debug("[%s] bad tsig signature", query_str); return LDNS_RCODE_NOTAUTH; } } return LDNS_RCODE_NOERROR; }
/** * IXFR. * */ static query_state query_process_ixfr(query_type* q) { uint16_t count = 0; ods_log_assert(q); ods_log_assert(q->buffer); ods_log_assert(buffer_pkt_qdcount(q->buffer) == 1); /* skip header and question section */ buffer_skip(q->buffer, BUFFER_PKT_HEADER_SIZE); if (!buffer_skip_rr(q->buffer, 1)) { ods_log_error("[%s] dropped packet: zone %s received bad ixfr " "request (bad question section)", query_str, q->zone->name); return QUERY_DISCARDED; } /* answer section is empty */ ods_log_assert(buffer_pkt_ancount(q->buffer) == 0); /* examine auth section */ q->startpos = buffer_position(q->buffer); count = buffer_pkt_nscount(q->buffer); if (count) { if (!buffer_skip_dname(q->buffer) || !query_parse_soa(q->buffer, &(q->serial))) { ods_log_error("[%s] dropped packet: zone %s received bad ixfr " "request (bad soa in auth section)", query_str, q->zone->name); return QUERY_DISCARDED; } ods_log_debug("[%s] found ixfr request zone %s serial=%u", query_str, q->zone->name, q->serial); return QUERY_PROCESSED; } ods_log_debug("[%s] ixfr request zone %s has no auth section", query_str, q->zone->name); q->serial = 0; return QUERY_PROCESSED; }
/** * Handle signals. * */ void * signal_handler(sig_atomic_t sig) { switch (sig) { case SIGHUP: ods_log_debug("[%s] SIGHUP received", signal_str); signal_hup_recvd++; if (signal_engine) { lock_basic_lock(&signal_engine->signal_lock); /* [LOCK] signal */ lock_basic_alarm(&signal_engine->signal_cond); /* [UNLOCK] signal */ lock_basic_unlock(&signal_engine->signal_lock); } break; case SIGINT: case SIGTERM: ods_log_debug("[%s] SIGTERM received", signal_str); signal_term_recvd++; if (signal_engine) { lock_basic_lock(&signal_engine->signal_lock); /* [LOCK] signal */ lock_basic_alarm(&signal_engine->signal_cond); /* [UNLOCK] signal */ lock_basic_unlock(&signal_engine->signal_lock); } break; default: break; } return NULL; }
/** * Start zone transfer handler. * */ void xfrhandler_start(xfrhandler_type* xfrhandler) { ods_log_assert(xfrhandler); ods_log_assert(xfrhandler->engine); ods_log_debug("[%s] start", xfrh_str); /* setup */ xfrhandler->start_time = time_now(); /* handlers */ netio_add_handler(xfrhandler->netio, &xfrhandler->dnshandler); /* service */ while (xfrhandler->need_to_exit == 0) { /* dispatch may block for a longer period, so current is gone */ xfrhandler->got_time = 0; ods_log_deeebug("[%s] netio dispatch", xfrh_str); if (netio_dispatch(xfrhandler->netio, NULL, NULL) == -1) { if (errno != EINTR) { ods_log_error("[%s] unable to dispatch netio: %s", xfrh_str, strerror(errno)); } } } /* shutdown */ ods_log_debug("[%s] shutdown", xfrh_str); }
/** * Work. * */ void worker_start(worker_type* worker) { time_t now, timeout = 1; task_type *task_that_was_worked_on; ods_log_assert(worker); while (worker->need_to_exit == 0) { ods_log_debug("[worker[%i]]: report for duty", worker->thread_num); lock_basic_lock(&worker->engine->taskq->schedule_lock); /* [LOCK] schedule */ worker->task = schedule_pop_task(worker->engine->taskq); if (worker->task) { /* [UNLOCK] schedule */ lock_basic_unlock(&worker->engine->taskq->schedule_lock); ods_log_debug("[worker[%i]] start working", worker->thread_num); worker->clock_in = time(NULL); worker_perform_task(worker); task_that_was_worked_on = worker->task; worker->task = NULL; ods_log_debug("[worker[%i]] finished working", worker->thread_num); if (task_that_was_worked_on) (void) lock_and_schedule_task(worker->engine->taskq, task_that_was_worked_on, 1); timeout = 1; } else { ods_log_debug("[worker[%i]] nothing to do", worker->thread_num); worker->task = schedule_get_first_task(worker->engine->taskq); /* [UNLOCK] schedule */ lock_basic_unlock(&worker->engine->taskq->schedule_lock); now = time_now(); if (worker->task && !worker->engine->taskq->loading) { timeout = (worker->task->when - now); } else { timeout *= 2; if (timeout > ODS_SE_MAX_BACKOFF) { timeout = ODS_SE_MAX_BACKOFF; } } worker->task = NULL; worker_sleep(worker, timeout); } } return; }
/** * Find TSIG RR. * */ static int query_find_tsig(query_type* q) { size_t saved_pos = 0; size_t rrcount = 0; size_t i = 0; ods_log_assert(q); ods_log_assert(q->tsig_rr); ods_log_assert(q->buffer); if (buffer_pkt_arcount(q->buffer) == 0) { q->tsig_rr->status = TSIG_NOT_PRESENT; return 1; } saved_pos = buffer_position(q->buffer); rrcount = buffer_pkt_qdcount(q->buffer) + buffer_pkt_ancount(q->buffer) + buffer_pkt_nscount(q->buffer); buffer_set_position(q->buffer, BUFFER_PKT_HEADER_SIZE); for (i=0; i < rrcount; i++) { if (!buffer_skip_rr(q->buffer, i < buffer_pkt_qdcount(q->buffer))) { buffer_set_position(q->buffer, saved_pos); return 0; } } rrcount = buffer_pkt_arcount(q->buffer); ods_log_assert(rrcount != 0); if (!tsig_rr_parse(q->tsig_rr, q->buffer)) { ods_log_debug("[%s] got bad tsig", query_str); return 0; } if (q->tsig_rr->status != TSIG_NOT_PRESENT) { --rrcount; } if (rrcount) { if (edns_rr_parse(q->edns_rr, q->buffer)) { --rrcount; } } if (rrcount && q->tsig_rr->status == TSIG_NOT_PRESENT) { /* see if tsig is after the edns record */ if (!tsig_rr_parse(q->tsig_rr, q->buffer)) { ods_log_debug("[%s] got bad tsig", query_str); return 0; } if (q->tsig_rr->status != TSIG_NOT_PRESENT) { --rrcount; } } if (rrcount > 0) { ods_log_debug("[%s] too many additional rrs", query_str); return 0; } buffer_set_position(q->buffer, saved_pos); return 1; }
/** * QUERY. * */ static query_state query_process_query(query_type* q, ldns_rr_type qtype, engine_type* engine) { dnsout_type* dnsout = NULL; if (!q || !q->zone) { return QUERY_DISCARDED; } ods_log_assert(q->zone->name); ods_log_debug("[%s] incoming query qtype=%s for zone %s", query_str, rrset_type2str(qtype), q->zone->name); /* sanity checks */ if (buffer_pkt_qdcount(q->buffer) != 1 || buffer_pkt_tc(q->buffer)) { buffer_pkt_set_flags(q->buffer, 0); return query_formerr(q); } if (buffer_pkt_ancount(q->buffer) != 0 || (qtype != LDNS_RR_TYPE_IXFR && buffer_pkt_nscount(q->buffer) != 0)) { buffer_pkt_set_flags(q->buffer, 0); return query_formerr(q); } /* acl */ if (!q->zone->adoutbound || q->zone->adoutbound->type != ADAPTER_DNS) { ods_log_error("[%s] zone %s is not configured to have output dns " "adapter", query_str, q->zone->name); return query_refused(q); } ods_log_assert(q->zone->adoutbound->config); dnsout = (dnsout_type*) q->zone->adoutbound->config; /* acl also in use for soa and other queries */ if (!acl_find(dnsout->provide_xfr, &q->addr, q->tsig_rr)) { return query_refused(q); } /* ixfr? */ if (qtype == LDNS_RR_TYPE_IXFR) { if (query_process_ixfr(q) != QUERY_PROCESSED) { buffer_pkt_set_flags(q->buffer, 0); return query_formerr(q); } query_prepare(q); ods_log_assert(q->zone->name); ods_log_debug("[%s] incoming ixfr request serial=%u for zone %s", query_str, q->serial, q->zone->name); return ixfr(q, engine); } query_prepare(q); /* axfr? */ if (qtype == LDNS_RR_TYPE_AXFR) { ods_log_assert(q->zone->name); ods_log_debug("[%s] incoming axfr request for zone %s", query_str, q->zone->name); return axfr(q, engine); } /* (soa) query */ return query_response(q, qtype); }
/** * Open a file. * */ FILE* ods_fopen(const char* file, const char* dir, const char* mode) { FILE* fd = NULL; size_t len_file = 0; size_t len_dir = 0; size_t len_total = 0; char* openf = NULL; ods_log_assert(mode); ods_log_deeebug("[%s] open file %s%s file=%s mode=%s", file_str, (dir?"dir=":""), (dir?dir:""), (file?file:"(null)"), ods_file_mode2str(mode)); if (dir) { len_dir= strlen(dir); } if (file) { len_file= strlen(file); } len_total = len_dir + len_file; if (len_total > 0) { openf = (char*) malloc(sizeof(char)*(len_total + 1)); if (!openf) { ods_log_error("[%s] unable to open file %s%s%s for %s: malloc() " "failed", file_str, (dir?dir:""), (dir?"/":""), (file?file:"(null)"), ods_file_mode2str(mode)); return NULL; } if (dir) { strncpy(openf, dir, len_dir); openf[len_dir] = '\0'; if (file) { strncat(openf, file, len_file); } } else if (file) { strncpy(openf, file, len_file); } openf[len_total] = '\0'; if (len_file) { fd = fopen(openf, mode); if (!fd) { ods_log_debug("[%s] unable to open file %s for %s: %s", file_str, openf[0]?openf:"(null)", ods_file_mode2str(mode), strerror(errno)); } else { file_count++; ods_log_debug("[%s] openfile %s count %u", file_str, openf[0]?openf:"(null)", file_count); } } free((void*) openf); } return fd; }
/** * Update zone list. * */ ods_status zonelist_update(zonelist_type* zl, const char* zlfile) { zonelist_type* new_zlist = NULL; allocator_type* tmp_alloc = NULL; time_t st_mtime = 0; ods_status status = ODS_STATUS_OK; char* datestamp = NULL; ods_log_debug("[%s] update zone list", zl_str); if (!zl|| !zl->zones || !zlfile) { return ODS_STATUS_ASSERT_ERR; } /* is the file updated? */ st_mtime = ods_file_lastmodified(zlfile); if (st_mtime <= zl->last_modified) { (void)time_datestamp(zl->last_modified, "%Y-%m-%d %T", &datestamp); ods_log_debug("[%s] zonelist file %s is unchanged since %s", zl_str, zlfile, datestamp?datestamp:"Unknown"); free((void*)datestamp); return ODS_STATUS_UNCHANGED; } /* create new zonelist */ tmp_alloc = allocator_create(malloc, free); if (!tmp_alloc) { return ODS_STATUS_MALLOC_ERR; } new_zlist = zonelist_create(tmp_alloc); if (!new_zlist) { ods_log_error("[%s] unable to update zonelist: zonelist_create() " "failed", zl_str); allocator_cleanup(tmp_alloc); return ODS_STATUS_ERR; } /* read zonelist */ status = zonelist_read(new_zlist, zlfile); if (status == ODS_STATUS_OK) { zl->just_removed = 0; zl->just_added = 0; zl->just_updated = 0; new_zlist->last_modified = st_mtime; zonelist_merge(zl, new_zlist); (void)time_datestamp(zl->last_modified, "%Y-%m-%d %T", &datestamp); ods_log_debug("[%s] file %s is modified since %s", zl_str, zlfile, datestamp?datestamp:"Unknown"); free((void*)datestamp); } else { ods_log_error("[%s] unable to update zonelist: read file %s failed " "(%s)", zl_str, zlfile, ods_status2str(status)); } zonelist_free(new_zlist); allocator_cleanup(tmp_alloc); return status; }
/** * Handle notify. * */ static void notify_handle_zone(netio_type* ATTR_UNUSED(netio), netio_handler_type* handler, netio_events_type event_types) { notify_type* notify = NULL; xfrhandler_type* xfrhandler = NULL; zone_type* zone = NULL; if (!handler) { return; } notify = (notify_type*) handler->user_data; ods_log_assert(notify); xfrhandler = (xfrhandler_type*) notify->xfrhandler; zone = (zone_type*) notify->zone; ods_log_assert(xfrhandler); ods_log_assert(zone); ods_log_assert(zone->name); ods_log_debug("[%s] handle notify for zone %s", notify_str, zone->name); if (notify->is_waiting) { ods_log_debug("[%s] already waiting, skipping notify for zone %s", notify_str, zone->name); ods_log_assert(notify->handler.fd == -1); return; } if (event_types & NETIO_EVENT_READ) { ods_log_debug("[%s] read notify ok for zone %s", notify_str, zone->name); ods_log_assert(notify->handler.fd != -1); if (notify_udp_read_packet(notify)) { if (notify_handle_reply(notify)) { notify_next(notify); } } } else if(event_types & NETIO_EVENT_TIMEOUT) { ods_log_debug("[%s] notify timeout for zone %s", notify_str, zone->name); /* timeout, try again */ } /* see if notify is still enabled */ if (notify->secondary) { ods_log_assert(notify->secondary->address); notify->retry++; if (notify->retry > NOTIFY_MAX_RETRY) { ods_log_verbose("[%s] notify max retry for zone %s, %s unreachable", notify_str, zone->name, notify->secondary->address); notify_next(notify); } else { notify_send(notify); } } return; }
/** * Update DNS configuration for zone. * */ static int dnsconfig_zone(engine_type* engine, zone_type* zone) { int numdns = 0; ods_log_assert(engine); ods_log_assert(engine->xfrhandler); ods_log_assert(engine->xfrhandler->netio); ods_log_assert(zone); ods_log_assert(zone->adinbound); ods_log_assert(zone->adoutbound); ods_log_assert(zone->name); if (zone->adinbound->type == ADAPTER_DNS) { /* zone transfer handler */ if (!zone->xfrd) { ods_log_debug("[%s] add transfer handler for zone %s", engine_str, zone->name); zone->xfrd = xfrd_create((void*) engine->xfrhandler, (void*) zone); ods_log_assert(zone->xfrd); netio_add_handler(engine->xfrhandler->netio, &zone->xfrd->handler); } else if (!zone->xfrd->serial_disk_acquired) { xfrd_set_timer_now(zone->xfrd); } numdns++; } else if (zone->xfrd) { netio_remove_handler(engine->xfrhandler->netio, &zone->xfrd->handler); xfrd_cleanup(zone->xfrd); zone->xfrd = NULL; } if (zone->adoutbound->type == ADAPTER_DNS) { /* notify handler */ if (!zone->notify) { ods_log_debug("[%s] add notify handler for zone %s", engine_str, zone->name); zone->notify = notify_create((void*) engine->xfrhandler, (void*) zone); ods_log_assert(zone->notify); netio_add_handler(engine->xfrhandler->netio, &zone->notify->handler); } numdns++; } else if (zone->notify) { netio_remove_handler(engine->xfrhandler->netio, &zone->notify->handler); notify_cleanup(zone->notify); zone->notify = NULL; } return numdns; }
static void engine_stop_dnshandler(engine_type* engine) { if (!engine || !engine->dnshandler || !engine->dnshandler->thread_id) { return; } ods_log_debug("[%s] stop dnshandler", engine_str); engine->dnshandler->need_to_exit = 1; dnshandler_signal(engine->dnshandler); ods_log_debug("[%s] join dnshandler", engine_str); ods_thread_join(engine->dnshandler->thread_id); engine->dnshandler->engine = NULL; }
/** * Enable notify. * */ void notify_enable(notify_type* notify, ldns_rr* soa) { xfrhandler_type* xfrhandler = NULL; zone_type* zone = NULL; dnsout_type* dnsout = NULL; if (!notify) { return; } xfrhandler = (xfrhandler_type*) notify->xfrhandler; ods_log_assert(xfrhandler); zone = (zone_type*) notify->zone; ods_log_assert(zone); ods_log_assert(zone->name); ods_log_assert(zone->adoutbound); ods_log_assert(zone->adoutbound->config); ods_log_assert(zone->adoutbound->type == ADAPTER_DNS); dnsout = (dnsout_type*) zone->adoutbound->config; if (!dnsout->do_notify) { ods_log_warning("[%s] zone %s has no notify acl", notify_str, zone->name); return; /* nothing to do */ } notify_update_soa(notify, soa); if (notify->is_waiting) { ods_log_debug("[%s] zone %s already on waiting list", notify_str, zone->name); return; } if (xfrhandler->notify_udp_num < NOTIFY_MAX_UDP) { notify_setup(notify); xfrhandler->notify_udp_num++; ods_log_debug("[%s] zone %s notify enabled", notify_str, zone->name); return; } /* put it in waiting list */ notify->secondary = dnsout->do_notify; notify->is_waiting = 1; notify->waiting_next = NULL; if (xfrhandler->notify_waiting_last) { xfrhandler->notify_waiting_last->waiting_next = notify; } else { xfrhandler->notify_waiting_first = notify; } xfrhandler->notify_waiting_last = notify; notify->handler.timeout = NULL; ods_log_debug("[%s] zone %s notify on waiting list", notify_str, zone->name); return; }
/** * Run engine, run!. * */ static void engine_run(engine_type* engine, int single_run) { if (!engine) { return; } engine_start_workers(engine); engine_start_drudgers(engine); lock_basic_lock(&engine->signal_lock); engine->signal = SIGNAL_RUN; lock_basic_unlock(&engine->signal_lock); while (!engine->need_to_exit && !engine->need_to_reload) { lock_basic_lock(&engine->signal_lock); engine->signal = signal_capture(engine->signal); switch (engine->signal) { case SIGNAL_RUN: ods_log_assert(1); break; case SIGNAL_RELOAD: engine->need_to_reload = 1; break; case SIGNAL_SHUTDOWN: engine->need_to_exit = 1; break; default: ods_log_warning("[%s] invalid signal %d captured, " "keep running", engine_str, signal); engine->signal = SIGNAL_RUN; break; } lock_basic_unlock(&engine->signal_lock); if (single_run) { engine->need_to_exit = engine_all_zones_processed(engine); } lock_basic_lock(&engine->signal_lock); if (engine->signal == SIGNAL_RUN && !single_run) { ods_log_debug("[%s] taking a break", engine_str); lock_basic_sleep(&engine->signal_cond, &engine->signal_lock, 3600); } lock_basic_unlock(&engine->signal_lock); } ods_log_debug("[%s] signer halted", engine_str); engine_stop_drudgers(engine); engine_stop_workers(engine); (void)lhsm_reopen(engine->config->cfg_filename); return; }
/** * Read and match a string from backup file. * */ int backup_read_check_str(FILE* in, const char* str) { char *p = backup_read_token(in); if (!p) { ods_log_debug("[%s] cannot read check string \'%s\'", backup_str, str); return 0; } if (ods_strcmp(p, str) != 0) { ods_log_debug("[%s] \'%s\' does not match \'%s\'", backup_str, p, str); return 0; } return 1; }
/** * Inspect head of queue and wakeup a worker now or set alarm. * Caller SHOULD hold schedule->schedule_lock. Failing to do so * could possibly cause a thread to miss the wakeup. */ static void set_alarm(schedule_type* schedule) { time_t now = time_now(); task_type *task = get_first_task(schedule); if (!task || task->when == -1) { ods_log_debug("[%s] no alarm set", schedule_str); } else if (task->when == 0 || task->when <= now) { ods_log_debug("[%s] signal now", schedule_str); pthread_cond_signal(&schedule->schedule_cond); } else { ods_log_debug("[%s] SIGALRM set", schedule_str); alarm(task->when - now); } }
/** * Create worker. * */ worker_type* worker_create(allocator_type* allocator, int num, worker_id type) { worker_type* worker; if (!allocator) { return NULL; } worker = (worker_type*) allocator_alloc(allocator, sizeof(worker_type)); if (!worker) { return NULL; } ods_log_debug("[%s[%i]] create", worker2str(type), num+1); lock_basic_init(&worker->worker_lock); lock_basic_set(&worker->worker_alarm); lock_basic_lock(&worker->worker_lock); worker->allocator = allocator; worker->thread_num = num +1; worker->engine = NULL; worker->task = NULL; worker->working_with = TASK_NONE; worker->need_to_exit = 0; worker->type = type; worker->clock_in = 0; worker->jobs_appointed = 0; worker->jobs_completed = 0; worker->jobs_failed = 0; worker->sleeping = 0; worker->waiting = 0; lock_basic_unlock(&worker->worker_lock); return worker; }
/** * Load zone signconf. * */ ods_status tools_signconf(zone_type* zone) { ods_status status = ODS_STATUS_OK; signconf_type* new_signconf = NULL; ods_log_assert(zone); ods_log_assert(zone->name); status = zone_load_signconf(zone, &new_signconf); if (status == ODS_STATUS_OK) { ods_log_assert(new_signconf); /* Denial of Existence Rollover? */ if (signconf_compare_denial(zone->signconf, new_signconf) == TASK_NSECIFY) { /** * Or NSEC -> NSEC3, or NSEC3 -> NSEC, or NSEC3 params changed. * All NSEC(3)s become invalid. */ namedb_wipe_denial(zone->db); namedb_cleanup_denials(zone->db); namedb_init_denials(zone->db); } /* all ok, switch signer configuration */ signconf_cleanup(zone->signconf); ods_log_debug("[%s] zone %s switch to new signconf", tools_str, zone->name); zone->signconf = new_signconf; signconf_log(zone->signconf, zone->name); zone->default_ttl = (uint32_t) duration2time(zone->signconf->soa_min); } else if (status != ODS_STATUS_UNCHANGED) { ods_log_error("[%s] unable to load signconf for zone %s: %s", tools_str, zone->name, ods_status2str(status)); } return status; }
static void engine_stop_xfrhandler(engine_type* engine) { if (!engine || !engine->xfrhandler) { return; } ods_log_debug("[%s] stop xfrhandler", engine_str); engine->xfrhandler->need_to_exit = 1; xfrhandler_signal(engine->xfrhandler); ods_log_debug("[%s] join xfrhandler", engine_str); if (engine->xfrhandler->started) { ods_thread_join(engine->xfrhandler->thread_id); engine->xfrhandler->started = 0; } engine->xfrhandler->engine = NULL; }
/** * Push item to queue. * */ ods_status fifoq_push(fifoq_type* q, void* item, worker_type* worker, int* tries) { if (!q || !item || !worker) { return ODS_STATUS_ASSERT_ERR; } if (q->count >= FIFOQ_MAX_COUNT) { /* #262 if drudgers remain on hold, do additional broadcast */ if (*tries > FIFOQ_TRIES_COUNT) { lock_basic_broadcast(&q->q_threshold); ods_log_debug("[%s] queue full, notify drudgers again", fifoq_str); /* reset tries */ *tries = 0; } return ODS_STATUS_UNCHANGED; } q->blob[q->count] = item; q->owner[q->count] = worker; q->count += 1; if (q->count == 1) { ods_log_deeebug("[%s] threshold %u reached, notify drudgers", fifoq_str, q->count); lock_basic_broadcast(&q->q_threshold); } return ODS_STATUS_OK; }
int handled_policy_import_cmd(int sockfd, engine_type* engine, const char *cmd, ssize_t n) { const char *scmd = "policy import"; cmd = ods_check_command(cmd,n,scmd); if (!cmd) return 0; // not handled ods_log_debug("[%s] %s command", module_str, scmd); time_t tstart = time(NULL); /* perform_policy_import(sockfd, engine->config); */ perform_update_kasp(sockfd, engine->config); //TODO: Need error checking so we only do this if the update succeeds perform_hsmkey_gen(sockfd, engine->config, 0 /* automatic */, engine->config->automatic_keygen_duration); flush_all_tasks(sockfd, engine); ods_printf(sockfd,"%s completed in %ld seconds.\n",scmd,time(NULL)-tstart); return 1; }
int handled_zone_del_cmd(int sockfd, engine_type* engine, const char *cmd, ssize_t n) { const char *scmd = "zone delete"; cmd = ods_check_command(cmd,n,scmd); if (!cmd) return 0; // not handled ods_log_debug("[%s] %s command", module_str, scmd); std::string zone; int need_write_xml = 0; if (!get_arguments(sockfd,cmd,zone, need_write_xml)) { help_zone_del_cmd(sockfd); return 1; } time_t tstart = time(NULL); perform_zone_del(sockfd,engine->config, zone.c_str(), need_write_xml, false); ods_printf(sockfd,"%s completed in %ld seconds.\n",scmd,time(NULL)-tstart); return 1; }
/** * Sign notify. * */ static void notify_tsig_sign(notify_type* notify, buffer_type* buffer) { tsig_algo_type* algo = NULL; if (!notify || !notify->tsig_rr || !notify->secondary || !notify->secondary->tsig || !notify->secondary->tsig->key || !buffer) { return; /* no tsig configured */ } algo = tsig_lookup_algo(notify->secondary->tsig->algorithm); if (!algo) { ods_log_error("[%s] unable to sign notify: tsig unknown algorithm " "%s", notify_str, notify->secondary->tsig->algorithm); return; } ods_log_assert(algo); tsig_rr_reset(notify->tsig_rr, algo, notify->secondary->tsig->key); notify->tsig_rr->original_query_id = buffer_pkt_id(buffer); notify->tsig_rr->algo_name = ldns_rdf_clone(notify->tsig_rr->algo->wf_name); notify->tsig_rr->key_name = ldns_rdf_clone(notify->tsig_rr->key->dname); log_dname(notify->tsig_rr->key_name, "tsig sign notify with key %s", LOG_DEBUG); log_dname(notify->tsig_rr->algo_name, "tsig sign notify with algorithm %s", LOG_DEBUG); tsig_rr_prepare(notify->tsig_rr); tsig_rr_update(notify->tsig_rr, buffer, buffer_position(buffer)); tsig_rr_sign(notify->tsig_rr); ods_log_debug("[%s] tsig append rr to notify id=%u", notify_str, buffer_pkt_id(buffer)); tsig_rr_append(notify->tsig_rr, buffer); buffer_pkt_set_arcount(buffer, buffer_pkt_arcount(buffer)+1); tsig_rr_prepare(notify->tsig_rr); return; }
/** * Create worker. * */ worker_type* worker_create(allocator_type* allocator, int num) { worker_type* worker; if (!allocator) { return NULL; } ods_log_assert(allocator); worker = (worker_type*) allocator_alloc(allocator, sizeof(worker_type)); if (!worker) { return NULL; } ods_log_debug("create worker[%i]", num +1); worker->allocator = allocator; worker->thread_num = num +1; worker->engine = NULL; worker->task = NULL; worker->need_to_exit = 0; worker->clock_in = 0; worker->jobs_appointed = 0; worker->jobs_completed = 0; worker->jobs_failed = 0; worker->sleeping = 0; worker->waiting = 0; lock_basic_init(&worker->worker_lock); lock_basic_set(&worker->worker_alarm); return worker; }
/** * Drop privileges. * */ static ods_status engine_privdrop(engine_type* engine) { ods_status status = ODS_STATUS_OK; uid_t uid = -1; gid_t gid = -1; ods_log_assert(engine); ods_log_assert(engine->config); ods_log_debug("[%s] drop privileges", engine_str); if (engine->config->username && engine->config->group) { ods_log_verbose("[%s] drop privileges to user %s, group %s", engine_str, engine->config->username, engine->config->group); } else if (engine->config->username) { ods_log_verbose("[%s] drop privileges to user %s", engine_str, engine->config->username); } else if (engine->config->group) { ods_log_verbose("[%s] drop privileges to group %s", engine_str, engine->config->group); } if (engine->config->chroot) { ods_log_verbose("[%s] chroot to %s", engine_str, engine->config->chroot); } status = privdrop(engine->config->username, engine->config->group, engine->config->chroot, &uid, &gid); engine->uid = uid; engine->gid = gid; privclose(engine->config->username, engine->config->group); return status; }
static int run(int sockfd, cmdhandler_ctx_type* context, const char *cmd) { db_connection_t* dbconn = getconnectioncontext(context); engine_type* engine = getglobalcontext(context); (void)cmd; if (!engine) { return 1; } if (!engine->config) { return 1; } if (!engine->config->zonelist_filename) { return 1; } if (!dbconn) { return 1; } ods_log_debug("[%s] %s command", module_str, zonelist_export_funcblock.cmdname); if (zonelist_export(sockfd, dbconn, engine->config->zonelist_filename, 1) != ZONELIST_EXPORT_OK) { ods_log_error("[%s] zonelist exported to %s failed", module_str, engine->config->zonelist_filename); client_printf_err(sockfd, "Exported zonelist to %s failed!\n", engine->config->zonelist_filename); return 1; } ods_log_info("[%s] zonelist exported to %s successfully", module_str, engine->config->zonelist_filename); client_printf(sockfd, "Exported zonelist to %s successfully\n", engine->config->zonelist_filename); return 0; }