OpenDNSSEC-signer 1.2.1
|
00001 /* 00002 * $Id: zonelist.c 4294 2011-01-13 19:58:29Z 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 "daemon/engine.h" 00036 #include "parser/confparser.h" 00037 #include "parser/zonelistparser.h" 00038 #include "scheduler/task.h" 00039 #include "signer/zone.h" 00040 #include "signer/zonelist.h" 00041 #include "util/file.h" 00042 #include "util/log.h" 00043 #include "util/se_malloc.h" 00044 00045 #include <ldns/ldns.h> /* ldns_dname_compare(), ldns_rbtree_*() */ 00046 00047 00052 static int 00053 zone_compare(const void* a, const void* b) 00054 { 00055 zone_type* x = (zone_type*)a; 00056 zone_type* y = (zone_type*)b; 00057 00058 se_log_assert(x); 00059 se_log_assert(y); 00060 00061 if (x->klass != y->klass) { 00062 if (x->klass < y->klass) { 00063 return -1; 00064 } 00065 return 1; 00066 } 00067 return ldns_dname_compare(x->dname, y->dname); 00068 } 00069 00070 00075 zonelist_type* 00076 zonelist_create(void) 00077 { 00078 zonelist_type* zlist = (zonelist_type*) se_malloc(sizeof(zonelist_type)); 00079 zlist->zones = ldns_rbtree_create(zone_compare); 00080 zlist->last_modified = 0; 00081 return zlist; 00082 } 00083 00084 00089 zonelist_type* 00090 zonelist_read(const char* zonelistfile, time_t last_modified) 00091 { 00092 zonelist_type* zlist = NULL; 00093 const char* rngfile = ODS_SE_RNGDIR "/zonelist.rng"; 00094 time_t st_mtime = 0; 00095 00096 se_log_assert(zonelistfile); 00097 se_log_verbose("read zone list file %s", 00098 zonelistfile?zonelistfile:"(null)"); 00099 00100 /* is the file updated? */ 00101 st_mtime = se_file_lastmodified(zonelistfile); 00102 if (st_mtime <= last_modified) { 00103 se_log_debug("zone list file %s is unchanged", 00104 zonelistfile?zonelistfile:"(null)"); 00105 return NULL; 00106 } 00107 /* does the file have no parse errors? */ 00108 if (parse_file_check(zonelistfile, rngfile) != 0) { 00109 se_log_error("unable to parse zone list file %s", 00110 zonelistfile?zonelistfile:"(null)"); 00111 return NULL; 00112 } 00113 /* ok, parse it! */ 00114 zlist = parse_zonelist_zones(zonelistfile); 00115 if (zlist) { 00116 zlist->last_modified = st_mtime; 00117 } else { 00118 se_log_error("unable to read zone list file %s", 00119 zonelistfile?zonelistfile:"(null)"); 00120 return NULL; 00121 } 00122 return zlist; 00123 } 00124 00125 00130 void 00131 zonelist_lock(zonelist_type* zonelist) 00132 { 00133 ldns_rbnode_t* node = LDNS_RBTREE_NULL; 00134 zone_type* zone = NULL; 00135 00136 se_log_assert(zonelist); 00137 se_log_assert(zonelist->zones); 00138 00139 node = ldns_rbtree_first(zonelist->zones); 00140 while (node && node != LDNS_RBTREE_NULL) { 00141 zone = (zone_type*) node->key; 00142 lock_basic_lock(&zone->zone_lock); 00143 node = ldns_rbtree_next(node); 00144 } 00145 return; 00146 } 00147 00152 void 00153 zonelist_unlock(zonelist_type* zonelist) 00154 { 00155 ldns_rbnode_t* node = LDNS_RBTREE_NULL; 00156 zone_type* zone = NULL; 00157 00158 se_log_assert(zonelist); 00159 se_log_assert(zonelist->zones); 00160 00161 node = ldns_rbtree_first(zonelist->zones); 00162 while (node && node != LDNS_RBTREE_NULL) { 00163 zone = (zone_type*) node->key; 00164 lock_basic_unlock(&zone->zone_lock); 00165 node = ldns_rbtree_next(node); 00166 } 00167 return; 00168 } 00169 00170 00175 static ldns_rbnode_t* 00176 zone2node(zone_type* zone) 00177 { 00178 ldns_rbnode_t* node = (ldns_rbnode_t*) se_malloc(sizeof(ldns_rbnode_t)); 00179 node->key = zone; 00180 node->data = zone; 00181 return node; 00182 } 00183 00184 00189 static zone_type* 00190 zonelist_lookup_zone(zonelist_type* zonelist, zone_type* zone) 00191 { 00192 ldns_rbnode_t* node = LDNS_RBTREE_NULL; 00193 00194 se_log_assert(zonelist); 00195 se_log_assert(zonelist->zones); 00196 se_log_assert(zone); 00197 00198 node = ldns_rbtree_search(zonelist->zones, zone); 00199 if (node) { 00200 return (zone_type*) node->key; 00201 } 00202 return NULL; 00203 } 00204 00205 00210 zone_type* 00211 zonelist_lookup_zone_by_name(zonelist_type* zonelist, const char* name) 00212 { 00213 ldns_rbnode_t* node = LDNS_RBTREE_NULL; 00214 zone_type* zone = NULL; 00215 00216 se_log_assert(zonelist); 00217 se_log_assert(zonelist->zones); 00218 se_log_assert(name); 00219 00220 if (zonelist->zones) { 00221 node = ldns_rbtree_first(zonelist->zones); 00222 } 00223 while (node != LDNS_RBTREE_NULL) { 00224 zone = (zone_type*) node->key; 00225 if (se_strcmp(zone->name, name) == 0) { 00226 return zone; 00227 } 00228 node = ldns_rbtree_next(node); 00229 } 00230 return NULL; 00231 } 00232 00233 00238 zone_type* 00239 zonelist_add_zone(zonelist_type* zonelist, zone_type* zone) 00240 { 00241 ldns_rbnode_t* new_node = NULL; 00242 00243 se_log_assert(zonelist); 00244 se_log_assert(zonelist->zones); 00245 se_log_assert(zone); 00246 00247 if (zonelist_lookup_zone(zonelist, zone) != NULL) { 00248 se_log_warning("unable to add zone %s: already present", 00249 zone->name?zone->name:"(null)"); 00250 zone_cleanup(zone); 00251 return NULL; 00252 } 00253 00254 new_node = zone2node(zone); 00255 if (ldns_rbtree_insert(zonelist->zones, new_node) == NULL) { 00256 se_log_error("unable to add zone %s: rbtree insert failed", 00257 zone->name?zone->name:"(null)"); 00258 zone_cleanup(zone); 00259 se_free((void*) new_node); 00260 return NULL; 00261 } 00262 zone->just_added = 1; 00263 return zone; 00264 } 00265 00266 00271 static zone_type* 00272 zonelist_delete_zone(zonelist_type* zonelist, zone_type* zone) 00273 { 00274 ldns_rbnode_t* old_node = LDNS_RBTREE_NULL; 00275 00276 se_log_assert(zonelist); 00277 se_log_assert(zonelist->zones); 00278 se_log_assert(zone); 00279 00280 old_node = ldns_rbtree_delete(zonelist->zones, zone); 00281 if (!old_node) { 00282 se_log_warning("unable to delete zone %s: not present", 00283 zone->name?zone->name:"(null)"); 00284 return zone; 00285 } 00286 00287 se_free((void*) old_node); 00288 zone_cleanup(zone); 00289 return NULL; 00290 } 00291 00292 00297 void 00298 zonelist_update(zonelist_type* zl, struct tasklist_struct* tl, 00299 const char* cmd, char* buf) 00300 { 00301 ldns_rbnode_t* node = LDNS_RBTREE_NULL; 00302 zone_type* zone = NULL; 00303 task_type* task = NULL; 00304 int just_removed = 0; 00305 int just_added = 0; 00306 int just_updated = 0; 00307 00308 se_log_debug("update zone list"); 00309 00310 node = ldns_rbtree_first(zl->zones); 00311 while (node && node != LDNS_RBTREE_NULL) { 00312 zone = (zone_type*) node->key; 00313 /* removed */ 00314 if (zone->tobe_removed) { 00315 if (zone->task) { 00316 /* remove task from queue */ 00317 task = tasklist_delete_task(tl, zone->task); 00318 task_cleanup(task); 00319 } 00320 node = ldns_rbtree_next(node); 00321 se_log_debug("delete zone %s from zone list", 00322 zone->name?zone->name:"(null)"); 00323 lock_basic_unlock(&zone->zone_lock); 00324 (void)zonelist_delete_zone(zl, zone); 00325 zone = NULL; 00326 just_removed++; 00327 continue; 00328 } 00329 /* added */ 00330 else if (zone->just_added) { 00331 zone->just_added = 0; 00332 if (cmd && !zone->notify_ns) { 00333 set_notify_ns(zone, cmd); 00334 } 00335 just_added++; 00336 } 00337 /* updated */ 00338 else if (zone->just_updated) { 00339 zone->just_updated = 0; 00340 just_updated++; 00341 } 00342 00343 node = ldns_rbtree_next(node); 00344 } 00345 00346 if (buf) { 00347 (void)snprintf(buf, ODS_SE_MAXLINE, "Zone list updated: " 00348 "%i removed, %i added, %i updated.\n", 00349 just_removed, just_added, just_updated); 00350 } 00351 return; 00352 } 00353 00354 00359 void 00360 zonelist_merge(zonelist_type* zl1, zonelist_type* zl2) 00361 { 00362 zone_type* z1 = NULL; 00363 zone_type* z2 = NULL; 00364 ldns_rbnode_t* n1 = LDNS_RBTREE_NULL; 00365 ldns_rbnode_t* n2 = LDNS_RBTREE_NULL; 00366 int ret = 0; 00367 00368 se_log_assert(zl1); 00369 se_log_assert(zl2); 00370 se_log_assert(zl1->zones); 00371 se_log_assert(zl2->zones); 00372 00373 n1 = ldns_rbtree_first(zl1->zones); 00374 n2 = ldns_rbtree_first(zl2->zones); 00375 while (n2 && n2 != LDNS_RBTREE_NULL) { 00376 z2 = (zone_type*) n2->key; 00377 if (n1 && n1 != LDNS_RBTREE_NULL) { 00378 z1 = (zone_type*) n1->key; 00379 } else { 00380 z1 = NULL; 00381 } 00382 00383 if (!z2) { 00384 /* no more zones to merge into zl1 */ 00385 return; 00386 } else if (!z1) { 00387 /* just add remaining zones from zl2 */ 00388 se_log_debug("add zone %s to zone list", 00389 z2->name?z2->name:"(null)"); 00390 z2 = zonelist_add_zone(zl1, z2); 00391 if (!z2) { 00392 se_log_error("zone list merge failed, z2 not added"); 00393 return; 00394 } 00395 lock_basic_lock(&z2->zone_lock); 00396 n2 = ldns_rbtree_next(n2); 00397 } else { 00398 /* compare the zones z1 and z2 */ 00399 ret = zone_compare(z1, z2); 00400 if (ret < 0) { 00401 /* remove zone z1, it is not present in the new zonelist zl2 */ 00402 z1->tobe_removed = 1; 00403 n1 = ldns_rbtree_next(n1); 00404 } else if (ret > 0) { 00405 /* add the new zone z2 */ 00406 se_log_debug("add zone %s to zone list", 00407 z2->name?z2->name:"(null)"); 00408 z2 = zonelist_add_zone(zl1, z2); 00409 if (!z2) { 00410 se_log_error("zone list merge failed, z2 not added"); 00411 return; 00412 } 00413 lock_basic_lock(&z2->zone_lock); 00414 n2 = ldns_rbtree_next(n2); 00415 } else { 00416 /* just update zone z1 */ 00417 n1 = ldns_rbtree_next(n1); 00418 n2 = ldns_rbtree_next(n2); 00419 zone_update_zonelist(z1, z2); 00420 } 00421 } 00422 } 00423 00424 /* remove remaining zones from z1 */ 00425 while (n1 && n1 != LDNS_RBTREE_NULL) { 00426 z1 = (zone_type*) n1->key; 00427 z1->tobe_removed = 1; 00428 n1 = ldns_rbtree_next(n1); 00429 } 00430 00431 zl1->last_modified = zl2->last_modified; 00432 if (zl2->zones) { 00433 se_rbnode_free(zl2->zones->root); 00434 ldns_rbtree_free(zl2->zones); 00435 } 00436 se_free((void*) zl2); 00437 return; 00438 } 00439 00440 00445 void 00446 zonelist_cleanup(zonelist_type* zonelist) 00447 { 00448 ldns_rbnode_t* node = LDNS_RBTREE_NULL; 00449 zone_type* zone = NULL; 00450 00451 if (zonelist) { 00452 if (zonelist->zones) { 00453 node = ldns_rbtree_first(zonelist->zones); 00454 while (node != LDNS_RBTREE_NULL) { 00455 zone = (zone_type*) node->key; 00456 zone_cleanup(zone); 00457 node = ldns_rbtree_next(node); 00458 } 00459 se_rbnode_free(zonelist->zones->root); 00460 ldns_rbtree_free(zonelist->zones); 00461 zonelist->zones = NULL; 00462 } 00463 se_free((void*) zonelist); 00464 } else { 00465 se_log_warning("cleanup empty zone list"); 00466 } 00467 }