OpenDNSSEC-signer 1.3.0rc3
/build/buildd2-opendnssec_1.3.0~rc3-1-mips-lpJjcT/opendnssec-1.3.0~rc3/signer/src/signer/tools.c
Go to the documentation of this file.
00001 /*
00002  * $Id: tools.c 5227 2011-06-12 08:51:24Z jakob $
00003  *
00004  * Copyright (c) 2009 NLNet Labs. All rights reserved.
00005  *
00006  * Redistribution and use in source and binary forms, with or without
00007  * modification, are permitted provided that the following conditions
00008  * are met:
00009  * 1. Redistributions of source code must retain the above copyright
00010  *    notice, this list of conditions and the following disclaimer.
00011  * 2. Redistributions in binary form must reproduce the above copyright
00012  *    notice, this list of conditions and the following disclaimer in the
00013  *    documentation and/or other materials provided with the distribution.
00014  *
00015  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
00016  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00017  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00018  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
00019  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00020  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
00021  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00022  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
00023  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
00024  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
00025  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00026  *
00027  */
00028 
00034 #include "config.h"
00035 #include "adapter/adapter.h"
00036 #include "shared/file.h"
00037 #include "shared/log.h"
00038 #include "signer/tools.h"
00039 #include "signer/zone.h"
00040 
00041 static const char* tools_str = "tools";
00042 
00043 
00048 ods_status
00049 tools_input(zone_type* zone)
00050 {
00051     ods_status status = ODS_STATUS_OK;
00052     int error = 0;
00053     char* tmpname = NULL;
00054     char* lockname = NULL;
00055     time_t start = 0;
00056     time_t end = 0;
00057     FILE* fd = NULL;
00058 
00059     if (!zone) {
00060         ods_log_error("[%s] unable to read zone: no zone", tools_str);
00061         return ODS_STATUS_ASSERT_ERR;
00062     }
00063     ods_log_assert(zone);
00064 
00065     if (!zone->zonedata) {
00066         ods_log_error("[%s] unable to read zone: no zone data", tools_str);
00067         return ODS_STATUS_ASSERT_ERR;
00068     }
00069     ods_log_assert(zone->zonedata);
00070 
00071     ods_log_assert(zone->adinbound);
00072     ods_log_assert(zone->signconf);
00073 
00074     if (zone->stats) {
00075         lock_basic_lock(&zone->stats->stats_lock);
00076         zone->stats->sort_done = 0;
00077         zone->stats->sort_count = 0;
00078         zone->stats->sort_time = 0;
00079         lock_basic_unlock(&zone->stats->stats_lock);
00080     }
00081 
00082     if (zone->adinbound->type == ADAPTER_FILE) {
00083         if (zone->fetch) {
00084             ods_log_verbose("fetch zone %s",
00085                 zone->name?zone->name:"(null)");
00086             tmpname = ods_build_path(
00087                 zone->adinbound->configstr, ".axfr", 0);
00088             lockname = ods_build_path(
00089                 zone->adinbound->configstr, ".lock", 0);
00090 
00091 lock_fetch:
00092             if (access(lockname, F_OK) == 0) {
00093                 ods_log_deeebug("axfr file %s is locked, waiting"
00094                     "waiting...", tmpname);
00095                 sleep(1);
00096                 goto lock_fetch;
00097             } else {
00098                 fd = fopen(lockname, "w");
00099                 if (!fd) {
00100                     ods_log_error("zone fetcher cannot lock AXFR file %s",
00101                         lockname);
00102                     free((void*)tmpname);
00103                     free((void*)lockname);
00104                     return ODS_STATUS_ERR;
00105                 }
00106             }
00107             ods_log_assert(fd); /* locked */
00108 
00109             error = ods_file_copy(tmpname, zone->adinbound->configstr);
00110 
00111             fclose(fd);
00112             (void) unlink(lockname); /* unlocked */
00113 
00114             if (error) {
00115                 ods_log_error("[%s] unable to copy axfr file %s to %s",
00116                     tools_str, tmpname, zone->adinbound->configstr);
00117                 free((void*)tmpname);
00118                 free((void*)lockname);
00119                 return ODS_STATUS_ERR;
00120             }
00121             free((void*)tmpname);
00122             free((void*)lockname);
00123         }
00124     }
00125 
00126     start = time(NULL);
00127     status = adapter_read(zone);
00128     if (status != ODS_STATUS_OK) {
00129         ods_log_error("[%s] unable to read from input adapter for zone %s: "
00130             "%s", tools_str, zone->name?zone->name:"(null)",
00131             ods_status2str(status));
00132     } else {
00133         tmpname = ods_build_path(zone->name, ".inbound", 0);
00134         status = ods_file_copy(zone->adinbound->configstr, tmpname);
00135         free((void*)tmpname);
00136         tmpname = NULL;
00137         if (status != ODS_STATUS_OK) {
00138             ods_log_error("[%s] unable to copy zone input file %s: "
00139                 "%s", tools_str, zone->name?zone->name:"(null)",
00140                 ods_status2str(status));
00141         }
00142     }
00143 
00144     if (status == ODS_STATUS_OK) {
00145         ods_log_verbose("[%s] commit updates for zone %s", tools_str,
00146             zone->name?zone->name:"(null)");
00147         status = zonedata_commit(zone->zonedata);
00148     } else {
00149         ods_log_warning("[%s] rollback updates for zone %s", tools_str,
00150             zone->name?zone->name:"(null)");
00151         zonedata_rollback(zone->zonedata);
00152     }
00153     end = time(NULL);
00154 
00155     if (status == ODS_STATUS_OK && zone->stats) {
00156         lock_basic_lock(&zone->stats->stats_lock);
00157         zone->stats->start_time = start;
00158         zone->stats->sort_time = (end-start);
00159         zone->stats->sort_done = 1;
00160         lock_basic_unlock(&zone->stats->stats_lock);
00161     }
00162     return status;
00163 }
00164 
00165 
00170 ods_status
00171 tools_nsecify(zone_type* zone)
00172 {
00173     ods_status status = ODS_STATUS_OK;
00174     time_t start = 0;
00175     time_t end = 0;
00176     uint32_t ttl = 0;
00177     uint32_t num_added = 0;
00178 
00179     if (!zone) {
00180         ods_log_error("[%s] unable to nsecify zone: no zone", tools_str);
00181         return ODS_STATUS_ASSERT_ERR;
00182     }
00183     ods_log_assert(zone);
00184 
00185     if (!zone->zonedata) {
00186         ods_log_error("[%s] unable to nsecify zone %s: no zonedata",
00187             tools_str, zone->name);
00188         return ODS_STATUS_ASSERT_ERR;
00189     }
00190     ods_log_assert(zone->zonedata);
00191 
00192     if (!zone->signconf) {
00193         ods_log_error("[%s] unable to nsecify zone %s: no signconf",
00194             tools_str, zone->name);
00195         return ODS_STATUS_ASSERT_ERR;
00196     }
00197     ods_log_assert(zone->signconf);
00198 
00199     if (zone->stats) {
00200         lock_basic_lock(&zone->stats->stats_lock);
00201         zone->stats->nsec_time = 0;
00202         zone->stats->nsec_count = 0;
00203         lock_basic_unlock(&zone->stats->stats_lock);
00204     }
00205 
00206     start = time(NULL);
00207     /* determine NSEC(3) ttl */
00208     ttl = zone->zonedata->default_ttl;
00209     if (zone->signconf->soa_min) {
00210         ttl = (uint32_t) duration2time(zone->signconf->soa_min);
00211     }
00212     /* add missing empty non-terminals */
00213     status = zonedata_entize(zone->zonedata, zone->dname);
00214     if (status != ODS_STATUS_OK) {
00215         ods_log_error("[%s] unable to nsecify zone %s: failed to add empty ",
00216             "non-terminals", tools_str, zone->name);
00217         return status;
00218     }
00219 
00220     /* NSEC or NSEC3? */
00221     if (zone->signconf->nsec_type == LDNS_RR_TYPE_NSEC) {
00222         status = zonedata_nsecify(zone->zonedata, zone->klass, ttl,
00223             &num_added);
00224     } else if (zone->signconf->nsec_type == LDNS_RR_TYPE_NSEC3) {
00225         if (zone->signconf->nsec3_optout) {
00226             ods_log_debug("[%s] OptOut is being used for zone %s",
00227                 tools_str, zone->name);
00228         }
00229         ods_log_assert(zone->nsec3params);
00230         status = zonedata_nsecify3(zone->zonedata, zone->klass, ttl,
00231             zone->nsec3params, &num_added);
00232     } else {
00233         ods_log_error("[%s] unable to nsecify zone %s: unknown RRtype %u for ",
00234             "denial of existence", tools_str, zone->name,
00235             (unsigned) zone->signconf->nsec_type);
00236         return ODS_STATUS_ERR;
00237     }
00238     end = time(NULL);
00239     if (status == ODS_STATUS_OK && zone->stats) {
00240         lock_basic_lock(&zone->stats->stats_lock);
00241         if (!zone->stats->start_time) {
00242             zone->stats->start_time = start;
00243         }
00244         zone->stats->nsec_time = (end-start);
00245         zone->stats->nsec_count = num_added;
00246         lock_basic_unlock(&zone->stats->stats_lock);
00247     }
00248     return status;
00249 }
00250 
00251 
00256 ods_status
00257 tools_audit(zone_type* zone, char* working_dir, char* cfg_filename)
00258 {
00259     char* inbound = NULL;
00260     char* finalized = NULL;
00261     char str[SYSTEM_MAXLEN];
00262     ods_status status = ODS_STATUS_OK;
00263     int error = 0;
00264     time_t start = 0;
00265     time_t end = 0;
00266 
00267     if (!zone) {
00268         ods_log_error("[%s] unable to audit zone: no zone", tools_str);
00269         return ODS_STATUS_ASSERT_ERR;
00270     }
00271     ods_log_assert(zone);
00272 
00273     if (!zone->signconf) {
00274         ods_log_error("[%s] unable to audit zone %s: no signconf",
00275             tools_str, zone->name?zone->name:"(null)");
00276         return ODS_STATUS_ASSERT_ERR;
00277     }
00278     ods_log_assert(zone->signconf);
00279 
00280     if (zone->stats) {
00281         lock_basic_lock(&zone->stats->stats_lock);
00282         if (zone->stats->sort_done == 0 &&
00283             (zone->stats->sig_count <= zone->stats->sig_soa_count)) {
00284             lock_basic_unlock(&zone->stats->stats_lock);
00285             return ODS_STATUS_OK;
00286         }
00287         lock_basic_unlock(&zone->stats->stats_lock);
00288     }
00289 
00290     if (zone->signconf->audit) {
00291         inbound = ods_build_path(zone->name, ".inbound", 0);
00292         finalized = ods_build_path(zone->name, ".finalized", 0);
00293         status = adfile_write(zone, finalized);
00294         if (status != ODS_STATUS_OK) {
00295             ods_log_error("[%s] audit zone %s failed: unable to write zone",
00296                 tools_str, zone->name?zone->name:"(null)");
00297             free((void*)inbound);
00298             free((void*)finalized);
00299             return status;
00300         }
00301 
00302         snprintf(str, SYSTEM_MAXLEN, "%s -c %s -u %s/%s -s %s/%s -z %s > /dev/null",
00303             ODS_SE_AUDITOR,
00304             cfg_filename?cfg_filename:ODS_SE_CFGFILE,
00305             working_dir?working_dir:"",
00306             inbound?inbound:"(null)",
00307             working_dir?working_dir:"",
00308             finalized?finalized:"(null)",
00309             zone->name?zone->name:"(null)");
00310 
00311         start = time(NULL);
00312         ods_log_debug("system call: %s", str);
00313         error = system(str);
00314         if (finalized) {
00315             if (!error) {
00316                 unlink(finalized);
00317             }
00318             free((void*)finalized);
00319         }
00320         free((void*)inbound);
00321 
00322         if (error) {
00323             status = ODS_STATUS_ERR;
00324         }
00325         end = time(NULL);
00326         if (status == ODS_STATUS_OK && zone->stats) {
00327             lock_basic_lock(&zone->stats->stats_lock);
00328             zone->stats->audit_time = (end-start);
00329             lock_basic_unlock(&zone->stats->stats_lock);
00330         }
00331     }
00332     return status;
00333 }
00334 
00335 
00340 ods_status
00341 tools_output(zone_type* zone)
00342 {
00343     ods_status status = ODS_STATUS_OK;
00344     char str[SYSTEM_MAXLEN];
00345     int error = 0;
00346     uint32_t outbound_serial = 0;
00347 
00348     if (!zone) {
00349         ods_log_error("[%s] unable to write zone: no zone", tools_str);
00350         return ODS_STATUS_ASSERT_ERR;
00351     }
00352     ods_log_assert(zone);
00353 
00354     if (!zone->adoutbound) {
00355         ods_log_error("[%s] unable to write zone %s: no outbound adapter",
00356             tools_str, zone->name?zone->name:"(null)");
00357         return ODS_STATUS_ASSERT_ERR;
00358     }
00359     ods_log_assert(zone->adoutbound);
00360 
00361     if (zone->stats) {
00362         lock_basic_lock(&zone->stats->stats_lock);
00363         if (zone->stats->sort_done == 0 &&
00364             (zone->stats->sig_count <= zone->stats->sig_soa_count)) {
00365             ods_log_verbose("[%s] skip write zone %s serial %u (zone not "
00366                 "changed)", tools_str, zone->name?zone->name:"(null)",
00367                 zone->zonedata->internal_serial);
00368             stats_clear(zone->stats);
00369             lock_basic_unlock(&zone->stats->stats_lock);
00370             zone->zonedata->internal_serial =
00371                 zone->zonedata->outbound_serial;
00372             return ODS_STATUS_OK;
00373         }
00374         lock_basic_unlock(&zone->stats->stats_lock);
00375     }
00376 
00377     outbound_serial = zone->zonedata->outbound_serial;
00378     zone->zonedata->outbound_serial = zone->zonedata->internal_serial;
00379     status = adapter_write(zone);
00380     if (status != ODS_STATUS_OK) {
00381         ods_log_error("[%s] unable to write zone %s: adapter failed",
00382             tools_str, zone->name);
00383         zone->zonedata->outbound_serial = outbound_serial;
00384         return status;
00385     }
00386 
00387     /* initialize zonedata */
00388     zone->zonedata->initialized = 1;
00389 
00390     /* kick the nameserver */
00391     if (zone->notify_ns) {
00392         ods_log_verbose("[%s] notify nameserver: %s", tools_str,
00393             zone->notify_ns);
00394         snprintf(str, SYSTEM_MAXLEN, "%s > /dev/null",
00395             zone->notify_ns);
00396         error = system(str);
00397         if (error) {
00398            ods_log_error("[%s] failed to notify nameserver", tools_str);
00399            status = ODS_STATUS_ERR;
00400         }
00401     }
00402     /* log stats */
00403     if (zone->stats) {
00404         lock_basic_lock(&zone->stats->stats_lock);
00405         zone->stats->end_time = time(NULL);
00406         ods_log_debug("[%s] log stats for zone %s", tools_str,
00407             zone->name?zone->name:"(null)");
00408         stats_log(zone->stats, zone->name, zone->signconf->nsec_type);
00409         stats_clear(zone->stats);
00410         lock_basic_unlock(&zone->stats->stats_lock);
00411     }
00412     return status;
00413 }