/** * Read DNS output adapter. * */ static ods_status dnsout_read(dnsout_type* addns, const char* filename) { const char* rngfile = ODS_SE_RNGDIR "/addns.rng"; ods_status status = ODS_STATUS_OK; FILE* fd = NULL; if (!filename || !addns) { return ODS_STATUS_ASSERT_ERR; } ods_log_debug("[%s] read dnsout file %s", adapter_str, filename); status = parse_file_check(filename, rngfile); if (status != ODS_STATUS_OK) { ods_log_error("[%s] unable to read dnsout: parse error in " "file %s (%s)", adapter_str, filename, ods_status2str(status)); return status; } fd = ods_fopen(filename, NULL, "r"); if (fd) { addns->tsig = parse_addns_tsig(addns->allocator, filename); addns->provide_xfr = parse_addns_provide_xfr(addns->allocator, filename, addns->tsig); addns->do_notify = parse_addns_do_notify(addns->allocator, filename, addns->tsig); ods_fclose(fd); return ODS_STATUS_OK; } ods_log_error("[%s] unable to read dnsout: failed to open file %s", adapter_str, filename); return ODS_STATUS_ERR; }
bool write_pb_message_to_xml_file(const google::protobuf::Message *document, const char *xmlfilepath) { FILE *fw = ods_fopen(xmlfilepath,NULL,"w"); if (!fw) return false; write_msg(fw,document); ods_fclose(fw); return true; }
/** * Write zonefile. * */ ods_status adfile_write(void* zone, const char* filename) { FILE* fd = NULL; char* tmpname = NULL; zone_type* adzone = (zone_type*) zone; ods_status status = ODS_STATUS_OK; /* [start] sanity parameter checking */ if (!adzone || !adzone->adoutbound) { ods_log_error("[%s] unable to write file: no output adapter", adapter_str); return ODS_STATUS_ASSERT_ERR; } if (!filename) { ods_log_error("[%s] unable to write file: no filename given", adapter_str); return ODS_STATUS_ASSERT_ERR; } /* [end] sanity parameter checking */ /* [start] write zone */ tmpname = ods_build_path(filename, ".tmp", 0, 0); if (!tmpname) { return ODS_STATUS_MALLOC_ERR; } fd = ods_fopen(tmpname, NULL, "w"); if (fd) { status = adapi_printzone(fd, adzone); ods_fclose(fd); if (status == ODS_STATUS_OK) { if (adzone->adoutbound->error) { ods_log_error("[%s] unable to write zone %s file %s: one or " "more RR print failed", adapter_str, adzone->name, filename); /* clear error */ adzone->adoutbound->error = 0; status = ODS_STATUS_FWRITE_ERR; } } } else { status = ODS_STATUS_FOPEN_ERR; } if (status == ODS_STATUS_OK) { if (rename((const char*) tmpname, filename) != 0) { ods_log_error("[%s] unable to write file: failed to rename %s " "to %s (%s)", adapter_str, tmpname, filename, strerror(errno)); status = ODS_STATUS_RENAME_ERR; } } free(tmpname); /* [end] write zone */ return status; }
/** * Read zone from zonefile. * */ ods_status adfile_read(void* zone) { FILE* fd = NULL; zone_type* adzone = (zone_type*) zone; ods_status status = ODS_STATUS_OK; if (!adzone || !adzone->adinbound || !adzone->adinbound->configstr) { return ODS_STATUS_ASSERT_ERR; } fd = ods_fopen(adzone->adinbound->configstr, NULL, "r"); if (!fd) { return ODS_STATUS_FOPEN_ERR; } status = adfile_read_file(fd, adzone); ods_fclose(fd); if (status == ODS_STATUS_OK) { adapi_trans_full(zone); } return status; }
/** * Initialize logging. * */ void ods_log_init(const char *filename, int use_syslog, int verbosity) { #ifdef HAVE_SYSLOG_H int facility; #endif /* HAVE_SYSLOG_H */ ods_log_verbose("[%s] switching log to %s verbosity %i (log level %i)", log_str, use_syslog?"syslog":(filename&&filename[0]?filename:"stderr"), verbosity, verbosity+2); if (logfile && logfile != stderr) { ods_fclose(logfile); } log_level = verbosity + 2; #ifdef HAVE_SYSLOG_H if(logging_to_syslog) { closelog(); logging_to_syslog = 0; } if(use_syslog) { facility = ods_log_get_facility(filename); openlog(MY_PACKAGE_TARNAME, LOG_NDELAY, facility); logging_to_syslog = 1; return; } #endif /* HAVE_SYSLOG_H */ if(filename && filename[0]) { logfile = ods_fopen(filename, NULL, "a"); if (logfile) { ods_log_debug("[%s] new logfile %s", log_str, filename); return; } logfile = stderr; ods_log_warning("[%s] cannot open %s for appending, logging to " "stderr", log_str, filename); } else { logfile = stderr; } return; }
/** * Write zonefile. * */ ods_status adfile_write(void* zone, const char* filename) { FILE* fd = NULL; char* tmpname = NULL; zone_type* adzone = (zone_type*) zone; ods_status status = ODS_STATUS_OK; /* [start] sanity parameter checking */ if (!adzone) { ods_log_error("[%s] unable to write file: no zone (or no " "name given)", adapter_str); return ODS_STATUS_ASSERT_ERR; } if (!filename) { ods_log_error("[%s] unable to write file: no filename given", adapter_str); return ODS_STATUS_ERR; } /* [end] sanity parameter checking */ /* [start] write zone */ tmpname = ods_build_path(filename, ".tmp", 0, 0); fd = ods_fopen(tmpname, NULL, "w"); if (fd) { status = adapi_printzone(fd, adzone); ods_fclose(fd); } else { status = ODS_STATUS_FOPEN_ERR; } if (status == ODS_STATUS_OK) { if (rename((const char*) tmpname, filename) != 0) { ods_log_error("[%s] unable to write file: failed to rename %s " "to %s (%s)", adapter_str, tmpname, filename, strerror(errno)); status = ODS_STATUS_RENAME_ERR; } } free(tmpname); /* [end] write zone */ return status; }
/** * Get file last modified. * */ time_t ods_file_lastmodified(const char* file) { int ret; struct stat buf; FILE* fd; ods_log_assert(file); if ((fd = ods_fopen(file, NULL, "r")) != NULL) { ret = stat(file, &buf); if (ret == -1) { ods_log_error("[%s] unable to stat file %s: %s", file_str, file, strerror(errno)); ods_fclose(fd); return 0; } ods_fclose(fd); return buf.st_mtime; } else { ods_log_error("[%s] unable to stat file %s: ods_fopen() failed", file_str, file); } return 0; }
/** * Read zone from DNS Input Adapter. * */ ods_status addns_read(void* zone) { zone_type* z = (zone_type*) zone; ods_status status = ODS_STATUS_OK; char* xfrfile = NULL; FILE* fd = NULL; ods_log_assert(z); ods_log_assert(z->name); ods_log_assert(z->xfrd); ods_log_assert(z->db); ods_log_assert(z->adinbound); ods_log_assert(z->adinbound->type == ADAPTER_DNS); if (!z->xfrd->serial_disk_acquired) { return ODS_STATUS_UNCHANGED; } lock_basic_lock(&z->xfrd->rw_lock); xfrfile = ods_build_path(z->name, ".xfrd", 0, 1); fd = ods_fopen(xfrfile, NULL, "r"); free((void*) xfrfile); if (!fd) { lock_basic_unlock(&z->xfrd->rw_lock); return ODS_STATUS_FOPEN_ERR; } status = addns_read_file(fd, z); if (status == ODS_STATUS_OK) { lock_basic_lock(&z->xfrd->serial_lock); z->xfrd->serial_xfr = adapi_get_serial(z); z->xfrd->serial_xfr_acquired = z->xfrd->serial_disk_acquired; lock_basic_unlock(&z->xfrd->serial_lock); } ods_fclose(fd); lock_basic_unlock(&z->xfrd->rw_lock); return status; }
/** * Read the next RR from zone file. * */ static ldns_rr* adfile_read_rr(FILE* fd, zone_type* zone, char* line, ldns_rdf** orig, ldns_rdf** prev, uint32_t* ttl, ldns_status* status, unsigned int* l) { ldns_rr* rr = NULL; ldns_rdf* tmp = NULL; FILE* fd_include = NULL; int len = 0; ods_status s = ODS_STATUS_OK; uint32_t new_ttl = 0; const char *endptr; /* unused */ int offset = 0; adfile_read_line: if (ttl) { new_ttl = *ttl; } len = adutil_readline_frm_file(fd, line, l, 0); adutil_rtrim_line(line, &len); if (len >= 0) { switch (line[0]) { /* directive */ case '$': if (strncmp(line, "$ORIGIN", 7) == 0 && isspace((int)line[7])) { /* copy from ldns */ if (*orig) { ldns_rdf_deep_free(*orig); *orig = NULL; } offset = 8; while (isspace((int)line[offset])) { offset++; } tmp = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, line + offset); if (!tmp) { /* could not parse what next to $ORIGIN */ *status = LDNS_STATUS_SYNTAX_DNAME_ERR; return NULL; } *orig = tmp; /* end copy from ldns */ goto adfile_read_line; /* perhaps next line is rr */ break; } else if (strncmp(line, "$TTL", 4) == 0 && isspace((int)line[4])) { /* override default ttl */ offset = 5; while (isspace((int)line[offset])) { offset++; } if (ttl) { *ttl = ldns_str2period(line + offset, &endptr); new_ttl = *ttl; } goto adfile_read_line; /* perhaps next line is rr */ break; } else if (strncmp(line, "$INCLUDE", 8) == 0 && isspace((int)line[8])) { /* dive into this file */ offset = 9; while (isspace((int)line[offset])) { offset++; } fd_include = ods_fopen(line + offset, NULL, "r"); if (fd_include) { s = adfile_read_file(fd_include, zone); ods_fclose(fd_include); } else { ods_log_error("[%s] unable to open include file %s", adapter_str, (line+offset)); *status = LDNS_STATUS_SYNTAX_ERR; return NULL; } if (s != ODS_STATUS_OK) { *status = LDNS_STATUS_SYNTAX_ERR; ods_log_error("[%s] error in include file %s", adapter_str, (line+offset)); return NULL; } /* restore current ttl */ if (ttl) { *ttl = new_ttl; } goto adfile_read_line; /* perhaps next line is rr */ break; } goto adfile_read_rr; /* this can be an owner name */ break; /* comments, empty lines */ case ';': case '\n': goto adfile_read_line; /* perhaps next line is rr */ break; /* let's hope its a RR */ default: adfile_read_rr: if (adutil_whitespace_line(line, len)) { goto adfile_read_line; /* perhaps next line is rr */ break; } *status = ldns_rr_new_frm_str(&rr, line, new_ttl, *orig, prev); if (*status == LDNS_STATUS_OK) { return rr; } else if (*status == LDNS_STATUS_SYNTAX_EMPTY) { if (rr) { ldns_rr_free(rr); rr = NULL; } *status = LDNS_STATUS_OK; goto adfile_read_line; /* perhaps next line is rr */ break; } else { ods_log_error("[%s] error parsing RR at line %i (%s): %s", adapter_str, l&&*l?*l:0, ldns_get_errorstr_by_id(*status), line); while (len >= 0) { len = adutil_readline_frm_file(fd, line, l, 0); } if (rr) { ldns_rr_free(rr); rr = NULL; } return NULL; } break; } } /* -1, EOF */ *status = LDNS_STATUS_OK; return NULL; }
/** * Configure engine. * */ engineconfig_type* engine_config(allocator_type* allocator, const char* cfgfile, int cmdline_verbosity) { engineconfig_type* ecfg; const char* rngfile = ODS_SE_RNGDIR "/conf.rng"; FILE* cfgfd = NULL; if (!allocator) { ods_log_error("[%s] failed to read: no allocator available", conf_str); return NULL; } ods_log_assert(allocator); if (!cfgfile) { ods_log_error("[%s] failed to read: no filename given", conf_str); return NULL; } ods_log_assert(cfgfile); ods_log_verbose("[%s] read cfgfile: %s", conf_str, cfgfile); ecfg = (engineconfig_type*) allocator_alloc(allocator, sizeof(engineconfig_type)); if (!ecfg) { ods_log_error("[%s] failed to read: allocator failed", conf_str); return NULL; } ecfg->allocator = allocator; /* check syntax (slows down parsing configuration file) */ if (parse_file_check(cfgfile, rngfile) != ODS_STATUS_OK) { ods_log_error("[%s] failed to read: unable to parse file %s", conf_str, cfgfile); return NULL; } /* open cfgfile */ cfgfd = ods_fopen(cfgfile, NULL, "r"); if (cfgfd) { /* get values */ ecfg->cfg_filename = allocator_strdup(allocator, cfgfile); ecfg->policy_filename = parse_conf_policy_filename(allocator, cfgfile); ecfg->zonelist_filename = parse_conf_zonelist_filename(allocator, cfgfile); ecfg->zonefetch_filename = parse_conf_zonefetch_filename(allocator, cfgfile); ecfg->log_filename = parse_conf_log_filename(allocator, cfgfile); ecfg->pid_filename = parse_conf_pid_filename(allocator, cfgfile); ecfg->delegation_signer_submit_command = parse_conf_delegation_signer_submit_command(allocator, cfgfile); ecfg->delegation_signer_retract_command = parse_conf_delegation_signer_retract_command(allocator, cfgfile); ecfg->clisock_filename = parse_conf_clisock_filename(allocator, cfgfile); ecfg->working_dir = parse_conf_working_dir(allocator, cfgfile); ecfg->username = parse_conf_username(allocator, cfgfile); ecfg->group = parse_conf_group(allocator, cfgfile); ecfg->chroot = parse_conf_chroot(allocator, cfgfile); ecfg->datastore = parse_conf_datastore(allocator, cfgfile); ecfg->db_host = parse_conf_db_host(allocator,cfgfile); ecfg->db_username = parse_conf_db_username(allocator,cfgfile); ecfg->db_password = parse_conf_db_password(allocator,cfgfile); ecfg->use_syslog = parse_conf_use_syslog(cfgfile); ecfg->num_worker_threads = parse_conf_worker_threads(cfgfile); ecfg->manual_keygen = parse_conf_manual_keygen(cfgfile); /* If any verbosity has been specified at cmd line we will use that */ if (cmdline_verbosity > 0) { ecfg->verbosity = cmdline_verbosity; } else { ecfg->verbosity = parse_conf_verbosity(cfgfile); } ecfg->db_port = parse_conf_db_port(cfgfile); ecfg->automatic_keygen_duration = parse_conf_automatic_keygen_period(cfgfile); /* done */ ods_fclose(cfgfd); return ecfg; } ods_log_error("[%s] failed to read: unable to open file %s", conf_str, cfgfile); return NULL; }
/** * Write to DNS Output Adapter. * */ ods_status addns_write(void* zone) { FILE* fd = NULL; char* atmpfile = NULL; char* axfrfile = NULL; char* itmpfile = NULL; char* ixfrfile = NULL; zone_type* z = (zone_type*) zone; int ret = 0; ods_status status = ODS_STATUS_OK; ods_log_assert(z); ods_log_assert(z->name); ods_log_assert(z->adoutbound); ods_log_assert(z->adoutbound->type == ADAPTER_DNS); atmpfile = ods_build_path(z->name, ".axfr.tmp", 0, 1); fd = ods_fopen(atmpfile, NULL, "w"); if (!fd) { free((void*) atmpfile); return ODS_STATUS_FOPEN_ERR; } status = adapi_printaxfr(fd, z); ods_fclose(fd); if (status != ODS_STATUS_OK) { return status; } if (z->db->is_initialized) { itmpfile = ods_build_path(z->name, ".ixfr.tmp", 0, 1); fd = ods_fopen(itmpfile, NULL, "w"); if (!fd) { free((void*) atmpfile); free((void*) itmpfile); return ODS_STATUS_FOPEN_ERR; } status = adapi_printixfr(fd, z); if (status != ODS_STATUS_OK) { return status; } ods_fclose(fd); } /* lock and move */ axfrfile = ods_build_path(z->name, ".axfr", 0, 1); lock_basic_lock(&z->xfr_lock); ret = rename(atmpfile, axfrfile); if (ret != 0) { ods_log_error("[%s] unable to rename file %s to %s: %s", adapter_str, atmpfile, axfrfile, strerror(errno)); lock_basic_unlock(&z->xfr_lock); free((void*) atmpfile); free((void*) axfrfile); free((void*) itmpfile); return ODS_STATUS_RENAME_ERR; } free((void*) atmpfile); free((void*) axfrfile); if (z->db->is_initialized) { ixfrfile = ods_build_path(z->name, ".ixfr", 0, 1); ret = rename(itmpfile, ixfrfile); if (ret != 0) { ods_log_error("[%s] unable to rename file %s to %s: %s", adapter_str, itmpfile, ixfrfile, strerror(errno)); lock_basic_unlock(&z->xfr_lock); free((void*) itmpfile); free((void*) ixfrfile); return ODS_STATUS_RENAME_ERR; } free((void*) itmpfile); free((void*) ixfrfile); } lock_basic_unlock(&z->xfr_lock); dnsout_send_notify(zone); return ODS_STATUS_OK; }
/** * Backup zone. * */ ods_status zone_backup2(zone_type* zone) { char* filename = NULL; char* tmpfile = NULL; FILE* fd = NULL; task_type* task = NULL; int ret = 0; ods_status status = ODS_STATUS_OK; ods_log_assert(zone); ods_log_assert(zone->name); ods_log_assert(zone->db); ods_log_assert(zone->signconf); ods_log_assert(zone->task); tmpfile = ods_build_path(zone->name, ".backup2.tmp", 0, 1); filename = ods_build_path(zone->name, ".backup2", 0, 1); if (!tmpfile || !filename) { return ODS_STATUS_MALLOC_ERR; } fd = ods_fopen(tmpfile, NULL, "w"); if (fd) { fprintf(fd, "%s\n", ODS_SE_FILE_MAGIC_V3); task = (task_type*) zone->task; fprintf(fd, ";;Time: %u\n", (unsigned) task->when); /** Backup zone */ fprintf(fd, ";;Zone: name %s class %i inbound %u internal %u " "outbound %u\n", zone->name, (int) zone->klass, (unsigned) zone->db->inbserial, (unsigned) zone->db->intserial, (unsigned) zone->db->outserial); /** Backup signconf */ signconf_backup(fd, zone->signconf, ODS_SE_FILE_MAGIC_V3); /** Backup NSEC3 parameters */ if (zone->signconf->nsec3params) { nsec3params_backup(fd, zone->signconf->nsec3_algo, zone->signconf->nsec3_optout, zone->signconf->nsec3_iterations, zone->signconf->nsec3_salt, zone->signconf->nsec3params->rr, ODS_SE_FILE_MAGIC_V3); } /** Backup keylist */ keylist_backup(fd, zone->signconf->keys, ODS_SE_FILE_MAGIC_V3); fprintf(fd, ";;\n"); /** Backup domains and stuff */ namedb_backup2(fd, zone->db); /** Done */ fprintf(fd, "%s\n", ODS_SE_FILE_MAGIC_V3); ods_fclose(fd); ret = rename(tmpfile, filename); if (ret != 0) { ods_log_error("[%s] unable to rename zone %s backup %s to %s: %s", zone_str, zone->name, tmpfile, filename, strerror(errno)); status = ODS_STATUS_RENAME_ERR; } } else { status = ODS_STATUS_FOPEN_ERR; } free((void*) tmpfile); free((void*) filename); return status; }
/** * Recover zone from backup. * */ ods_status zone_recover2(zone_type* zone) { char* filename = NULL; FILE* fd = NULL; const char* token = NULL; time_t when = 0; task_type* task = NULL; ods_status status = ODS_STATUS_OK; /* zone part */ int klass = 0; uint32_t inbound = 0, internal = 0, outbound = 0; /* signconf part */ time_t lastmod = 0; /* nsec3params part */ const char* salt = NULL; ods_log_assert(zone); ods_log_assert(zone->name); ods_log_assert(zone->signconf); ods_log_assert(zone->db); filename = ods_build_path(zone->name, ".backup2", 0, 1); if (!filename) { return ODS_STATUS_MALLOC_ERR; } fd = ods_fopen(filename, NULL, "r"); if (fd) { /* start recovery */ if (!backup_read_check_str(fd, ODS_SE_FILE_MAGIC_V3)) { ods_log_error("[%s] corrupted backup file zone %s: read magic " "error", zone_str, zone->name); goto recover_error2; } if (!backup_read_check_str(fd, ";;Time:") | !backup_read_time_t(fd, &when)) { ods_log_error("[%s] corrupted backup file zone %s: read time " "error", zone_str, zone->name); goto recover_error2; } /* zone stuff */ if (!backup_read_check_str(fd, ";;Zone:") | !backup_read_check_str(fd, "name") | !backup_read_check_str(fd, zone->name)) { ods_log_error("[%s] corrupted backup file zone %s: read name " "error", zone_str, zone->name); goto recover_error2; } if (!backup_read_check_str(fd, "class") | !backup_read_int(fd, &klass)) { ods_log_error("[%s] corrupted backup file zone %s: read class " "error", zone_str, zone->name); goto recover_error2; } if (!backup_read_check_str(fd, "inbound") | !backup_read_uint32_t(fd, &inbound) | !backup_read_check_str(fd, "internal") | !backup_read_uint32_t(fd, &internal) | !backup_read_check_str(fd, "outbound") | !backup_read_uint32_t(fd, &outbound)) { ods_log_error("[%s] corrupted backup file zone %s: read serial " "error", zone_str, zone->name); goto recover_error2; } zone->klass = (ldns_rr_class) klass; zone->db->inbserial = inbound; zone->db->intserial = internal; zone->db->outserial = outbound; /* signconf part */ if (!backup_read_check_str(fd, ";;Signconf:") | !backup_read_check_str(fd, "lastmod") | !backup_read_time_t(fd, &lastmod) | !backup_read_check_str(fd, "maxzonettl") | !backup_read_check_str(fd, "0") | !backup_read_check_str(fd, "resign") | !backup_read_duration(fd, &zone->signconf->sig_resign_interval) | !backup_read_check_str(fd, "refresh") | !backup_read_duration(fd, &zone->signconf->sig_refresh_interval) | !backup_read_check_str(fd, "valid") | !backup_read_duration(fd, &zone->signconf->sig_validity_default) | !backup_read_check_str(fd, "denial") | !backup_read_duration(fd,&zone->signconf->sig_validity_denial) | !backup_read_check_str(fd, "jitter") | !backup_read_duration(fd, &zone->signconf->sig_jitter) | !backup_read_check_str(fd, "offset") | !backup_read_duration(fd, &zone->signconf->sig_inception_offset) | !backup_read_check_str(fd, "nsec") | !backup_read_rr_type(fd, &zone->signconf->nsec_type) | !backup_read_check_str(fd, "dnskeyttl") | !backup_read_duration(fd, &zone->signconf->dnskey_ttl) | !backup_read_check_str(fd, "soattl") | !backup_read_duration(fd, &zone->signconf->soa_ttl) | !backup_read_check_str(fd, "soamin") | !backup_read_duration(fd, &zone->signconf->soa_min) | !backup_read_check_str(fd, "serial") | !backup_read_str(fd, &zone->signconf->soa_serial)) { ods_log_error("[%s] corrupted backup file zone %s: read signconf " "error", zone_str, zone->name); goto recover_error2; } /* nsec3params part */ if (zone->signconf->nsec_type == LDNS_RR_TYPE_NSEC3) { if (!backup_read_check_str(fd, ";;Nsec3parameters:") | !backup_read_check_str(fd, "salt") | !backup_read_str(fd, &salt) | !backup_read_check_str(fd, "algorithm") | !backup_read_uint32_t(fd, &zone->signconf->nsec3_algo) | !backup_read_check_str(fd, "optout") | !backup_read_int(fd, &zone->signconf->nsec3_optout) | !backup_read_check_str(fd, "iterations") | !backup_read_uint32_t(fd, &zone->signconf->nsec3_iterations)) { ods_log_error("[%s] corrupted backup file zone %s: read " "nsec3parameters error", zone_str, zone->name); goto recover_error2; } zone->signconf->nsec3_salt = allocator_strdup( zone->signconf->allocator, salt); free((void*) salt); salt = NULL; zone->signconf->nsec3params = nsec3params_create( (void*) zone->signconf, (uint8_t) zone->signconf->nsec3_algo, (uint8_t) zone->signconf->nsec3_optout, (uint16_t) zone->signconf->nsec3_iterations, zone->signconf->nsec3_salt); if (!zone->signconf->nsec3params) { ods_log_error("[%s] corrupted backup file zone %s: unable to " "create nsec3param", zone_str, zone->name); goto recover_error2; } } zone->signconf->last_modified = lastmod; zone->default_ttl = (uint32_t) duration2time(zone->signconf->soa_min); /* keys part */ zone->signconf->keys = keylist_create((void*) zone->signconf); while (backup_read_str(fd, &token)) { if (ods_strcmp(token, ";;Key:") == 0) { if (!key_recover2(fd, zone->signconf->keys)) { ods_log_error("[%s] corrupted backup file zone %s: read " "key error", zone_str, zone->name); goto recover_error2; } } else if (ods_strcmp(token, ";;") == 0) { /* keylist done */ free((void*) token); token = NULL; break; } else { /* keylist corrupted */ goto recover_error2; } free((void*) token); token = NULL; } /* publish dnskeys */ status = zone_publish_dnskeys(zone); if (status != ODS_STATUS_OK) { ods_log_error("[%s] corrupted backup file zone %s: unable to " "publish dnskeys (%s)", zone_str, zone->name, ods_status2str(status)); goto recover_error2; } /* publish nsec3param */ status = zone_publish_nsec3param(zone); if (status != ODS_STATUS_OK) { ods_log_error("[%s] corrupted backup file zone %s: unable to " "publish nsec3param (%s)", zone_str, zone->name, ods_status2str(status)); goto recover_error2; } /* publish other records */ status = backup_read_namedb(fd, zone); if (status != ODS_STATUS_OK) { ods_log_error("[%s] corrupted backup file zone %s: unable to " "read resource records (%s)", zone_str, zone->name, ods_status2str(status)); goto recover_error2; } /* task */ task = task_create(TASK_SIGN, when, (void*) zone); if (!task) { ods_log_error("[%s] failed to restore zone %s: unable to " "create task", zone_str, zone->name); goto recover_error2; } zone->task = (void*) task; free((void*)filename); ods_fclose(fd); /* journal */ zone->db->is_initialized = 1; filename = ods_build_path(zone->name, ".ixfr", 0, 1); if (filename) { fd = ods_fopen(filename, NULL, "r"); } if (fd) { status = backup_read_ixfr(fd, zone); if (status != ODS_STATUS_OK) { ods_log_warning("[%s] corrupted journal file zone %s, " "skipping (%s)", zone_str, zone->name, ods_status2str(status)); ixfr_cleanup(zone->ixfr); zone->ixfr = ixfr_create((void*)zone); } } lock_basic_lock(&zone->ixfr->ixfr_lock); ixfr_purge(zone->ixfr); lock_basic_unlock(&zone->ixfr->ixfr_lock); /* all ok */ free((void*)filename); ods_fclose(fd); if (zone->stats) { lock_basic_lock(&zone->stats->stats_lock); stats_clear(zone->stats); lock_basic_unlock(&zone->stats->stats_lock); } return ODS_STATUS_OK; } return ODS_STATUS_UNCHANGED; recover_error2: free((void*)filename); ods_fclose(fd); /* signconf cleanup */ free((void*)salt); salt = NULL; signconf_cleanup(zone->signconf); zone->signconf = signconf_create(); ods_log_assert(zone->signconf); /* namedb cleanup */ namedb_cleanup(zone->db); zone->db = namedb_create((void*)zone); ods_log_assert(zone->db); /* stats reset */ if (zone->stats) { lock_basic_lock(&zone->stats->stats_lock); stats_clear(zone->stats); lock_basic_unlock(&zone->stats->stats_lock); } return ODS_STATUS_ERR; }