1 /* 2 * dbaccess.c -- access methods for nsd(8) database 3 * 4 * Copyright (c) 2001-2006, NLnet Labs. All rights reserved. 5 * 6 * See LICENSE for the license. 7 * 8 */ 9 10 #include "config.h" 11 12 #include <sys/types.h> 13 #include <sys/stat.h> 14 15 #include <errno.h> 16 #include <stdlib.h> 17 #include <string.h> 18 #include <unistd.h> 19 #include <fcntl.h> 20 21 #include "dns.h" 22 #include "namedb.h" 23 #include "util.h" 24 #include "options.h" 25 #include "rdata.h" 26 #include "udb.h" 27 #include "udbradtree.h" 28 #include "udbzone.h" 29 #include "zonec.h" 30 #include "nsec3.h" 31 #include "difffile.h" 32 #include "nsd.h" 33 #include "ixfr.h" 34 #include "ixfrcreate.h" 35 36 static time_t udb_time = 0; 37 static unsigned long udb_rrsets = 0; 38 static unsigned long udb_rrset_count = 0; 39 40 void 41 namedb_close(struct namedb* db) 42 { 43 if(db) { 44 if(db->udb) { 45 udb_base_close(db->udb); 46 udb_base_free(db->udb); 47 db->udb = NULL; 48 } 49 zonec_desetup_parser(); 50 region_destroy(db->region); 51 } 52 } 53 54 void 55 namedb_close_udb(struct namedb* db) 56 { 57 if(db) { 58 /* we cannot actually munmap the data, because other 59 * processes still need to access the udb, so cleanup the 60 * udb */ 61 udb_base_free_keep_mmap(db->udb); 62 db->udb = NULL; 63 } 64 } 65 66 void 67 namedb_free_ixfr(struct namedb* db) 68 { 69 struct radnode* n; 70 for(n=radix_first(db->zonetree); n; n=radix_next(n)) { 71 zone_ixfr_free(((zone_type*)n->elem)->ixfr); 72 } 73 } 74 75 /** read rr */ 76 static void 77 read_rr(namedb_type* db, rr_type* rr, udb_ptr* urr, domain_type* domain) 78 { 79 buffer_type buffer; 80 ssize_t c; 81 assert(udb_ptr_get_type(urr) == udb_chunk_type_rr); 82 rr->owner = domain; 83 rr->type = RR(urr)->type; 84 rr->klass = RR(urr)->klass; 85 rr->ttl = RR(urr)->ttl; 86 87 buffer_create_from(&buffer, RR(urr)->wire, RR(urr)->len); 88 c = rdata_wireformat_to_rdata_atoms(db->region, db->domains, 89 rr->type, RR(urr)->len, &buffer, &rr->rdatas); 90 if(c == -1) { 91 /* safe on error */ 92 rr->rdata_count = 0; 93 rr->rdatas = NULL; 94 return; 95 } 96 rr->rdata_count = c; 97 } 98 99 /** calculate rr count */ 100 static uint16_t 101 calculate_rr_count(udb_base* udb, udb_ptr* rrset) 102 { 103 udb_ptr rr; 104 uint16_t num = 0; 105 udb_ptr_new(&rr, udb, &RRSET(rrset)->rrs); 106 while(rr.data) { 107 num++; 108 udb_ptr_set_rptr(&rr, udb, &RR(&rr)->next); 109 } 110 udb_ptr_unlink(&rr, udb); 111 return num; 112 } 113 114 /** read rrset */ 115 static void 116 read_rrset(udb_base* udb, namedb_type* db, zone_type* zone, 117 domain_type* domain, udb_ptr* urrset) 118 { 119 rrset_type* rrset; 120 udb_ptr urr; 121 unsigned i; 122 assert(udb_ptr_get_type(urrset) == udb_chunk_type_rrset); 123 /* if no RRs, do not create anything (robust) */ 124 if(RRSET(urrset)->rrs.data == 0) 125 return; 126 rrset = (rrset_type *) region_alloc(db->region, sizeof(rrset_type)); 127 rrset->zone = zone; 128 rrset->rr_count = calculate_rr_count(udb, urrset); 129 rrset->rrs = (rr_type *) region_alloc_array( 130 db->region, rrset->rr_count, sizeof(rr_type)); 131 /* add the RRs */ 132 udb_ptr_new(&urr, udb, &RRSET(urrset)->rrs); 133 for(i=0; i<rrset->rr_count; i++) { 134 read_rr(db, &rrset->rrs[i], &urr, domain); 135 udb_ptr_set_rptr(&urr, udb, &RR(&urr)->next); 136 } 137 udb_ptr_unlink(&urr, udb); 138 domain_add_rrset(domain, rrset); 139 if(domain == zone->apex) 140 apex_rrset_checks(db, rrset, domain); 141 } 142 143 /** read one elem from db, of type domain_d */ 144 static void read_node_elem(udb_base* udb, namedb_type* db, 145 region_type* dname_region, zone_type* zone, struct domain_d* d) 146 { 147 const dname_type* dname; 148 domain_type* domain; 149 udb_ptr urrset; 150 151 dname = dname_make(dname_region, d->name, 0); 152 if(!dname) return; 153 domain = domain_table_insert(db->domains, dname); 154 assert(domain); /* domain_table_insert should always return non-NULL */ 155 156 /* add rrsets */ 157 udb_ptr_init(&urrset, udb); 158 udb_ptr_set_rptr(&urrset, udb, &d->rrsets); 159 while(urrset.data) { 160 read_rrset(udb, db, zone, domain, &urrset); 161 udb_ptr_set_rptr(&urrset, udb, &RRSET(&urrset)->next); 162 163 if(++udb_rrsets % ZONEC_PCT_COUNT == 0 && time(NULL) > udb_time + ZONEC_PCT_TIME) { 164 udb_time = time(NULL); 165 VERBOSITY(1, (LOG_INFO, "read %s %d %%", 166 zone->opts->name, 167 (int)(udb_rrsets*((unsigned long)100)/udb_rrset_count))); 168 } 169 } 170 region_free_all(dname_region); 171 udb_ptr_unlink(&urrset, udb); 172 } 173 174 /** recurse read radix from disk. This radix tree is by domain name, so max of 175 * 256 depth, and thus the stack usage is small. */ 176 static void read_zone_recurse(udb_base* udb, namedb_type* db, 177 region_type* dname_region, zone_type* zone, struct udb_radnode_d* node) 178 { 179 if(node->elem.data) { 180 /* pre-order process of node->elem, for radix tree this is 181 * also in-order processing (identical to order tree_next()) */ 182 read_node_elem(udb, db, dname_region, zone, (struct domain_d*) 183 ((char*)udb->base + node->elem.data)); 184 } 185 if(node->lookup.data) { 186 uint16_t i; 187 struct udb_radarray_d* a = (struct udb_radarray_d*) 188 ((char*)udb->base + node->lookup.data); 189 /* we do not care for what the exact radix key is, we want 190 * to add all of them and the read routine does not need 191 * the radix-key, it has it stored */ 192 for(i=0; i<a->len; i++) { 193 if(a->array[i].node.data) { 194 read_zone_recurse(udb, db, dname_region, zone, 195 (struct udb_radnode_d*)((char*)udb->base + 196 a->array[i].node.data)); 197 } 198 } 199 } 200 } 201 202 /** read zone data */ 203 static void 204 read_zone_data(udb_base* udb, namedb_type* db, region_type* dname_region, 205 udb_ptr* z, zone_type* zone) 206 { 207 udb_ptr dtree; 208 /* recursively read domains, we only read so ptrs stay valid */ 209 udb_ptr_new(&dtree, udb, &ZONE(z)->domains); 210 if(RADTREE(&dtree)->root.data) 211 read_zone_recurse(udb, db, dname_region, zone, 212 (struct udb_radnode_d*) 213 ((char*)udb->base + RADTREE(&dtree)->root.data)); 214 udb_ptr_unlink(&dtree, udb); 215 } 216 217 /** create a zone */ 218 zone_type* 219 namedb_zone_create(namedb_type* db, const dname_type* dname, 220 struct zone_options* zo) 221 { 222 zone_type* zone = (zone_type *) region_alloc(db->region, 223 sizeof(zone_type)); 224 zone->node = radname_insert(db->zonetree, dname_name(dname), 225 dname->name_size, zone); 226 assert(zone->node); 227 zone->apex = domain_table_insert(db->domains, dname); 228 zone->apex->usage++; /* the zone.apex reference */ 229 zone->apex->is_apex = 1; 230 zone->soa_rrset = NULL; 231 zone->soa_nx_rrset = NULL; 232 zone->ns_rrset = NULL; 233 #ifdef NSEC3 234 zone->nsec3_param = NULL; 235 zone->nsec3_last = NULL; 236 zone->nsec3tree = NULL; 237 zone->hashtree = NULL; 238 zone->wchashtree = NULL; 239 zone->dshashtree = NULL; 240 #endif 241 zone->opts = zo; 242 zone->ixfr = NULL; 243 zone->filename = NULL; 244 zone->logstr = NULL; 245 zone->mtime.tv_sec = 0; 246 zone->mtime.tv_nsec = 0; 247 zone->zonestatid = 0; 248 zone->is_secure = 0; 249 zone->is_changed = 0; 250 zone->is_updated = 0; 251 zone->is_skipped = 0; 252 zone->is_checked = 0; 253 zone->is_bad = 0; 254 zone->is_ok = 1; 255 return zone; 256 } 257 258 void 259 namedb_zone_delete(namedb_type* db, zone_type* zone) 260 { 261 /* RRs and UDB and NSEC3 and so on must be already deleted */ 262 radix_delete(db->zonetree, zone->node); 263 264 /* see if apex can be deleted */ 265 if(zone->apex) { 266 zone->apex->usage --; 267 zone->apex->is_apex = 0; 268 if(zone->apex->usage == 0) { 269 /* delete the apex, possibly */ 270 domain_table_deldomain(db, zone->apex); 271 } 272 } 273 274 /* soa_rrset is freed when the SOA was deleted */ 275 if(zone->soa_nx_rrset) { 276 region_recycle(db->region, zone->soa_nx_rrset->rrs, 277 sizeof(rr_type)); 278 region_recycle(db->region, zone->soa_nx_rrset, 279 sizeof(rrset_type)); 280 } 281 #ifdef NSEC3 282 hash_tree_delete(db->region, zone->nsec3tree); 283 hash_tree_delete(db->region, zone->hashtree); 284 hash_tree_delete(db->region, zone->wchashtree); 285 hash_tree_delete(db->region, zone->dshashtree); 286 #endif 287 zone_ixfr_free(zone->ixfr); 288 if(zone->filename) 289 region_recycle(db->region, zone->filename, 290 strlen(zone->filename)+1); 291 if(zone->logstr) 292 region_recycle(db->region, zone->logstr, 293 strlen(zone->logstr)+1); 294 region_recycle(db->region, zone, sizeof(zone_type)); 295 } 296 297 #ifdef HAVE_MMAP 298 /** read a zone */ 299 static void 300 read_zone(udb_base* udb, namedb_type* db, struct nsd_options* opt, 301 region_type* dname_region, udb_ptr* z) 302 { 303 /* construct dname */ 304 const dname_type* dname = dname_make(dname_region, ZONE(z)->name, 0); 305 struct zone_options* zo = dname?zone_options_find(opt, dname):NULL; 306 zone_type* zone; 307 if(!dname) return; 308 if(!zo) { 309 /* deleted from the options, remove it from the nsd.db too */ 310 VERBOSITY(2, (LOG_WARNING, "zone %s is deleted", 311 dname_to_string(dname, NULL))); 312 udb_zone_delete(udb, z); 313 region_free_all(dname_region); 314 return; 315 } 316 assert(udb_ptr_get_type(z) == udb_chunk_type_zone); 317 udb_rrsets = 0; 318 udb_rrset_count = ZONE(z)->rrset_count; 319 zone = namedb_zone_create(db, dname, zo); 320 region_free_all(dname_region); 321 read_zone_data(udb, db, dname_region, z, zone); 322 zone->is_changed = (ZONE(z)->is_changed != 0); 323 #ifdef NSEC3 324 prehash_zone_complete(db, zone); 325 #endif 326 } 327 #endif /* HAVE_MMAP */ 328 329 #ifdef HAVE_MMAP 330 /** read zones from nsd.db */ 331 static void 332 read_zones(udb_base* udb, namedb_type* db, struct nsd_options* opt, 333 region_type* dname_region) 334 { 335 udb_ptr ztree, n, z; 336 udb_ptr_init(&z, udb); 337 udb_ptr_new(&ztree, udb, udb_base_get_userdata(udb)); 338 udb_radix_first(udb,&ztree,&n); 339 udb_time = time(NULL); 340 while(n.data) { 341 udb_ptr_set_rptr(&z, udb, &RADNODE(&n)->elem); 342 udb_radix_next(udb, &n); /* store in case n is deleted */ 343 read_zone(udb, db, opt, dname_region, &z); 344 udb_ptr_zero(&z, udb); 345 if(nsd.signal_hint_shutdown) break; 346 } 347 udb_ptr_unlink(&ztree, udb); 348 udb_ptr_unlink(&n, udb); 349 udb_ptr_unlink(&z, udb); 350 } 351 #endif /* HAVE_MMAP */ 352 353 #ifdef HAVE_MMAP 354 /** try to read the udb file or fail */ 355 static int 356 try_read_udb(namedb_type* db, int fd, const char* filename, 357 struct nsd_options* opt) 358 { 359 /* 360 * Temporary region used while loading domain names from the 361 * database. The region is freed after each time a dname is 362 * read from the database. 363 */ 364 region_type* dname_region; 365 366 assert(fd != -1); 367 if(!(db->udb=udb_base_create_fd(filename, fd, &namedb_walkfunc, 368 NULL))) { 369 /* fd is closed by failed udb create call */ 370 VERBOSITY(1, (LOG_ERR, "can not use %s, " 371 "will create anew", filename)); 372 return 0; 373 } 374 /* sanity check if can be opened */ 375 if(udb_base_get_userflags(db->udb) != 0) { 376 log_msg(LOG_ERR, "%s was not closed properly, it might " 377 "be corrupted, will create anew", filename); 378 udb_base_free(db->udb); 379 db->udb = NULL; 380 return 0; 381 } 382 /* read if it can be opened */ 383 dname_region = region_create(xalloc, free); 384 /* this operation does not fail, we end up with 385 * something, even if that is an empty namedb */ 386 read_zones(db->udb, db, opt, dname_region); 387 region_destroy(dname_region); 388 return 1; 389 } 390 #endif /* HAVE_MMAP */ 391 392 struct namedb * 393 namedb_open (const char* filename, struct nsd_options* opt) 394 { 395 namedb_type* db; 396 397 /* 398 * Region used to store the loaded database. The region is 399 * freed in namedb_close. 400 */ 401 region_type* db_region; 402 int fd; 403 404 #ifdef USE_MMAP_ALLOC 405 db_region = region_create_custom(mmap_alloc, mmap_free, MMAP_ALLOC_CHUNK_SIZE, 406 MMAP_ALLOC_LARGE_OBJECT_SIZE, MMAP_ALLOC_INITIAL_CLEANUP_SIZE, 1); 407 #else /* !USE_MMAP_ALLOC */ 408 db_region = region_create_custom(xalloc, free, DEFAULT_CHUNK_SIZE, 409 DEFAULT_LARGE_OBJECT_SIZE, DEFAULT_INITIAL_CLEANUP_SIZE, 1); 410 #endif /* !USE_MMAP_ALLOC */ 411 db = (namedb_type *) region_alloc(db_region, sizeof(struct namedb)); 412 db->region = db_region; 413 db->domains = domain_table_create(db->region); 414 db->zonetree = radix_tree_create(db->region); 415 db->diff_skip = 0; 416 db->diff_pos = 0; 417 zonec_setup_parser(db); 418 419 if (gettimeofday(&(db->diff_timestamp), NULL) != 0) { 420 log_msg(LOG_ERR, "unable to load %s: cannot initialize" 421 "timestamp", filename); 422 region_destroy(db_region); 423 return NULL; 424 } 425 426 /* in dbless mode there is no file to read or mmap */ 427 if(filename == NULL || filename[0] == 0) { 428 db->udb = NULL; 429 return db; 430 } 431 432 #ifndef HAVE_MMAP 433 /* no mmap() system call, use dbless mode */ 434 VERBOSITY(1, (LOG_INFO, "no mmap(), ignoring database %s", filename)); 435 db->udb = NULL; 436 (void)fd; (void)opt; 437 return db; 438 #else /* HAVE_MMAP */ 439 440 /* attempt to open, if does not exist, create a new one */ 441 fd = open(filename, O_RDWR); 442 if(fd == -1) { 443 if(errno != ENOENT) { 444 log_msg(LOG_ERR, "%s: %s", filename, strerror(errno)); 445 region_destroy(db_region); 446 return NULL; 447 } 448 } 449 /* attempt to read the file (if it exists) */ 450 if(fd != -1) { 451 if(!try_read_udb(db, fd, filename, opt)) 452 fd = -1; 453 } 454 /* attempt to create the file (if necessary or failed read) */ 455 if(fd == -1) { 456 if(!(db->udb=udb_base_create_new(filename, &namedb_walkfunc, 457 NULL))) { 458 region_destroy(db_region); 459 return NULL; 460 } 461 if(!udb_dns_init_file(db->udb)) { 462 region_destroy(db->region); 463 return NULL; 464 } 465 } 466 return db; 467 #endif /* HAVE_MMAP */ 468 } 469 470 /** get the file mtime stat (or nonexist or error) */ 471 int 472 file_get_mtime(const char* file, struct timespec* mtime, int* nonexist) 473 { 474 struct stat s; 475 if(stat(file, &s) != 0) { 476 mtime->tv_sec = 0; 477 mtime->tv_nsec = 0; 478 *nonexist = (errno == ENOENT); 479 return 0; 480 } 481 *nonexist = 0; 482 mtime->tv_sec = s.st_mtime; 483 #ifdef HAVE_STRUCT_STAT_ST_MTIMENSEC 484 mtime->tv_nsec = s.st_mtimensec; 485 #elif defined(HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC) 486 mtime->tv_nsec = s.st_mtim.tv_nsec; 487 #else 488 mtime->tv_nsec = 0; 489 #endif 490 return 1; 491 } 492 493 void 494 namedb_read_zonefile(struct nsd* nsd, struct zone* zone, udb_base* taskudb, 495 udb_ptr* last_task) 496 { 497 struct timespec mtime; 498 int nonexist = 0; 499 unsigned int errors; 500 const char* fname; 501 struct ixfr_create* ixfrcr = NULL; 502 int ixfr_create_already_done = 0; 503 if(!nsd->db || !zone || !zone->opts || !zone->opts->pattern->zonefile) 504 return; 505 mtime.tv_sec = 0; 506 mtime.tv_nsec = 0; 507 fname = config_make_zonefile(zone->opts, nsd); 508 assert(fname); 509 if(!file_get_mtime(fname, &mtime, &nonexist)) { 510 if(nonexist) { 511 if(zone_is_slave(zone->opts)) { 512 /* for slave zones not as bad, no zonefile 513 * may just mean we have to transfer it */ 514 VERBOSITY(2, (LOG_INFO, "zonefile %s does not exist", 515 fname)); 516 } else { 517 /* without a download option, we can never 518 * serve data, more severe error printout */ 519 log_msg(LOG_ERR, "zonefile %s does not exist", fname); 520 } 521 522 } else 523 log_msg(LOG_ERR, "zonefile %s: %s", 524 fname, strerror(errno)); 525 if(taskudb) task_new_soainfo(taskudb, last_task, zone, 0); 526 return; 527 } else { 528 const char* zone_fname = zone->filename; 529 struct timespec zone_mtime = zone->mtime; 530 if(nsd->db->udb) { 531 zone_fname = udb_zone_get_file_str(nsd->db->udb, 532 dname_name(domain_dname(zone->apex)), 533 domain_dname(zone->apex)->name_size); 534 udb_zone_get_mtime(nsd->db->udb, 535 dname_name(domain_dname(zone->apex)), 536 domain_dname(zone->apex)->name_size, 537 &zone_mtime); 538 } 539 /* if no zone_fname, then it was acquired in zone transfer, 540 * see if the file is newer than the zone transfer 541 * (regardless if this is a different file), because the 542 * zone transfer is a different content source too */ 543 if(!zone_fname && timespec_compare(&zone_mtime, &mtime) >= 0) { 544 VERBOSITY(3, (LOG_INFO, "zonefile %s is older than " 545 "zone transfer in memory", fname)); 546 return; 547 548 /* if zone_fname, then the file was acquired from reading it, 549 * and see if filename changed or mtime newer to read it */ 550 } else if(zone_fname && strcmp(zone_fname, fname) == 0 && 551 timespec_compare(&zone_mtime, &mtime) == 0) { 552 VERBOSITY(3, (LOG_INFO, "zonefile %s is not modified", 553 fname)); 554 return; 555 } 556 } 557 if(ixfr_create_from_difference(zone, fname, 558 &ixfr_create_already_done)) { 559 ixfrcr = ixfr_create_start(zone, fname, 560 zone->opts->pattern->ixfr_size, 0); 561 if(!ixfrcr) { 562 /* leaves the ixfrcr at NULL, so it is not created */ 563 log_msg(LOG_ERR, "out of memory starting ixfr create"); 564 } 565 } 566 567 assert(parser); 568 /* wipe zone from memory */ 569 #ifdef NSEC3 570 nsec3_clear_precompile(nsd->db, zone); 571 zone->nsec3_param = NULL; 572 #endif 573 delete_zone_rrs(nsd->db, zone); 574 errors = zonec_read(zone->opts->name, fname, zone); 575 if(errors > 0) { 576 log_msg(LOG_ERR, "zone %s file %s read with %u errors", 577 zone->opts->name, fname, errors); 578 /* wipe (partial) zone from memory */ 579 zone->is_ok = 1; 580 #ifdef NSEC3 581 nsec3_clear_precompile(nsd->db, zone); 582 zone->nsec3_param = NULL; 583 #endif 584 delete_zone_rrs(nsd->db, zone); 585 if(nsd->db->udb) { 586 region_type* dname_region; 587 udb_ptr z; 588 /* see if we can revert to the udb stored version */ 589 if(!udb_zone_search(nsd->db->udb, &z, dname_name(domain_dname( 590 zone->apex)), domain_dname(zone->apex)->name_size)) { 591 /* tell that zone contents has been lost */ 592 if(taskudb) task_new_soainfo(taskudb, last_task, zone, 0); 593 ixfr_create_cancel(ixfrcr); 594 return; 595 } 596 /* read from udb */ 597 dname_region = region_create(xalloc, free); 598 udb_rrsets = 0; 599 udb_rrset_count = ZONE(&z)->rrset_count; 600 udb_time = time(NULL); 601 read_zone_data(nsd->db->udb, nsd->db, dname_region, &z, zone); 602 region_destroy(dname_region); 603 udb_ptr_unlink(&z, nsd->db->udb); 604 } else { 605 if(zone->filename) 606 region_recycle(nsd->db->region, zone->filename, 607 strlen(zone->filename)+1); 608 zone->filename = NULL; 609 if(zone->logstr) 610 region_recycle(nsd->db->region, zone->logstr, 611 strlen(zone->logstr)+1); 612 zone->logstr = NULL; 613 } 614 } else { 615 VERBOSITY(1, (LOG_INFO, "zone %s read with success", 616 zone->opts->name)); 617 zone->is_ok = 1; 618 zone->is_changed = 0; 619 /* store zone into udb */ 620 if(nsd->db->udb) { 621 if(!write_zone_to_udb(nsd->db->udb, zone, &mtime, 622 fname)) { 623 log_msg(LOG_ERR, "failed to store zone in db"); 624 } else { 625 VERBOSITY(2, (LOG_INFO, "zone %s written to db", 626 zone->opts->name)); 627 } 628 } else { 629 zone->mtime = mtime; 630 if(zone->filename) 631 region_recycle(nsd->db->region, zone->filename, 632 strlen(zone->filename)+1); 633 zone->filename = region_strdup(nsd->db->region, fname); 634 if(zone->logstr) 635 region_recycle(nsd->db->region, zone->logstr, 636 strlen(zone->logstr)+1); 637 zone->logstr = NULL; 638 } 639 if(ixfr_create_already_done) { 640 ixfr_readup_exist(zone, nsd, fname); 641 } else if(ixfrcr) { 642 if(!ixfr_create_perform(ixfrcr, zone, 1, nsd, fname, 643 zone->opts->pattern->ixfr_number)) { 644 log_msg(LOG_ERR, "failed to create IXFR"); 645 } else { 646 VERBOSITY(2, (LOG_INFO, "zone %s created IXFR %s.ixfr", 647 zone->opts->name, fname)); 648 } 649 ixfr_create_free(ixfrcr); 650 } else if(zone_is_ixfr_enabled(zone)) { 651 ixfr_read_from_file(nsd, zone, fname); 652 } 653 } 654 if(taskudb) task_new_soainfo(taskudb, last_task, zone, 0); 655 #ifdef NSEC3 656 prehash_zone_complete(nsd->db, zone); 657 #endif 658 } 659 660 void namedb_check_zonefile(struct nsd* nsd, udb_base* taskudb, 661 udb_ptr* last_task, struct zone_options* zopt) 662 { 663 zone_type* zone; 664 const dname_type* dname = (const dname_type*)zopt->node.key; 665 /* find zone to go with it, or create it */ 666 zone = namedb_find_zone(nsd->db, dname); 667 if(!zone) { 668 zone = namedb_zone_create(nsd->db, dname, zopt); 669 } 670 namedb_read_zonefile(nsd, zone, taskudb, last_task); 671 } 672 673 void namedb_check_zonefiles(struct nsd* nsd, struct nsd_options* opt, 674 udb_base* taskudb, udb_ptr* last_task) 675 { 676 struct zone_options* zo; 677 /* check all zones in opt, create if not exist in main db */ 678 RBTREE_FOR(zo, struct zone_options*, opt->zone_options) { 679 namedb_check_zonefile(nsd, taskudb, last_task, zo); 680 if(nsd->signal_hint_shutdown) break; 681 } 682 } 683