OpenDNSSEC-signer  1.3.4
/build/buildd/opendnssec-1.3.4/signer/src/shared/util.c
Go to the documentation of this file.
00001 /*
00002  * $Id: util.c 4341 2011-01-31 15:21:09Z matthijs $
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 "shared/file.h"
00036 #include "shared/log.h"
00037 #include "shared/util.h"
00038 
00039 #include <time.h>
00040 #include <ldns/ldns.h>
00041 
00042 static const char* util_str = "util";
00043 
00044 
00049 int
00050 util_is_dnssec_rr(ldns_rr* rr)
00051 {
00052     ldns_rr_type type = 0;
00053 
00054     if (!rr) {
00055         return 0;
00056     }
00057 
00058     type = ldns_rr_get_type(rr);
00059     return (type == LDNS_RR_TYPE_RRSIG ||
00060             type == LDNS_RR_TYPE_NSEC ||
00061             type == LDNS_RR_TYPE_NSEC3 ||
00062             type == LDNS_RR_TYPE_NSEC3PARAMS);
00063 }
00064 
00065 
00070 int
00071 util_soa_compare_rdata(ldns_rr* rr1, ldns_rr* rr2)
00072 {
00073     size_t i = 0;
00074     size_t rdata_count = SE_SOA_RDATA_MINIMUM;
00075 
00076     for (i = 0; i <= rdata_count; i++) {
00077         if (i != SE_SOA_RDATA_SERIAL &&
00078             ldns_rdf_compare(ldns_rr_rdf(rr1, i), ldns_rr_rdf(rr2, i)) != 0) {
00079                 return 1;
00080         }
00081     }
00082     return 0;
00083 }
00084 
00085 
00090 int
00091 util_soa_compare(ldns_rr* rr1, ldns_rr* rr2)
00092 {
00093     size_t rr1_len = 0;
00094     size_t rr2_len = 0;
00095     size_t offset = 0;
00096 
00097     if (!rr1 || !rr2) {
00098         return 1;
00099     }
00100 
00101     rr1_len = ldns_rr_uncompressed_size(rr1);
00102     rr2_len = ldns_rr_uncompressed_size(rr2);
00103     if (ldns_dname_compare(ldns_rr_owner(rr1), ldns_rr_owner(rr2)) != 0) {
00104         return 1;
00105     }
00106     if (ldns_rr_get_class(rr1) != ldns_rr_get_class(rr2)) {
00107         return 1;
00108     }
00109     if (ldns_rr_get_type(rr1) != LDNS_RR_TYPE_SOA) {
00110         return 1;
00111     }
00112     if (ldns_rr_get_type(rr1) != ldns_rr_get_type(rr2)) {
00113         return 1;
00114     }
00115     if (offset > rr1_len || offset > rr2_len) {
00116         if (rr1_len == rr2_len) {
00117             return util_soa_compare_rdata(rr1, rr2);
00118         }
00119         return 1;
00120     }
00121 
00122     return util_soa_compare_rdata(rr1, rr2);
00123 }
00124 
00125 
00126 
00131 ldns_status
00132 util_dnssec_rrs_compare(ldns_rr* rr1, ldns_rr* rr2, int* cmp)
00133 {
00134     ldns_status status = LDNS_STATUS_OK;
00135     size_t rr1_len;
00136     size_t rr2_len;
00137     ldns_buffer* rr1_buf;
00138     ldns_buffer* rr2_buf;
00139 
00140     if (!rr1 || !rr2) {
00141         return LDNS_STATUS_ERR;
00142     }
00143 
00144     rr1_len = ldns_rr_uncompressed_size(rr1);
00145     rr2_len = ldns_rr_uncompressed_size(rr2);
00146     rr1_buf = ldns_buffer_new(rr1_len);
00147     rr2_buf = ldns_buffer_new(rr2_len);
00148 
00149     /* name, class and type should already be equal */
00150     status = ldns_rr2buffer_wire_canonical(rr1_buf, rr1, LDNS_SECTION_ANY);
00151     if (status != LDNS_STATUS_OK) {
00152         ldns_buffer_free(rr1_buf);
00153         ldns_buffer_free(rr2_buf);
00154         /* critical */
00155         return status;
00156     }
00157     status = ldns_rr2buffer_wire_canonical(rr2_buf, rr2, LDNS_SECTION_ANY);
00158     if (status != LDNS_STATUS_OK) {
00159         ldns_buffer_free(rr1_buf);
00160         ldns_buffer_free(rr2_buf);
00161         /* critical */
00162         return status;
00163     }
00164     *cmp = ldns_rr_compare_wire(rr1_buf, rr2_buf);
00165     ldns_buffer_free(rr1_buf);
00166     ldns_buffer_free(rr2_buf);
00167     return LDNS_STATUS_OK;
00168 }
00169 
00170 
00175 ldns_status
00176 util_dnssec_rrs_add_rr(ldns_dnssec_rrs *rrs, ldns_rr *rr)
00177 {
00178     int cmp = 0;
00179     ldns_dnssec_rrs *new_rrs = NULL;
00180     ldns_status status = LDNS_STATUS_OK;
00181     uint32_t rr_ttl = 0;
00182     uint32_t default_ttl = 0;
00183 
00184     if (!rrs || !rrs->rr || !rr) {
00185         return LDNS_STATUS_ERR;
00186     }
00187 
00188     rr_ttl = ldns_rr_ttl(rr);
00189     status = util_dnssec_rrs_compare(rrs->rr, rr, &cmp);
00190     if (status != LDNS_STATUS_OK) {
00191         /* critical */
00192         return status;
00193     }
00194 
00195     if (cmp < 0) {
00196         if (rrs->next) {
00197             return util_dnssec_rrs_add_rr(rrs->next, rr);
00198         } else {
00199             new_rrs = ldns_dnssec_rrs_new();
00200             new_rrs->rr = rr;
00201             rrs->next = new_rrs;
00202             default_ttl = ldns_rr_ttl(rrs->rr);
00203             if (rr_ttl < default_ttl) {
00204                 ldns_rr_set_ttl(rrs->rr, rr_ttl);
00205             } else {
00206                 ldns_rr_set_ttl(new_rrs->rr, default_ttl);
00207             }
00208             return LDNS_STATUS_OK;
00209         }
00210     } else if (cmp > 0) {
00211         /* put the current old rr in the new next, put the new
00212            rr in the current container */
00213         new_rrs = ldns_dnssec_rrs_new();
00214         new_rrs->rr = rrs->rr;
00215         new_rrs->next = rrs->next;
00216 
00217         rrs->rr = rr;
00218         rrs->next = new_rrs;
00219 
00220         default_ttl = ldns_rr_ttl(new_rrs->rr);
00221         if (rr_ttl < default_ttl) {
00222             ldns_rr_set_ttl(new_rrs->rr, rr_ttl);
00223         } else {
00224             ldns_rr_set_ttl(rrs->rr, default_ttl);
00225         }
00226 
00227         return LDNS_STATUS_OK;
00228     } else {
00229         /* should we error on equal? or free memory of rr */
00230         ods_log_warning("[%s] adding duplicate RR?", util_str);
00231         return LDNS_STATUS_NO_DATA;
00232     }
00233     return LDNS_STATUS_OK;
00234 }
00235 
00236 
00241 int
00242 util_write_pidfile(const char* pidfile, pid_t pid)
00243 {
00244     FILE* fd;
00245     char pidbuf[32];
00246     size_t result = 0, size = 0;
00247 
00248     ods_log_assert(pidfile);
00249     ods_log_assert(pid);
00250     ods_log_debug("[%s] writing pid %lu to pidfile %s", util_str,
00251         (unsigned long) pid, pidfile);
00252     snprintf(pidbuf, sizeof(pidbuf), "%lu\n", (unsigned long) pid);
00253     fd = ods_fopen(pidfile, NULL, "w");
00254     if (!fd) {
00255         return -1;
00256     }
00257     size = strlen(pidbuf);
00258     if (size == 0) {
00259         result = 1;
00260     } else {
00261         result = fwrite((const void*) pidbuf, 1, size, fd);
00262     }
00263     if (result == 0) {
00264         ods_log_error("[%s] write to pidfile %s failed: %s", util_str,
00265             pidfile, strerror(errno));
00266     } else if (result < size) {
00267         ods_log_error("[%s] short write to pidfile %s: disk full?", util_str,
00268             pidfile);
00269         result = 0;
00270     } else {
00271         result = 1;
00272     }
00273     ods_fclose(fd);
00274     if (!result) {
00275         return -1;
00276     }
00277     return 0;
00278 }