• Main Page
  • Data Structures
  • Files
  • File List
  • Globals

/build/buildd-opendnssec_1.3.2-1~bpo60+1-kfreebsd-i386-KuwQV_/opendnssec-1.3.2/signer/src/signer/zonelist.c

Go to the documentation of this file.
00001 /*
00002  * $Id: zonelist.c 5292 2011-07-05 14:01:20Z 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 "parser/confparser.h"
00036 #include "parser/zonelistparser.h"
00037 #include "shared/allocator.h"
00038 #include "shared/duration.h"
00039 #include "shared/file.h"
00040 #include "shared/log.h"
00041 #include "shared/status.h"
00042 #include "signer/zone.h"
00043 #include "signer/zonelist.h"
00044 
00045 #include <ldns/ldns.h>
00046 #include <stdlib.h>
00047 
00048 static const char* zl_str = "zonelist";
00049 
00050 
00055 static int
00056 zone_compare(const void* a, const void* b)
00057 {
00058     zone_type* x = (zone_type*)a;
00059     zone_type* y = (zone_type*)b;
00060 
00061     ods_log_assert(x);
00062     ods_log_assert(y);
00063 
00064     if (x->klass != y->klass) {
00065         if (x->klass < y->klass) {
00066             return -1;
00067         }
00068         return 1;
00069     }
00070     return ldns_dname_compare(x->dname, y->dname);
00071 }
00072 
00073 
00078 zonelist_type*
00079 zonelist_create(allocator_type* allocator)
00080 {
00081     zonelist_type* zlist;
00082     if (!allocator) {
00083         ods_log_error("[%s] cannot create: no allocator available", zl_str);
00084         return NULL;
00085     }
00086     ods_log_assert(allocator);
00087 
00088     zlist = (zonelist_type*) allocator_alloc(allocator, sizeof(zonelist_type));
00089     if (!zlist) {
00090         ods_log_error("[%s] cannot create: allocator failed", zl_str);
00091         return NULL;
00092     }
00093     ods_log_assert(zlist);
00094 
00095     zlist->allocator = allocator;
00096     zlist->zones = ldns_rbtree_create(zone_compare);
00097     zlist->last_modified = 0;
00098     lock_basic_init(&zlist->zl_lock);
00099     return zlist;
00100 }
00101 
00102 
00107 static ods_status
00108 zonelist_read(zonelist_type* zl, const char* zlfile)
00109 {
00110     const char* rngfile = ODS_SE_RNGDIR "/zonelist.rng";
00111     ods_status status = ODS_STATUS_OK;
00112 
00113     ods_log_assert(zlfile);
00114     ods_log_verbose("[%s] read file %s", zl_str, zlfile);
00115 
00116     /* does the file have no parse errors? */
00117     status = parse_file_check(zlfile, rngfile);
00118     if (status != ODS_STATUS_OK) {
00119         ods_log_error("[%s] unable to parse file %s: %s", zl_str,
00120             zlfile, ods_status2str(status));
00121         return status;
00122     }
00123 
00124     /* ok, parse it */
00125     return parse_zonelist_zones((struct zonelist_struct*) zl, zlfile);
00126 }
00127 
00128 
00133 static ldns_rbnode_t*
00134 zone2node(zone_type* zone)
00135 {
00136     ldns_rbnode_t* node = (ldns_rbnode_t*) malloc(sizeof(ldns_rbnode_t));
00137     if (!node) {
00138         return NULL;
00139     }
00140     node->key = zone;
00141     node->data = zone;
00142     return node;
00143 }
00144 
00145 
00150 static zone_type*
00151 zonelist_lookup_zone(zonelist_type* zonelist, zone_type* zone)
00152 {
00153     ldns_rbnode_t* node = LDNS_RBTREE_NULL;
00154 
00155     if (!zonelist || !zonelist->zones) {
00156         ods_log_error("[%s] unable to lookup zone: no zonelist", zl_str);
00157         return NULL;
00158     }
00159     ods_log_assert(zonelist);
00160     ods_log_assert(zonelist->zones);
00161     if (!zone) {
00162         ods_log_error("[%s] unable to lookup zone: zone is null", zl_str);
00163         return NULL;
00164     }
00165     ods_log_assert(zone);
00166 
00167     node = ldns_rbtree_search(zonelist->zones, zone);
00168     if (node) {
00169         return (zone_type*) node->data;
00170     }
00171     return NULL;
00172 }
00173 
00174 
00179 zone_type*
00180 zonelist_lookup_zone_by_name(zonelist_type* zonelist, const char* name,
00181     ldns_rr_class klass)
00182 {
00183     zone_type* zone = NULL;
00184     zone_type* result = NULL;
00185 
00186     if (!zonelist || !zonelist->zones || !name || !klass) {
00187         return NULL;
00188     }
00189     ods_log_assert(zonelist);
00190     ods_log_assert(zonelist->zones);
00191     ods_log_assert(name);
00192     ods_log_assert(klass);
00193 
00194     zone = zone_create((char*) name, klass);
00195     if (!zone) {
00196         ods_log_error("[%s] unable to lookup zone: create zone failed", zl_str);
00197         return NULL;
00198     }
00199     result = zonelist_lookup_zone(zonelist, zone);
00200     zone_cleanup(zone);
00201     return result;
00202 }
00203 
00204 
00209 zone_type*
00210 zonelist_add_zone(zonelist_type* zlist, zone_type* zone)
00211 {
00212     ldns_rbnode_t* new_node = NULL;
00213 
00214     if (!zone) {
00215         ods_log_error("[%s] unable to add zone: zone is null", zl_str);
00216         return NULL;
00217     }
00218     ods_log_assert(zone);
00219     if (!zlist || !zlist->zones) {
00220         ods_log_error("[%s] unable to add zone %s: no zonelist", zl_str,
00221             zone->name);
00222         zone_cleanup(zone);
00223         return NULL;
00224     }
00225     ods_log_assert(zlist);
00226     ods_log_assert(zlist->zones);
00227 
00228     if (zonelist_lookup_zone(zlist, zone) != NULL) {
00229         ods_log_warning("[%s] unable to add zone %s: already present", zl_str,
00230             zone->name);
00231         zone_cleanup(zone);
00232         return NULL;
00233     }
00234 
00235     new_node = zone2node(zone);
00236     if (ldns_rbtree_insert(zlist->zones, new_node) == NULL) {
00237         ods_log_error("[%s] unable to add zone %s: rbtree insert failed",
00238             zl_str, zone->name);
00239         free((void*) new_node);
00240         zone_cleanup(zone);
00241         return NULL;
00242     }
00243     zone->just_added = 1;
00244     zlist->just_added++;
00245     return zone;
00246 }
00247 
00248 
00253 zone_type*
00254 zonelist_del_zone(zonelist_type* zlist, zone_type* zone)
00255 {
00256     ldns_rbnode_t* old_node = LDNS_RBTREE_NULL;
00257 
00258     if (!zone) {
00259         ods_log_warning("[%s] unable to delete zone: zone is null", zl_str);
00260         return NULL;
00261     }
00262     ods_log_assert(zone);
00263     if (!zlist || !zlist->zones) {
00264         ods_log_error("[%s] unable to delete zone %s: no zone list", zl_str,
00265             zone->name);
00266         return zone;
00267     }
00268     ods_log_assert(zlist);
00269     ods_log_assert(zlist->zones);
00270 
00271     old_node = ldns_rbtree_delete(zlist->zones, zone);
00272     if (!old_node) {
00273         ods_log_warning("[%s] unable to delete zone %s: not present", zl_str,
00274             zone->name);
00275         return zone;
00276     }
00277     free((void*) old_node);
00278     return zone;
00279 }
00280 
00281 
00286 static void
00287 zonelist_merge(zonelist_type* zl1, zonelist_type* zl2)
00288 {
00289     zone_type* z1 = NULL;
00290     zone_type* z2 = NULL;
00291     ldns_rbnode_t* n1 = LDNS_RBTREE_NULL;
00292     ldns_rbnode_t* n2 = LDNS_RBTREE_NULL;
00293     int ret = 0;
00294 
00295     ods_log_assert(zl1);
00296     ods_log_assert(zl2);
00297     ods_log_assert(zl1->zones);
00298     ods_log_assert(zl2->zones);
00299     ods_log_debug("[%s] merge two zone lists", zl_str);
00300 
00301     n1 = ldns_rbtree_first(zl1->zones);
00302     n2 = ldns_rbtree_first(zl2->zones);
00303     while (n2 && n2 != LDNS_RBTREE_NULL) {
00304         z2 = (zone_type*) n2->data;
00305         if (n1 && n1 != LDNS_RBTREE_NULL) {
00306             z1 = (zone_type*) n1->data;
00307         } else {
00308             z1 = NULL;
00309         }
00310 
00311         if (!z2) {
00312             /* no more zones to merge into zl1 */
00313             return;
00314         } else if (!z1) {
00315             /* just add remaining zones from zl2 */
00316             z2 = zonelist_add_zone(zl1, z2);
00317             if (!z2) {
00318                 ods_log_error("[%s] merge failed: z2 not added", zl_str);
00319                 return;
00320             }
00321             n2 = ldns_rbtree_next(n2);
00322         } else {
00323             /* compare the zones z1 and z2 */
00324             ret = zone_compare(z1, z2);
00325             if (ret < 0) {
00326                 /* remove zone z1, it is not present in the new list zl2 */
00327                 z1->tobe_removed = 1;
00328                 zl1->just_removed++;
00329                 n1 = ldns_rbtree_next(n1);
00330             } else if (ret > 0) {
00331                 /* add the new zone z2 */
00332                 z2 = zonelist_add_zone(zl1, z2);
00333                 if (!z2) {
00334                     ods_log_error("[%s] merge failed: z2 not added", zl_str);
00335                     return;
00336                 }
00337                 n2 = ldns_rbtree_next(n2);
00338             } else {
00339                 /* just update zone z1 */
00340                 n1 = ldns_rbtree_next(n1);
00341                 n2 = ldns_rbtree_next(n2);
00342                 zone_merge(z1, z2);
00343                 zone_cleanup(z2);
00344                 if (z1->just_updated) {
00345                     zl1->just_updated++;
00346                 }
00347                 z1->just_updated = 1;
00348             }
00349         }
00350     }
00351 
00352     /* remove remaining zones from z1 */
00353     while (n1 && n1 != LDNS_RBTREE_NULL) {
00354         z1 = (zone_type*) n1->data;
00355         z1->tobe_removed = 1;
00356         zl1->just_removed++;
00357         n1 = ldns_rbtree_next(n1);
00358     }
00359 
00360     zl1->last_modified = zl2->last_modified;
00361     return;
00362 }
00363 
00364 
00369 ods_status
00370 zonelist_update(zonelist_type* zl, const char* zlfile)
00371 {
00372     zonelist_type* new_zlist = NULL;
00373     allocator_type* tmp_alloc = NULL;
00374     time_t st_mtime = 0;
00375     ods_status status = ODS_STATUS_OK;
00376     char* datestamp = NULL;
00377     uint32_t ustamp = 0;
00378 
00379     ods_log_debug("[%s] update zone list", zl_str);
00380     if (!zl|| !zl->zones) {
00381         ods_log_error("[%s] cannot update: no zonelist storaga", zl_str);
00382         return ODS_STATUS_ASSERT_ERR;
00383     }
00384     ods_log_assert(zl);
00385     ods_log_assert(zl->zones);
00386     if (!zlfile) {
00387         ods_log_error("[%s] cannot update: no filename", zl_str);
00388         return ODS_STATUS_ASSERT_ERR;
00389     }
00390     ods_log_assert(zlfile);
00391 
00392     /* is the file updated? */
00393     st_mtime = ods_file_lastmodified(zlfile);
00394     if (st_mtime <= zl->last_modified) {
00395         ustamp = time_datestamp(zl->last_modified,
00396             "%Y-%m-%d %T", &datestamp);
00397         ods_log_debug("[%s] zonelist file %s is unchanged since %s",
00398             zl_str, zlfile, datestamp?datestamp:"Unknown");
00399         free((void*)datestamp);
00400         return ODS_STATUS_UNCHANGED;
00401     }
00402 
00403     /* create new zonelist */
00404     tmp_alloc = allocator_create(malloc, free);
00405     if (!tmp_alloc) {
00406         ods_log_error("[%s] error creating allocator for zone list",
00407             zl_str);
00408         return ODS_STATUS_ERR;
00409     }
00410     new_zlist = zonelist_create(tmp_alloc);
00411     if (!new_zlist) {
00412         ods_log_error("[%s] error creating new zone list", zl_str);
00413         allocator_cleanup(tmp_alloc);
00414         return ODS_STATUS_ERR;
00415     }
00416 
00417     /* read zonelist */
00418     status = zonelist_read(new_zlist, zlfile);
00419     if (status == ODS_STATUS_OK) {
00420         zl->just_removed = 0;
00421         zl->just_added = 0;
00422         zl->just_updated = 0;
00423         new_zlist->last_modified = st_mtime;
00424         zonelist_merge(zl, new_zlist);
00425         ustamp = time_datestamp(zl->last_modified, "%Y-%m-%d %T",
00426             &datestamp);
00427         ods_log_debug("[%s] file %s is modified since %s", zl_str, zlfile,
00428             datestamp?datestamp:"Unknown");
00429         free((void*)datestamp);
00430     } else {
00431         ods_log_error("[%s] unable to read file %s: %s", zl_str, zlfile,
00432             ods_status2str(status));
00433     }
00434 
00435     zonelist_free(new_zlist);
00436     allocator_cleanup(tmp_alloc);
00437     return status;
00438 }
00439 
00440 
00445 static void
00446 zone_delfunc(ldns_rbnode_t* elem)
00447 {
00448     zone_type* zone;
00449 
00450     if (elem && elem != LDNS_RBTREE_NULL) {
00451         zone = (zone_type*) elem->data;
00452         zone_delfunc(elem->left);
00453         zone_delfunc(elem->right);
00454 
00455         ods_log_debug("[%s] cleanup zone %s", zl_str, zone->name);
00456         zone_cleanup(zone);
00457         free((void*)elem);
00458     }
00459     return;
00460 }
00461 
00462 
00467 static void
00468 node_delfunc(ldns_rbnode_t* elem)
00469 {
00470     if (elem && elem != LDNS_RBTREE_NULL) {
00471         node_delfunc(elem->left);
00472         node_delfunc(elem->right);
00473         free((void*)elem);
00474     }
00475     return;
00476 }
00477 
00478 
00483 void
00484 zonelist_cleanup(zonelist_type* zl)
00485 {
00486     allocator_type* allocator;
00487     lock_basic_type zl_lock;
00488 
00489     if (!zl) {
00490         return;
00491     }
00492 
00493     ods_log_debug("[%s] cleanup zonelist", zl_str);
00494     if (zl->zones) {
00495         zone_delfunc(zl->zones->root);
00496         ldns_rbtree_free(zl->zones);
00497         zl->zones = NULL;
00498     }
00499 
00500     allocator = zl->allocator;
00501     zl_lock = zl->zl_lock;
00502 
00503     allocator_deallocate(allocator, (void*) zl);
00504     lock_basic_destroy(&zl_lock);
00505     return;
00506 }
00507 
00508 
00513 void
00514 zonelist_free(zonelist_type* zl)
00515 {
00516     allocator_type* allocator;
00517     lock_basic_type zl_lock;
00518 
00519     if (!zl) {
00520         return;
00521     }
00522 
00523     if (zl->zones) {
00524         node_delfunc(zl->zones->root);
00525         ldns_rbtree_free(zl->zones);
00526         zl->zones = NULL;
00527     }
00528 
00529     allocator = zl->allocator;
00530     zl_lock = zl->zl_lock;
00531 
00532     allocator_deallocate(allocator, (void*) zl);
00533     lock_basic_destroy(&zl_lock);
00534     return;
00535 }

Generated on Sun Dec 18 2011 10:32:16 for OpenDNSSEC-signer by  doxygen 1.7.1