00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
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
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
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
00313 return;
00314 } else if (!z1) {
00315
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
00324 ret = zone_compare(z1, z2);
00325 if (ret < 0) {
00326
00327 z1->tobe_removed = 1;
00328 zl1->just_removed++;
00329 n1 = ldns_rbtree_next(n1);
00330 } else if (ret > 0) {
00331
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
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
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
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
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
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 }