Esempio n. 1
0
/**
 * 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;
}
Esempio n. 2
0
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;
}
Esempio n. 4
0
/**
 * 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;
}
Esempio n. 5
0
/**
 * 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;
}
Esempio n. 6
0
/**
 * 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;
}
Esempio n. 7
0
/**
 * 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;
}
Esempio n. 8
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;
}
Esempio n. 9
0
/**
 * 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;
}
Esempio n. 10
0
/**
 * 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;
}
Esempio n. 11
0
/**
 * 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;
}
Esempio n. 12
0
/**
 * 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;
}
Esempio n. 13
0
/**
 * 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;
}