1/* 2 * difffile.c - DIFF file handling source code. Read and write diff files. 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#include <assert.h> 12#include <string.h> 13#include <unistd.h> 14#include <stdlib.h> 15#include <errno.h> 16#include "difffile.h" 17#include "xfrd-disk.h" 18#include "util.h" 19#include "packet.h" 20#include "rdata.h" 21#include "udb.h" 22#include "nsec3.h" 23#include "nsd.h" 24#include "rrl.h" 25#include "ixfr.h" 26#include "zonec.h" 27#include "xfrd-catalog-zones.h" 28 29static int 30write_64(FILE *out, uint64_t val) 31{ 32 return write_data(out, &val, sizeof(val)); 33} 34 35static int 36write_32(FILE *out, uint32_t val) 37{ 38 val = htonl(val); 39 return write_data(out, &val, sizeof(val)); 40} 41 42static int 43write_8(FILE *out, uint8_t val) 44{ 45 return write_data(out, &val, sizeof(val)); 46} 47 48static int 49write_str(FILE *out, const char* str) 50{ 51 uint32_t len = strlen(str); 52 if(!write_32(out, len)) 53 return 0; 54 return write_data(out, str, len); 55} 56 57void 58diff_write_packet(const char* zone, const char* pat, uint32_t old_serial, 59 uint32_t new_serial, uint32_t seq_nr, uint8_t* data, size_t len, 60 struct nsd* nsd, uint64_t filenumber) 61{ 62 FILE* df = xfrd_open_xfrfile(nsd, filenumber, seq_nr?"a":"w"); 63 if(!df) { 64 log_msg(LOG_ERR, "could not open transfer %s file %lld: %s", 65 zone, (long long)filenumber, strerror(errno)); 66 return; 67 } 68 69 /* if first part, first write the header */ 70 if(seq_nr == 0) { 71 struct timeval tv; 72 if (gettimeofday(&tv, NULL) != 0) { 73 log_msg(LOG_ERR, "could not get timestamp for %s: %s", 74 zone, strerror(errno)); 75 } 76 if(!write_32(df, DIFF_PART_XFRF) || 77 !write_8(df, 0) /* notcommitted(yet) */ || 78 !write_32(df, 0) /* numberofparts when done */ || 79 !write_64(df, (uint64_t) tv.tv_sec) || 80 !write_32(df, (uint32_t) tv.tv_usec) || 81 !write_32(df, old_serial) || 82 !write_32(df, new_serial) || 83 !write_64(df, (uint64_t) tv.tv_sec) || 84 !write_32(df, (uint32_t) tv.tv_usec) || 85 !write_str(df, zone) || 86 !write_str(df, pat)) { 87 log_msg(LOG_ERR, "could not write transfer %s file %lld: %s", 88 zone, (long long)filenumber, strerror(errno)); 89 fclose(df); 90 return; 91 } 92 } 93 94 if(!write_32(df, DIFF_PART_XXFR) || 95 !write_32(df, len) || 96 !write_data(df, data, len) || 97 !write_32(df, len)) 98 { 99 log_msg(LOG_ERR, "could not write transfer %s file %lld: %s", 100 zone, (long long)filenumber, strerror(errno)); 101 } 102 fclose(df); 103} 104 105void 106diff_write_commit(const char* zone, uint32_t old_serial, uint32_t new_serial, 107 uint32_t num_parts, uint8_t commit, const char* log_str, 108 struct nsd* nsd, uint64_t filenumber) 109{ 110 struct timeval tv; 111 FILE* df; 112 113 if (gettimeofday(&tv, NULL) != 0) { 114 log_msg(LOG_ERR, "could not set timestamp for %s: %s", 115 zone, strerror(errno)); 116 } 117 118 /* overwrite the first part of the file with 'committed = 1', 119 * as well as the end_time and number of parts. 120 * also write old_serial and new_serial, so that a bad file mixup 121 * will result in unusable serial numbers. */ 122 123 df = xfrd_open_xfrfile(nsd, filenumber, "r+"); 124 if(!df) { 125 log_msg(LOG_ERR, "could not open transfer %s file %lld: %s", 126 zone, (long long)filenumber, strerror(errno)); 127 return; 128 } 129 if(!write_32(df, DIFF_PART_XFRF) || 130 !write_8(df, commit) /* committed */ || 131 !write_32(df, num_parts) || 132 !write_64(df, (uint64_t) tv.tv_sec) || 133 !write_32(df, (uint32_t) tv.tv_usec) || 134 !write_32(df, old_serial) || 135 !write_32(df, new_serial)) 136 { 137 log_msg(LOG_ERR, "could not write transfer %s file %lld: %s", 138 zone, (long long)filenumber, strerror(errno)); 139 fclose(df); 140 return; 141 } 142 143 /* append the log_str to the end of the file */ 144 if(fseek(df, 0, SEEK_END) == -1) { 145 log_msg(LOG_ERR, "could not fseek transfer %s file %lld: %s", 146 zone, (long long)filenumber, strerror(errno)); 147 fclose(df); 148 return; 149 } 150 if(!write_str(df, log_str)) { 151 log_msg(LOG_ERR, "could not write transfer %s file %lld: %s", 152 zone, (long long)filenumber, strerror(errno)); 153 fclose(df); 154 return; 155 156 } 157 fflush(df); 158 fclose(df); 159} 160 161void 162diff_update_commit( 163 const char* zone, uint8_t commit, struct nsd* nsd, uint64_t filenumber) 164{ 165 FILE *df; 166 167 assert(zone != NULL); 168 assert(nsd != NULL); 169 assert(commit == DIFF_NOT_COMMITTED || 170 commit == DIFF_COMMITTED || 171 commit == DIFF_CORRUPT || 172 commit == DIFF_INCONSISTENT || 173 commit == DIFF_VERIFIED); 174 175 df = xfrd_open_xfrfile(nsd, filenumber, "r+"); 176 if(!df) { 177 log_msg(LOG_ERR, "could not open transfer %s file %lld: %s", 178 zone, (long long)filenumber, strerror(errno)); 179 return; 180 } 181 if(!write_32(df, DIFF_PART_XFRF) || !write_8(df, commit)) { 182 log_msg(LOG_ERR, "could not write transfer %s file %lld: %s", 183 zone, (long long)filenumber, strerror(errno)); 184 fclose(df); 185 return; 186 } 187 fflush(df); 188 fclose(df); 189} 190 191int 192diff_read_64(FILE *in, uint64_t* result) 193{ 194 if (fread(result, sizeof(*result), 1, in) == 1) { 195 return 1; 196 } else { 197 return 0; 198 } 199} 200 201int 202diff_read_32(FILE *in, uint32_t* result) 203{ 204 if (fread(result, sizeof(*result), 1, in) == 1) { 205 *result = ntohl(*result); 206 return 1; 207 } else { 208 return 0; 209 } 210} 211 212int 213diff_read_8(FILE *in, uint8_t* result) 214{ 215 if (fread(result, sizeof(*result), 1, in) == 1) { 216 return 1; 217 } else { 218 return 0; 219 } 220} 221 222int 223diff_read_str(FILE* in, char* buf, size_t len) 224{ 225 uint32_t disklen; 226 if(!diff_read_32(in, &disklen)) 227 return 0; 228 if(disklen >= len) 229 return 0; 230 if(fread(buf, disklen, 1, in) != 1) 231 return 0; 232 buf[disklen] = 0; 233 return 1; 234} 235 236static void 237add_rdata_to_recyclebin(namedb_type* db, rr_type* rr) 238{ 239 /* add rdatas to recycle bin. */ 240 size_t i; 241 for(i=0; i<rr->rdata_count; i++) 242 { 243 if(!rdata_atom_is_domain(rr->type, i)) 244 region_recycle(db->region, rr->rdatas[i].data, 245 rdata_atom_size(rr->rdatas[i]) 246 + sizeof(uint16_t)); 247 } 248 region_recycle(db->region, rr->rdatas, 249 sizeof(rdata_atom_type)*rr->rdata_count); 250} 251 252/* this routine determines if below a domain there exist names with 253 * data (is_existing) or no names below the domain have data. 254 */ 255static int 256has_data_below(domain_type* top) 257{ 258 domain_type* d = top; 259 assert(d != NULL); 260 /* in the canonical ordering subdomains are after this name */ 261 d = domain_next(d); 262 while(d != NULL && domain_is_subdomain(d, top)) { 263 if(d->is_existing) 264 return 1; 265 d = domain_next(d); 266 } 267 return 0; 268} 269 270/** check if domain with 0 rrsets has become empty (nonexist) */ 271static domain_type* 272rrset_zero_nonexist_check(domain_type* domain, domain_type* ce) 273{ 274 /* is the node now an empty node (completely deleted) */ 275 if(domain->rrsets == 0) { 276 /* if there is no data below it, it becomes non existing. 277 also empty nonterminals above it become nonexisting */ 278 /* check for data below this node. */ 279 if(!has_data_below(domain)) { 280 /* nonexist this domain and all parent empty nonterminals */ 281 domain_type* p = domain; 282 while(p != NULL && p->rrsets == 0) { 283 if(p == ce || has_data_below(p)) 284 return p; 285 p->is_existing = 0; 286 /* fixup wildcard child of parent */ 287 if(p->parent && 288 p->parent->wildcard_child_closest_match == p) 289 p->parent->wildcard_child_closest_match = domain_previous_existing_child(p); 290 p = p->parent; 291 } 292 } 293 } 294 return NULL; 295} 296 297/** remove rrset. Adjusts zone params. Does not remove domain */ 298static void 299rrset_delete(namedb_type* db, domain_type* domain, rrset_type* rrset) 300{ 301 int i; 302 /* find previous */ 303 rrset_type** pp = &domain->rrsets; 304 while(*pp && *pp != rrset) { 305 pp = &( (*pp)->next ); 306 } 307 if(!*pp) { 308 /* rrset does not exist for domain */ 309 return; 310 } 311 *pp = rrset->next; 312 313 DEBUG(DEBUG_XFRD,2, (LOG_INFO, "delete rrset of %s type %s", 314 domain_to_string(domain), 315 rrtype_to_string(rrset_rrtype(rrset)))); 316 317 /* is this a SOA rrset ? */ 318 if(rrset->zone->soa_rrset == rrset) { 319 rrset->zone->soa_rrset = 0; 320 } 321 if(rrset->zone->ns_rrset == rrset) { 322 rrset->zone->ns_rrset = 0; 323 } 324 if(domain == rrset->zone->apex && rrset_rrtype(rrset) == TYPE_RRSIG) { 325 for (i = 0; i < rrset->rr_count; ++i) { 326 if(rr_rrsig_type_covered(&rrset->rrs[i])==TYPE_DNSKEY) { 327 rrset->zone->is_secure = 0; 328 break; 329 } 330 } 331 } 332 /* recycle the memory space of the rrset */ 333 for (i = 0; i < rrset->rr_count; ++i) 334 add_rdata_to_recyclebin(db, &rrset->rrs[i]); 335 region_recycle(db->region, rrset->rrs, 336 sizeof(rr_type) * rrset->rr_count); 337 rrset->rr_count = 0; 338 region_recycle(db->region, rrset, sizeof(rrset_type)); 339} 340 341static int 342rdatas_equal(rdata_atom_type *a, rdata_atom_type *b, int num, uint16_t type, 343 int* rdnum, char** reason) 344{ 345 int k, start, end; 346 start = 0; 347 end = num; 348 /** 349 * SOA RDATA comparisons in XFR are more lenient, 350 * only serial rdata is checked. 351 **/ 352 if (type == TYPE_SOA) { 353 start = 2; 354 end = 3; 355 } 356 for(k = start; k < end; k++) 357 { 358 if(rdata_atom_is_domain(type, k)) { 359 if(dname_compare(domain_dname(a[k].domain), 360 domain_dname(b[k].domain))!=0) { 361 *rdnum = k; 362 *reason = "dname data"; 363 return 0; 364 } 365 } else if(rdata_atom_is_literal_domain(type, k)) { 366 /* literal dname, but compare case insensitive */ 367 if(a[k].data[0] != b[k].data[0]) { 368 *rdnum = k; 369 *reason = "literal dname len"; 370 return 0; /* uncompressed len must be equal*/ 371 } 372 if(!dname_equal_nocase((uint8_t*)(a[k].data+1), 373 (uint8_t*)(b[k].data+1), a[k].data[0])) { 374 *rdnum = k; 375 *reason = "literal dname data"; 376 return 0; 377 } 378 } else { 379 /* check length */ 380 if(a[k].data[0] != b[k].data[0]) { 381 *rdnum = k; 382 *reason = "rdata len"; 383 return 0; 384 } 385 /* check data */ 386 if(memcmp(a[k].data+1, b[k].data+1, a[k].data[0])!=0) { 387 *rdnum = k; 388 *reason = "rdata data"; 389 return 0; 390 } 391 } 392 } 393 return 1; 394} 395 396static void 397debug_find_rr_num(rrset_type* rrset, uint16_t type, uint16_t klass, 398 rdata_atom_type *rdatas, ssize_t rdata_num) 399{ 400 int i, rd; 401 char* reason = ""; 402 403 for(i=0; i < rrset->rr_count; ++i) { 404 if (rrset->rrs[i].type != type) { 405 log_msg(LOG_WARNING, "diff: RR <%s, %s> does not match " 406 "RR num %d type %s", 407 dname_to_string(domain_dname(rrset->rrs[i].owner),0), 408 rrtype_to_string(type), i, 409 rrtype_to_string(rrset->rrs[i].type)); 410 } 411 if (rrset->rrs[i].klass != klass) { 412 log_msg(LOG_WARNING, "diff: RR <%s, %s> class %d " 413 "does not match RR num %d class %d", 414 dname_to_string(domain_dname(rrset->rrs[i].owner),0), 415 rrtype_to_string(type), 416 klass, i, 417 rrset->rrs[i].klass); 418 } 419 if (rrset->rrs[i].rdata_count != rdata_num) { 420 log_msg(LOG_WARNING, "diff: RR <%s, %s> rdlen %u " 421 "does not match RR num %d rdlen %d", 422 dname_to_string(domain_dname(rrset->rrs[i].owner),0), 423 rrtype_to_string(type), 424 (unsigned) rdata_num, i, 425 (unsigned) rrset->rrs[i].rdata_count); 426 } 427 if (!rdatas_equal(rdatas, rrset->rrs[i].rdatas, rdata_num, type, 428 &rd, &reason)) { 429 log_msg(LOG_WARNING, "diff: RR <%s, %s> rdata element " 430 "%d differs from RR num %d rdata (%s)", 431 dname_to_string(domain_dname(rrset->rrs[i].owner),0), 432 rrtype_to_string(type), 433 rd, i, reason); 434 } 435 } 436} 437 438static int 439find_rr_num(rrset_type* rrset, uint16_t type, uint16_t klass, 440 rdata_atom_type *rdatas, ssize_t rdata_num, int add) 441{ 442 int i, rd; 443 char* reason; 444 445 for(i=0; i < rrset->rr_count; ++i) { 446 if(rrset->rrs[i].type == type && 447 rrset->rrs[i].klass == klass && 448 rrset->rrs[i].rdata_count == rdata_num && 449 rdatas_equal(rdatas, rrset->rrs[i].rdatas, rdata_num, type, 450 &rd, &reason)) 451 { 452 return i; 453 } 454 } 455 /* this is odd. Log why rr cannot be found. */ 456 if (!add) { 457 debug_find_rr_num(rrset, type, klass, rdatas, rdata_num); 458 } 459 return -1; 460} 461 462#ifdef NSEC3 463/* see if nsec3 deletion triggers need action */ 464static void 465nsec3_delete_rr_trigger(namedb_type* db, rr_type* rr, zone_type* zone) 466{ 467 /* the RR has not actually been deleted yet, so we can inspect it */ 468 if(!zone->nsec3_param) 469 return; 470 /* see if the domain was an NSEC3-domain in the chain, but no longer */ 471 if(rr->type == TYPE_NSEC3 && rr->owner->nsec3 && 472 rr->owner->nsec3->nsec3_node.key && 473 nsec3_rr_uses_params(rr, zone) && 474 nsec3_in_chain_count(rr->owner, zone) <= 1) { 475 domain_type* prev = nsec3_chain_find_prev(zone, rr->owner); 476 /* remove from prehash because no longer an NSEC3 domain */ 477 if(domain_is_prehash(db->domains, rr->owner)) 478 prehash_del(db->domains, rr->owner); 479 /* fixup the last in the zone */ 480 if(rr->owner == zone->nsec3_last) 481 zone->nsec3_last = prev; 482 /* unlink from the nsec3tree */ 483 zone_del_domain_in_hash_tree(zone->nsec3tree, 484 &rr->owner->nsec3->nsec3_node); 485 /* add previous NSEC3 to the prehash list */ 486 if(prev && prev != rr->owner) 487 prehash_add(db->domains, prev); 488 else nsec3_clear_precompile(db, zone); 489 /* this domain becomes ordinary data domain: done later */ 490 } 491 /* see if the rr was NSEC3PARAM that we were using */ 492 else if(rr->type == TYPE_NSEC3PARAM && rr == zone->nsec3_param) { 493 /* clear trees, wipe hashes, wipe precompile */ 494 nsec3_clear_precompile(db, zone); 495 /* pick up new nsec3param (from udb, or avoid deleted rr) */ 496 nsec3_find_zone_param(db, zone, rr, 0); 497 /* if no more NSEC3, done */ 498 if(!zone->nsec3_param) 499 return; 500 nsec3_precompile_newparam(db, zone); 501 } 502} 503 504/* see if nsec3 prehash can be removed with new rrset content */ 505static void 506nsec3_rrsets_changed_remove_prehash(domain_type* domain, zone_type* zone) 507{ 508 /* deletion of rrset already done, we can check if conditions apply */ 509 /* see if the domain is no longer precompiled */ 510 /* it has a hash_node, but no longer fulfills conditions */ 511 if(nsec3_domain_part_of_zone(domain, zone) && domain->nsec3 && 512 domain->nsec3->hash_wc && 513 domain->nsec3->hash_wc->hash.node.key && 514 !nsec3_condition_hash(domain, zone)) { 515 /* remove precompile */ 516 domain->nsec3->nsec3_cover = NULL; 517 domain->nsec3->nsec3_wcard_child_cover = NULL; 518 domain->nsec3->nsec3_is_exact = 0; 519 /* remove it from the hash tree */ 520 zone_del_domain_in_hash_tree(zone->hashtree, 521 &domain->nsec3->hash_wc->hash.node); 522 zone_del_domain_in_hash_tree(zone->wchashtree, 523 &domain->nsec3->hash_wc->wc.node); 524 } 525 if(domain != zone->apex && domain->nsec3 && 526 domain->nsec3->ds_parent_hash && 527 domain->nsec3->ds_parent_hash->node.key && 528 (!domain->parent || nsec3_domain_part_of_zone(domain->parent, zone)) && 529 !nsec3_condition_dshash(domain, zone)) { 530 /* remove precompile */ 531 domain->nsec3->nsec3_ds_parent_cover = NULL; 532 domain->nsec3->nsec3_ds_parent_is_exact = 0; 533 /* remove it from the hash tree */ 534 zone_del_domain_in_hash_tree(zone->dshashtree, 535 &domain->nsec3->ds_parent_hash->node); 536 } 537} 538 539/* see if domain needs to get precompiled info */ 540static void 541nsec3_rrsets_changed_add_prehash(namedb_type* db, domain_type* domain, 542 zone_type* zone) 543{ 544 if(!zone->nsec3_param) 545 return; 546 if((!domain->nsec3 || !domain->nsec3->hash_wc 547 || !domain->nsec3->hash_wc->hash.node.key) 548 && nsec3_condition_hash(domain, zone)) { 549 region_type* tmpregion = region_create(xalloc, free); 550 nsec3_precompile_domain(db, domain, zone, tmpregion); 551 region_destroy(tmpregion); 552 } 553 if((!domain->nsec3 || !domain->nsec3->ds_parent_hash 554 || !domain->nsec3->ds_parent_hash->node.key) 555 && nsec3_condition_dshash(domain, zone)) { 556 nsec3_precompile_domain_ds(db, domain, zone); 557 } 558} 559 560/* see if nsec3 rrset-deletion triggers need action */ 561static void 562nsec3_delete_rrset_trigger(namedb_type* db, domain_type* domain, 563 zone_type* zone, uint16_t type) 564{ 565 if(!zone->nsec3_param) 566 return; 567 nsec3_rrsets_changed_remove_prehash(domain, zone); 568 /* for type nsec3, or a delegation, the domain may have become a 569 * 'normal' domain with its remaining data now */ 570 if(type == TYPE_NSEC3 || type == TYPE_NS || type == TYPE_DS) 571 nsec3_rrsets_changed_add_prehash(db, domain, zone); 572 /* for type DNAME or a delegation, obscured data may be revealed */ 573 if(type == TYPE_NS || type == TYPE_DS || type == TYPE_DNAME) { 574 /* walk over subdomains and check them each */ 575 domain_type *d; 576 for(d=domain_next(domain); d && domain_is_subdomain(d, domain); 577 d=domain_next(d)) { 578 nsec3_rrsets_changed_add_prehash(db, d, zone); 579 } 580 } 581} 582 583/* see if nsec3 addition triggers need action */ 584static void 585nsec3_add_rr_trigger(namedb_type* db, rr_type* rr, zone_type* zone) 586{ 587 /* the RR has been added in full, also to UDB (and thus NSEC3PARAM 588 * in the udb has been adjusted) */ 589 if(zone->nsec3_param && rr->type == TYPE_NSEC3 && 590 (!rr->owner->nsec3 || !rr->owner->nsec3->nsec3_node.key) 591 && nsec3_rr_uses_params(rr, zone)) { 592 if(!zone->nsec3_last) { 593 /* all nsec3s have previously been deleted, but 594 * we have nsec3 parameters, set it up again from 595 * being cleared. */ 596 nsec3_precompile_newparam(db, zone); 597 } 598 /* added NSEC3 into the chain */ 599 nsec3_precompile_nsec3rr(db, rr->owner, zone); 600 /* the domain has become an NSEC3-domain, if it was precompiled 601 * previously, remove that, neatly done in routine above */ 602 nsec3_rrsets_changed_remove_prehash(rr->owner, zone); 603 /* set this NSEC3 to prehash */ 604 prehash_add(db->domains, rr->owner); 605 } else if(!zone->nsec3_param && rr->type == TYPE_NSEC3PARAM) { 606 /* see if this means NSEC3 chain can be used */ 607 nsec3_find_zone_param(db, zone, NULL, 0); 608 if(!zone->nsec3_param) 609 return; 610 nsec3_zone_trees_create(db->region, zone); 611 nsec3_precompile_newparam(db, zone); 612 } 613} 614 615/* see if nsec3 rrset-addition triggers need action */ 616static void 617nsec3_add_rrset_trigger(namedb_type* db, domain_type* domain, zone_type* zone, 618 uint16_t type) 619{ 620 /* the rrset has been added so we can inspect it */ 621 if(!zone->nsec3_param) 622 return; 623 /* because the rrset is added we can check conditions easily. 624 * check if domain needs to become precompiled now */ 625 nsec3_rrsets_changed_add_prehash(db, domain, zone); 626 /* if a delegation, it changes from normal name to unhashed referral */ 627 if(type == TYPE_NS || type == TYPE_DS) { 628 nsec3_rrsets_changed_remove_prehash(domain, zone); 629 } 630 /* if delegation or DNAME added, then some RRs may get obscured */ 631 if(type == TYPE_NS || type == TYPE_DS || type == TYPE_DNAME) { 632 /* walk over subdomains and check them each */ 633 domain_type *d; 634 for(d=domain_next(domain); d && domain_is_subdomain(d, domain); 635 d=domain_next(d)) { 636 nsec3_rrsets_changed_remove_prehash(d, zone); 637 } 638 } 639} 640#endif /* NSEC3 */ 641 642/* fixup usage lower for domain names in the rdata */ 643static void 644rr_lower_usage(namedb_type* db, rr_type* rr) 645{ 646 unsigned i; 647 for(i=0; i<rr->rdata_count; i++) { 648 if(rdata_atom_is_domain(rr->type, i)) { 649 assert(rdata_atom_domain(rr->rdatas[i])->usage > 0); 650 rdata_atom_domain(rr->rdatas[i])->usage --; 651 if(rdata_atom_domain(rr->rdatas[i])->usage == 0) 652 domain_table_deldomain(db, 653 rdata_atom_domain(rr->rdatas[i])); 654 } 655 } 656} 657 658static void 659rrset_lower_usage(namedb_type* db, rrset_type* rrset) 660{ 661 unsigned i; 662 for(i=0; i<rrset->rr_count; i++) 663 rr_lower_usage(db, &rrset->rrs[i]); 664} 665 666int 667delete_RR(namedb_type* db, const dname_type* dname, 668 uint16_t type, uint16_t klass, 669 buffer_type* packet, size_t rdatalen, zone_type *zone, 670 region_type* temp_region, int* softfail) 671{ 672 domain_type *domain; 673 rrset_type *rrset; 674 domain = domain_table_find(db->domains, dname); 675 if(!domain) { 676 log_msg(LOG_WARNING, "diff: domain %s does not exist", 677 dname_to_string(dname,0)); 678 buffer_skip(packet, rdatalen); 679 *softfail = 1; 680 return 1; /* not fatal error */ 681 } 682 rrset = domain_find_rrset(domain, zone, type); 683 if(!rrset) { 684 log_msg(LOG_WARNING, "diff: rrset %s does not exist", 685 dname_to_string(dname,0)); 686 buffer_skip(packet, rdatalen); 687 *softfail = 1; 688 return 1; /* not fatal error */ 689 } else { 690 /* find the RR in the rrset */ 691 domain_table_type *temptable; 692 rdata_atom_type *rdatas; 693 ssize_t rdata_num; 694 int rrnum; 695 temptable = domain_table_create(temp_region); 696 /* This will ensure that the dnames in rdata are 697 * normalized, conform RFC 4035, section 6.2 698 */ 699 rdata_num = rdata_wireformat_to_rdata_atoms( 700 temp_region, temptable, type, rdatalen, packet, &rdatas); 701 if(rdata_num == -1) { 702 log_msg(LOG_ERR, "diff: bad rdata for %s", 703 dname_to_string(dname,0)); 704 return 0; 705 } 706 rrnum = find_rr_num(rrset, type, klass, rdatas, rdata_num, 0); 707 if(rrnum == -1 && type == TYPE_SOA && domain == zone->apex 708 && rrset->rr_count != 0) 709 rrnum = 0; /* replace existing SOA if no match */ 710 if(rrnum == -1) { 711 log_msg(LOG_WARNING, "diff: RR <%s, %s> does not exist", 712 dname_to_string(dname,0), rrtype_to_string(type)); 713 *softfail = 1; 714 return 1; /* not fatal error */ 715 } 716#ifdef NSEC3 717 /* process triggers for RR deletions */ 718 nsec3_delete_rr_trigger(db, &rrset->rrs[rrnum], zone); 719#endif 720 /* lower usage (possibly deleting other domains, and thus 721 * invalidating the current RR's domain pointers) */ 722 rr_lower_usage(db, &rrset->rrs[rrnum]); 723 if(rrset->rr_count == 1) { 724 /* delete entire rrset */ 725 rrset_delete(db, domain, rrset); 726 /* check if domain is now nonexisting (or parents) */ 727 rrset_zero_nonexist_check(domain, NULL); 728#ifdef NSEC3 729 /* cleanup nsec3 */ 730 nsec3_delete_rrset_trigger(db, domain, zone, type); 731#endif 732 /* see if the domain can be deleted (and inspect parents) */ 733 domain_table_deldomain(db, domain); 734 } else { 735 /* swap out the bad RR and decrease the count */ 736 rr_type* rrs_orig = rrset->rrs; 737 add_rdata_to_recyclebin(db, &rrset->rrs[rrnum]); 738 if(rrnum < rrset->rr_count-1) 739 rrset->rrs[rrnum] = rrset->rrs[rrset->rr_count-1]; 740 memset(&rrset->rrs[rrset->rr_count-1], 0, sizeof(rr_type)); 741 /* realloc the rrs array one smaller */ 742 rrset->rrs = region_alloc_array_init(db->region, rrs_orig, 743 (rrset->rr_count-1), sizeof(rr_type)); 744 if(!rrset->rrs) { 745 log_msg(LOG_ERR, "out of memory, %s:%d", __FILE__, __LINE__); 746 exit(1); 747 } 748 region_recycle(db->region, rrs_orig, 749 sizeof(rr_type) * rrset->rr_count); 750#ifdef NSEC3 751 if(type == TYPE_NSEC3PARAM && zone->nsec3_param) { 752 /* fixup nsec3_param pointer to same RR */ 753 assert(zone->nsec3_param >= rrs_orig && 754 zone->nsec3_param <= 755 rrs_orig+rrset->rr_count); 756 /* last moved to rrnum, others at same index*/ 757 if(zone->nsec3_param == &rrs_orig[ 758 rrset->rr_count-1]) 759 zone->nsec3_param = &rrset->rrs[rrnum]; 760 else 761 zone->nsec3_param = 762 (void*)zone->nsec3_param 763 -(void*)rrs_orig + 764 (void*)rrset->rrs; 765 } 766#endif /* NSEC3 */ 767 rrset->rr_count --; 768#ifdef NSEC3 769 /* for type nsec3, the domain may have become a 770 * 'normal' domain with its remaining data now */ 771 if(type == TYPE_NSEC3) 772 nsec3_rrsets_changed_add_prehash(db, domain, 773 zone); 774#endif /* NSEC3 */ 775 } 776 } 777 return 1; 778} 779 780int 781add_RR(namedb_type* db, const dname_type* dname, 782 uint16_t type, uint16_t klass, uint32_t ttl, 783 buffer_type* packet, size_t rdatalen, zone_type *zone, 784 int* softfail) 785{ 786 domain_type* domain; 787 rrset_type* rrset; 788 rdata_atom_type *rdatas; 789 rr_type *rrs_old; 790 ssize_t rdata_num; 791 int rrnum; 792#ifdef NSEC3 793 int rrset_added = 0; 794#endif 795 domain = domain_table_find(db->domains, dname); 796 if(!domain) { 797 /* create the domain */ 798 domain = domain_table_insert(db->domains, dname); 799 } 800 rrset = domain_find_rrset(domain, zone, type); 801 if(!rrset) { 802 /* create the rrset */ 803 rrset = region_alloc(db->region, sizeof(rrset_type)); 804 if(!rrset) { 805 log_msg(LOG_ERR, "out of memory, %s:%d", __FILE__, __LINE__); 806 exit(1); 807 } 808 rrset->zone = zone; 809 rrset->rrs = 0; 810 rrset->rr_count = 0; 811 domain_add_rrset(domain, rrset); 812#ifdef NSEC3 813 rrset_added = 1; 814#endif 815 } 816 817 /* dnames in rdata are normalized, conform RFC 4035, 818 * Section 6.2 819 */ 820 rdata_num = rdata_wireformat_to_rdata_atoms( 821 db->region, db->domains, type, rdatalen, packet, &rdatas); 822 if(rdata_num == -1) { 823 log_msg(LOG_ERR, "diff: bad rdata for %s", 824 dname_to_string(dname,0)); 825 return 0; 826 } 827 rrnum = find_rr_num(rrset, type, klass, rdatas, rdata_num, 1); 828 if(rrnum != -1) { 829 DEBUG(DEBUG_XFRD, 2, (LOG_ERR, "diff: RR <%s, %s> already exists", 830 dname_to_string(dname,0), rrtype_to_string(type))); 831 /* ignore already existing RR: lenient accepting of messages */ 832 *softfail = 1; 833 return 1; 834 } 835 if(rrset->rr_count == 65535) { 836 log_msg(LOG_ERR, "diff: too many RRs at %s", 837 dname_to_string(dname,0)); 838 return 0; 839 } 840 841 /* re-alloc the rrs and add the new */ 842 rrs_old = rrset->rrs; 843 rrset->rrs = region_alloc_array(db->region, 844 (rrset->rr_count+1), sizeof(rr_type)); 845 if(!rrset->rrs) { 846 log_msg(LOG_ERR, "out of memory, %s:%d", __FILE__, __LINE__); 847 exit(1); 848 } 849 if(rrs_old) 850 memcpy(rrset->rrs, rrs_old, rrset->rr_count * sizeof(rr_type)); 851 region_recycle(db->region, rrs_old, sizeof(rr_type) * rrset->rr_count); 852 rrset->rr_count ++; 853 854 rrset->rrs[rrset->rr_count - 1].owner = domain; 855 rrset->rrs[rrset->rr_count - 1].rdatas = rdatas; 856 rrset->rrs[rrset->rr_count - 1].ttl = ttl; 857 rrset->rrs[rrset->rr_count - 1].type = type; 858 rrset->rrs[rrset->rr_count - 1].klass = klass; 859 rrset->rrs[rrset->rr_count - 1].rdata_count = rdata_num; 860 861 /* see if it is a SOA */ 862 if(domain == zone->apex) { 863 apex_rrset_checks(db, rrset, domain); 864#ifdef NSEC3 865 if(type == TYPE_NSEC3PARAM && zone->nsec3_param) { 866 /* the pointer just changed, fix it up to point 867 * to the same record */ 868 assert(zone->nsec3_param >= rrs_old && 869 zone->nsec3_param < rrs_old+rrset->rr_count); 870 /* in this order to make sure no overflow/underflow*/ 871 zone->nsec3_param = (void*)zone->nsec3_param - 872 (void*)rrs_old + (void*)rrset->rrs; 873 } 874#endif /* NSEC3 */ 875 } 876 877#ifdef NSEC3 878 if(rrset_added) { 879 domain_type* p = domain->parent; 880 nsec3_add_rrset_trigger(db, domain, zone, type); 881 /* go up and process (possibly created) empty nonterminals, 882 * until we hit the apex or root */ 883 while(p && p->rrsets == NULL && !p->is_apex) { 884 nsec3_rrsets_changed_add_prehash(db, p, zone); 885 p = p->parent; 886 } 887 } 888 nsec3_add_rr_trigger(db, &rrset->rrs[rrset->rr_count - 1], zone); 889#endif /* NSEC3 */ 890 return 1; 891} 892 893static zone_type* 894find_or_create_zone(namedb_type* db, const dname_type* zone_name, 895 struct nsd_options* opt, const char* zstr, const char* patname) 896{ 897 zone_type* zone; 898 struct zone_options* zopt; 899 zone = namedb_find_zone(db, zone_name); 900 if(zone) { 901 return zone; 902 } 903 zopt = zone_options_find(opt, zone_name); 904 if(!zopt) { 905 /* if _implicit_ then insert as _part_of_config */ 906 if(strncmp(patname, PATTERN_IMPLICIT_MARKER, 907 strlen(PATTERN_IMPLICIT_MARKER)) == 0) { 908 zopt = zone_options_create(opt->region); 909 if(!zopt) return 0; 910 zopt->part_of_config = 1; 911 zopt->name = region_strdup(opt->region, zstr); 912 zopt->pattern = pattern_options_find(opt, patname); 913 if(!zopt->name || !zopt->pattern) return 0; 914 if(!nsd_options_insert_zone(opt, zopt)) { 915 log_msg(LOG_ERR, "bad domain name or duplicate zone '%s' " 916 "pattern %s", zstr, patname); 917 } 918 } else { 919 /* create zone : presumably already added to zonelist 920 * by xfrd, who wrote the AXFR or IXFR to disk, so we only 921 * need to add it to our config. 922 * This process does not need linesize and offset zonelist */ 923 zopt = zone_list_zone_insert(opt, zstr, patname); 924 if(!zopt) 925 return 0; 926 } 927 } 928 zone = namedb_zone_create(db, zone_name, zopt); 929 return zone; 930} 931 932void 933delete_zone_rrs(namedb_type* db, zone_type* zone) 934{ 935 rrset_type *rrset; 936 domain_type *domain = zone->apex, *next; 937 int nonexist_check = 0; 938 /* go through entire tree below the zone apex (incl subzones) */ 939 while(domain && domain_is_subdomain(domain, zone->apex)) 940 { 941 DEBUG(DEBUG_XFRD,2, (LOG_INFO, "delete zone visit %s", 942 domain_to_string(domain))); 943 /* delete all rrsets of the zone */ 944 while((rrset = domain_find_any_rrset(domain, zone))) { 945 /* lower usage can delete other domains */ 946 rrset_lower_usage(db, rrset); 947 /* rrset del does not delete our domain(yet) */ 948 rrset_delete(db, domain, rrset); 949 /* no rrset_zero_nonexist_check, do that later */ 950 if(domain->rrsets == 0) 951 nonexist_check = 1; 952 } 953 /* the delete upcoming could delete parents, but nothing next 954 * or after the domain so store next ptr */ 955 next = domain_next(domain); 956 /* see if the domain can be deleted (and inspect parents) */ 957 domain_table_deldomain(db, domain); 958 domain = next; 959 } 960 961 /* check if data deletions have created nonexisting domain entries, 962 * but after deleting domains so the checks are faster */ 963 if(nonexist_check) { 964 domain_type* ce = NULL; /* for speeding up has_data_below */ 965 DEBUG(DEBUG_XFRD, 1, (LOG_INFO, "axfrdel: zero rrset check")); 966 domain = zone->apex; 967 while(domain && domain_is_subdomain(domain, zone->apex)) 968 { 969 /* the interesting domains should be existing==1 970 * and rrsets==0, speeding up out processing of 971 * sub-zones, since we only spuriously check empty 972 * nonterminals */ 973 if(domain->is_existing) 974 ce = rrset_zero_nonexist_check(domain, ce); 975 domain = domain_next(domain); 976 } 977 } 978 979 DEBUG(DEBUG_XFRD, 1, (LOG_INFO, "axfrdel: recyclebin holds %lu bytes", 980 (unsigned long) region_get_recycle_size(db->region))); 981#ifndef NDEBUG 982 if(nsd_debug_level >= 2) 983 region_log_stats(db->region); 984#endif 985 986 assert(zone->soa_rrset == 0); 987 /* keep zone->soa_nx_rrset alloced: it is reused */ 988 assert(zone->ns_rrset == 0); 989 assert(zone->is_secure == 0); 990} 991 992/* return value 0: syntaxerror,badIXFR, 1:OK, 2:done_and_skip_it */ 993static int 994apply_ixfr(nsd_type* nsd, FILE *in, uint32_t serialno, 995 uint32_t seq_nr, uint32_t seq_total, 996 int* is_axfr, int* delete_mode, int* rr_count, 997 struct zone* zone, int* bytes, 998 int* softfail, struct ixfr_store* ixfr_store) 999{ 1000 uint32_t msglen, checklen, pkttype; 1001 int qcount, ancount; 1002 buffer_type* packet; 1003 region_type* region; 1004 1005 /* note that errors could not really happen due to format of the 1006 * packet since xfrd has checked all dnames and RRs before commit, 1007 * this is why the errors are fatal (exit process), it must be 1008 * something internal or a bad disk or something. */ 1009 1010 /* read ixfr packet RRs and apply to in memory db */ 1011 if(!diff_read_32(in, &pkttype) || pkttype != DIFF_PART_XXFR) { 1012 log_msg(LOG_ERR, "could not read type or wrong type"); 1013 return 0; 1014 } 1015 1016 if(!diff_read_32(in, &msglen)) { 1017 log_msg(LOG_ERR, "could not read len"); 1018 return 0; 1019 } 1020 1021 if(msglen < QHEADERSZ) { 1022 log_msg(LOG_ERR, "msg too short"); 1023 return 0; 1024 } 1025 1026 region = region_create(xalloc, free); 1027 if(!region) { 1028 log_msg(LOG_ERR, "out of memory"); 1029 return 0; 1030 } 1031 packet = buffer_create(region, QIOBUFSZ); 1032 if(msglen > QIOBUFSZ) { 1033 log_msg(LOG_ERR, "msg too long"); 1034 region_destroy(region); 1035 return 0; 1036 } 1037 buffer_clear(packet); 1038 if(fread(buffer_begin(packet), msglen, 1, in) != 1) { 1039 log_msg(LOG_ERR, "short fread: %s", strerror(errno)); 1040 region_destroy(region); 1041 return 0; 1042 } 1043 buffer_set_limit(packet, msglen); 1044 1045 /* see if check on data fails: checks that we are not reading 1046 * random garbage */ 1047 if(!diff_read_32(in, &checklen) || checklen != msglen) { 1048 log_msg(LOG_ERR, "transfer part has incorrect checkvalue"); 1049 return 0; 1050 } 1051 *bytes += msglen; 1052 1053 /* only answer section is really used, question, additional and 1054 authority section RRs are skipped */ 1055 qcount = QDCOUNT(packet); 1056 ancount = ANCOUNT(packet); 1057 buffer_skip(packet, QHEADERSZ); 1058 /* qcount should be 0 or 1 really, ancount limited by 64k packet */ 1059 if(qcount > 64 || ancount > 65530) { 1060 log_msg(LOG_ERR, "RR count impossibly high"); 1061 region_destroy(region); 1062 return 0; 1063 } 1064 1065 /* skip queries */ 1066 for(int i=0; i < qcount; ++i) { 1067 if(!packet_skip_rr(packet, 1)) { 1068 log_msg(LOG_ERR, "bad RR in question section"); 1069 region_destroy(region); 1070 return 0; 1071 } 1072 } 1073 1074 DEBUG(DEBUG_XFRD, 2, (LOG_INFO, "diff: started packet for zone %s", 1075 domain_to_string(zone->apex))); 1076 1077 for(int i=0; i < ancount; ++i, ++(*rr_count)) { 1078 const dname_type *owner; 1079 uint16_t type, klass, rrlen; 1080 uint32_t ttl; 1081 1082 owner = dname_make_from_packet(region, packet, 1, 1); 1083 if(!owner) { 1084 log_msg(LOG_ERR, "bad xfr RR dname %d", *rr_count); 1085 region_destroy(region); 1086 return 0; 1087 } 1088 if(!buffer_available(packet, 10)) { 1089 log_msg(LOG_ERR, "bad xfr RR format %d", *rr_count); 1090 region_destroy(region); 1091 return 0; 1092 } 1093 type = buffer_read_u16(packet); 1094 klass = buffer_read_u16(packet); 1095 ttl = buffer_read_u32(packet); 1096 rrlen = buffer_read_u16(packet); 1097 if(!buffer_available(packet, rrlen)) { 1098 log_msg(LOG_ERR, "bad xfr RR rdata %d, len %d have %d", 1099 *rr_count, rrlen, (int)buffer_remaining(packet)); 1100 region_destroy(region); 1101 return 0; 1102 } 1103 1104 DEBUG(DEBUG_XFRD,2, (LOG_INFO, "diff: %s parsed count %d, ax %d, delmode %d", 1105 domain_to_string(zone->apex), *rr_count, *is_axfr, *delete_mode)); 1106 1107 if (type == TYPE_SOA) { 1108 size_t position; 1109 uint32_t serial; 1110 position = buffer_position(packet); 1111 if (!packet_skip_dname(packet) || 1112 !packet_skip_dname(packet) || 1113 buffer_remaining(packet) < sizeof(uint32_t) * 5) 1114 { 1115 log_msg(LOG_ERR, "bad xfr SOA RR formerr."); 1116 region_destroy(region); 1117 return 0; 1118 } 1119 1120 serial = buffer_read_u32(packet); 1121 buffer_set_position(packet, position); 1122 1123 /* first RR: check if SOA and correct zone & serialno */ 1124 if (*rr_count == 0) { 1125 assert(!*is_axfr); 1126 assert(!*delete_mode); 1127 if (klass != CLASS_IN) { 1128 log_msg(LOG_ERR, "first RR not SOA IN"); 1129 region_destroy(region); 1130 return 0; 1131 } 1132 if(dname_compare(domain_dname(zone->apex), owner) != 0) { 1133 log_msg(LOG_ERR, "SOA dname not equal to zone %s", 1134 domain_to_string(zone->apex)); 1135 region_destroy(region); 1136 return 0; 1137 } 1138 if(serial != serialno) { 1139 log_msg(LOG_ERR, "SOA serial %u different from commit %u", 1140 (unsigned)serial, (unsigned)serialno); 1141 region_destroy(region); 1142 return 0; 1143 } 1144 buffer_skip(packet, rrlen); 1145 1146 if(ixfr_store) 1147 ixfr_store_add_newsoa(ixfr_store, ttl, packet, rrlen); 1148 1149 continue; 1150 } else if (*rr_count == 1) { 1151 assert(!*is_axfr); 1152 assert(!*delete_mode); 1153 /* if the serial no of the SOA equals the serialno, then AXFR */ 1154 if (serial == serialno) 1155 goto axfr; 1156 *delete_mode = 1; 1157 /* must have stuff in memory for a successful IXFR, 1158 * the serial number of the SOA has been checked 1159 * previously (by check_for_bad_serial) if it exists */ 1160 if(!domain_find_rrset(zone->apex, zone, TYPE_SOA)) { 1161 log_msg(LOG_ERR, "%s SOA serial %u is not " 1162 "in memory, skip IXFR", domain_to_string(zone->apex), serialno); 1163 region_destroy(region); 1164 /* break out and stop the IXFR, ignore it */ 1165 return 2; 1166 } 1167 1168 if(ixfr_store) 1169 ixfr_store_add_oldsoa(ixfr_store, ttl, packet, rrlen); 1170 } else if (!*is_axfr) { 1171 /* do not delete final SOA RR for IXFR */ 1172 if (i == ancount - 1 && seq_nr == seq_total - 1) { 1173 if (ixfr_store) { 1174 ixfr_store_add_newsoa(ixfr_store, ttl, packet, rrlen); 1175 } 1176 *delete_mode = 0; 1177 buffer_skip(packet, rrlen); 1178 continue; 1179 } else 1180 *delete_mode = !*delete_mode; 1181 1182 if (ixfr_store && *delete_mode) { 1183 ixfr_store_add_newsoa(ixfr_store, ttl, packet, rrlen); 1184 ixfr_store_finish(ixfr_store, nsd, NULL); 1185 ixfr_store_start(zone, ixfr_store); 1186 ixfr_store_add_oldsoa(ixfr_store, ttl, packet, rrlen); 1187 } 1188 /* switch from delete-part to add-part and back again, 1189 just before soa - so it gets deleted and added too */ 1190 DEBUG(DEBUG_XFRD,2, (LOG_INFO, "diff: %s IXFRswapdel count %d, ax %d, delmode %d", 1191 domain_to_string(zone->apex), *rr_count, *is_axfr, *delete_mode)); 1192 } 1193 } else { 1194 if (*rr_count == 0) { 1195 log_msg(LOG_ERR, "first RR not SOA IN"); 1196 region_destroy(region); 1197 return 0; 1198 /* second RR: if not SOA: this is an AXFR; delete all zone contents */ 1199 } else if (*rr_count == 1) { 1200axfr: 1201 *is_axfr = 1; 1202#ifdef NSEC3 1203 nsec3_clear_precompile(nsd->db, zone); 1204 zone->nsec3_param = NULL; 1205#endif 1206 delete_zone_rrs(nsd->db, zone); 1207 if(ixfr_store) { 1208 ixfr_store_cancel(ixfr_store); 1209 ixfr_store_delixfrs(zone); 1210 } 1211 DEBUG(DEBUG_XFRD,2, (LOG_INFO, "diff: %s sawAXFR count %d, ax %d, delmode %d", 1212 domain_to_string(zone->apex), *rr_count, *is_axfr, *delete_mode)); 1213 } 1214 } 1215 1216 if(type == TYPE_TSIG || type == TYPE_OPT) { 1217 /* ignore pseudo RRs */ 1218 buffer_skip(packet, rrlen); 1219 continue; 1220 } 1221 1222 DEBUG(DEBUG_XFRD,2, (LOG_INFO, "xfr %s RR dname is %s type %s", 1223 *delete_mode?"del":"add", 1224 dname_to_string(owner, 0), rrtype_to_string(type))); 1225 if(*delete_mode) { 1226 assert(!*is_axfr); 1227 /* delete this rr */ 1228 if(ixfr_store) 1229 ixfr_store_delrr(ixfr_store, owner, type, 1230 klass, ttl, packet, rrlen, region); 1231 if(!delete_RR(nsd->db, owner, type, klass, packet, 1232 rrlen, zone, region, softfail)) { 1233 region_destroy(region); 1234 return 0; 1235 } 1236 } else { 1237 /* add this rr */ 1238 if(ixfr_store) 1239 ixfr_store_addrr(ixfr_store, owner, type, 1240 klass, ttl, packet, rrlen, region); 1241 if(!add_RR(nsd->db, owner, type, klass, ttl, packet, 1242 rrlen, zone, softfail)) { 1243 region_destroy(region); 1244 return 0; 1245 } 1246 } 1247 } 1248 region_destroy(region); 1249 return 1; 1250} 1251 1252static int 1253check_for_bad_serial(namedb_type* db, const char* zone_str, uint32_t old_serial) 1254{ 1255 /* see if serial OK with in-memory serial */ 1256 domain_type* domain; 1257 region_type* region = region_create(xalloc, free); 1258 const dname_type* zone_name = dname_parse(region, zone_str); 1259 zone_type* zone = 0; 1260 domain = domain_table_find(db->domains, zone_name); 1261 if(domain) 1262 zone = domain_find_zone(db, domain); 1263 if(zone && zone->apex == domain && zone->soa_rrset && old_serial) 1264 { 1265 uint32_t memserial; 1266 memcpy(&memserial, rdata_atom_data(zone->soa_rrset->rrs[0].rdatas[2]), 1267 sizeof(uint32_t)); 1268 if(old_serial != ntohl(memserial)) { 1269 region_destroy(region); 1270 return 1; 1271 } 1272 } 1273 region_destroy(region); 1274 return 0; 1275} 1276 1277int 1278apply_ixfr_for_zone(nsd_type* nsd, zone_type* zone, FILE* in, 1279 struct nsd_options* ATTR_UNUSED(opt), udb_base* taskudb, udb_ptr* last_task, 1280 uint32_t xfrfilenr) 1281{ 1282 char zone_buf[3072]; 1283 char log_buf[5120]; 1284 char patname_buf[2048]; 1285 1286 uint32_t old_serial, new_serial, num_parts, type; 1287 uint64_t time_end_0, time_start_0; 1288 uint32_t time_end_1, time_start_1; 1289 uint8_t committed; 1290 uint32_t i; 1291 int num_bytes = 0; 1292 (void)last_task; 1293 assert(zone); 1294 1295 /* read zone name and serial */ 1296 if(!diff_read_32(in, &type)) { 1297 log_msg(LOG_ERR, "diff file too short"); 1298 return 0; 1299 } 1300 if(type != DIFF_PART_XFRF) { 1301 log_msg(LOG_ERR, "xfr file has wrong format"); 1302 return 0; 1303 1304 } 1305 /* committed and num_parts are first because they need to be 1306 * updated once the rest is written. The log buf is not certain 1307 * until its done, so at end of file. The patname is in case a 1308 * new zone is created, we know what the options-pattern is */ 1309 if(!diff_read_8(in, &committed) || 1310 !diff_read_32(in, &num_parts) || 1311 !diff_read_64(in, &time_end_0) || 1312 !diff_read_32(in, &time_end_1) || 1313 !diff_read_32(in, &old_serial) || 1314 !diff_read_32(in, &new_serial) || 1315 !diff_read_64(in, &time_start_0) || 1316 !diff_read_32(in, &time_start_1) || 1317 !diff_read_str(in, zone_buf, sizeof(zone_buf)) || 1318 !diff_read_str(in, patname_buf, sizeof(patname_buf))) { 1319 log_msg(LOG_ERR, "diff file bad commit part"); 1320 return 0; 1321 } 1322 1323 /* has been read in completely */ 1324 if(strcmp(zone_buf, domain_to_string(zone->apex)) != 0) { 1325 log_msg(LOG_ERR, "file %s does not match task %s", 1326 zone_buf, domain_to_string(zone->apex)); 1327 return 0; 1328 } 1329 switch(committed) { 1330 case DIFF_NOT_COMMITTED: 1331 log_msg(LOG_ERR, "diff file %s was not committed", zone_buf); 1332 return 0; 1333 case DIFF_CORRUPT: 1334 log_msg(LOG_ERR, "diff file %s was corrupt", zone_buf); 1335 return 0; 1336 case DIFF_INCONSISTENT: 1337 log_msg(LOG_ERR, "diff file %s was inconsistent", zone_buf); 1338 return 0; 1339 case DIFF_VERIFIED: 1340 log_msg(LOG_INFO, "diff file %s already verified", zone_buf); 1341 break; 1342 default: 1343 break; 1344 } 1345 if(num_parts == 0) { 1346 log_msg(LOG_ERR, "diff file %s was not completed", zone_buf); 1347 return 0; 1348 } 1349 if(check_for_bad_serial(nsd->db, zone_buf, old_serial)) { 1350 DEBUG(DEBUG_XFRD,1, (LOG_ERR, 1351 "skipping diff file commit with bad serial")); 1352 return -2; /* Success in "main" process, failure in "xfrd" */ 1353 } 1354 1355 if(!zone->is_skipped) 1356 { 1357 int is_axfr=0, delete_mode=0, rr_count=0, softfail=0; 1358 struct ixfr_store* ixfr_store = NULL, ixfr_store_mem; 1359 1360 DEBUG(DEBUG_XFRD,1, (LOG_INFO, "processing xfr: %s", zone_buf)); 1361 if(zone_is_ixfr_enabled(zone)) 1362 ixfr_store = ixfr_store_start(zone, &ixfr_store_mem); 1363 /* read and apply all of the parts */ 1364 for(i=0; i<num_parts; i++) { 1365 int ret; 1366 DEBUG(DEBUG_XFRD,2, (LOG_INFO, "processing xfr: apply part %d", (int)i)); 1367 ret = apply_ixfr(nsd, in, new_serial, 1368 i, num_parts, &is_axfr, &delete_mode, 1369 &rr_count, zone, 1370 &num_bytes, &softfail, ixfr_store); 1371 if(ret == 0) { 1372 log_msg(LOG_ERR, "bad ixfr packet part %d in diff file for %s", (int)i, zone_buf); 1373 diff_update_commit( 1374 zone_buf, DIFF_CORRUPT, nsd, xfrfilenr); 1375 /* the udb is still dirty, it is bad */ 1376 return -1; /* Fatal! */ 1377 } else if(ret == 2) { 1378 break; 1379 } 1380 } 1381 /* read the final log_str: but do not fail on it */ 1382 if(!diff_read_str(in, log_buf, sizeof(log_buf))) { 1383 log_msg(LOG_ERR, "could not read log for transfer %s", 1384 zone_buf); 1385 snprintf(log_buf, sizeof(log_buf), "error reading log"); 1386 } 1387#ifdef NSEC3 1388 prehash_zone(nsd->db, zone); 1389#endif /* NSEC3 */ 1390 zone->is_changed = 1; 1391 zone->is_updated = 1; 1392 zone->is_checked = (committed == DIFF_VERIFIED); 1393 zone->mtime.tv_sec = time_end_0; 1394 zone->mtime.tv_nsec = time_end_1*1000; 1395 if(zone->logstr) 1396 region_recycle(nsd->db->region, zone->logstr, 1397 strlen(zone->logstr)+1); 1398 zone->logstr = region_strdup(nsd->db->region, log_buf); 1399 if(zone->filename) 1400 region_recycle(nsd->db->region, zone->filename, 1401 strlen(zone->filename)+1); 1402 zone->filename = NULL; 1403 if(softfail && taskudb && !is_axfr) { 1404 log_msg(LOG_ERR, "Failed to apply IXFR cleanly " 1405 "(deletes nonexistent RRs, adds existing RRs). " 1406 "Zone %s contents is different from primary, " 1407 "starting AXFR. Transfer %s", zone_buf, log_buf); 1408 /* add/del failures in IXFR, get an AXFR */ 1409 diff_update_commit( 1410 zone_buf, DIFF_INCONSISTENT, nsd, xfrfilenr); 1411 return -1; /* Fatal! */ 1412 } 1413 if(ixfr_store) 1414 ixfr_store_finish(ixfr_store, nsd, log_buf); 1415 1416 if(1 <= verbosity) { 1417 double elapsed = (double)(time_end_0 - time_start_0)+ 1418 (double)((double)time_end_1 1419 -(double)time_start_1) / 1000000.0; 1420 VERBOSITY(1, (LOG_INFO, "zone %s %s of %d bytes in %g seconds", 1421 zone_buf, log_buf, num_bytes, elapsed)); 1422 } 1423 } 1424 else { 1425 DEBUG(DEBUG_XFRD,1, (LOG_INFO, "skipping xfr: %s", zone_buf)); 1426 } 1427 return 1; 1428} 1429 1430static void udb_task_walk_chunk(void* base, void* d, uint64_t s, udb_walk_relptr_cb* cb, void *arg) 1431{ 1432 struct task_list_d* p = (struct task_list_d*)d; 1433 assert(s >= p->size); 1434 (void)s; 1435 (*cb)(base, &p->next, arg); 1436} 1437 1438void udb_walkfunc(void* base, void* warg, uint8_t t, void* d, uint64_t s, 1439 udb_walk_relptr_cb* cb, void *arg) 1440{ 1441 (void)warg; 1442 switch(t) { 1443 case udb_chunk_type_task: 1444 udb_task_walk_chunk(base, d, s, cb, arg); 1445 break; 1446 default: 1447 /* no rel ptrs */ 1448 break; 1449 } 1450} 1451 1452struct udb_base* task_file_create(const char* file) 1453{ 1454 return udb_base_create_new(file, &udb_walkfunc, NULL); 1455} 1456 1457static int 1458task_create_new_elem(struct udb_base* udb, udb_ptr* last, udb_ptr* e, 1459 size_t sz, const dname_type* zname) 1460{ 1461 if(!udb_ptr_alloc_space(e, udb, udb_chunk_type_task, sz)) { 1462 return 0; 1463 } 1464 if(udb_ptr_is_null(last)) { 1465 udb_base_set_userdata(udb, e->data); 1466 } else { 1467 udb_rptr_set_ptr(&TASKLIST(last)->next, udb, e); 1468 } 1469 udb_ptr_set_ptr(last, udb, e); 1470 1471 /* fill in tasklist item */ 1472 udb_rel_ptr_init(&TASKLIST(e)->next); 1473 TASKLIST(e)->size = sz; 1474 TASKLIST(e)->oldserial = 0; 1475 TASKLIST(e)->newserial = 0; 1476 TASKLIST(e)->yesno = 0; 1477 1478 if(zname) { 1479 memmove(TASKLIST(e)->zname, zname, dname_total_size(zname)); 1480 } 1481 return 1; 1482} 1483 1484void task_new_soainfo(struct udb_base* udb, udb_ptr* last, struct zone* z, 1485 enum soainfo_hint hint) 1486{ 1487 /* calculate size */ 1488 udb_ptr e; 1489 size_t sz; 1490 const dname_type* apex, *ns, *em; 1491 if(!z || !z->apex || !domain_dname(z->apex)) 1492 return; /* safety check */ 1493 1494 DEBUG(DEBUG_IPC,1, (LOG_INFO, "nsd: add soa info for zone %s", 1495 domain_to_string(z->apex))); 1496 apex = domain_dname(z->apex); 1497 sz = sizeof(struct task_list_d) + dname_total_size(apex); 1498 if(z->soa_rrset && hint == soainfo_ok) { 1499 ns = domain_dname(rdata_atom_domain( 1500 z->soa_rrset->rrs[0].rdatas[0])); 1501 em = domain_dname(rdata_atom_domain( 1502 z->soa_rrset->rrs[0].rdatas[1])); 1503 sz += sizeof(uint32_t)*6 + sizeof(uint8_t)*2 1504 + ns->name_size + em->name_size; 1505 } else { 1506 ns = 0; 1507 em = 0; 1508 } 1509 1510 /* create new task_list item */ 1511 if(!task_create_new_elem(udb, last, &e, sz, apex)) { 1512 log_msg(LOG_ERR, "tasklist: out of space, cannot add SOAINFO"); 1513 return; 1514 } 1515 TASKLIST(&e)->task_type = task_soa_info; 1516 TASKLIST(&e)->yesno = (uint64_t)hint; 1517 1518 if(z->soa_rrset && hint == soainfo_ok) { 1519 uint32_t ttl = htonl(z->soa_rrset->rrs[0].ttl); 1520 uint8_t* p = (uint8_t*)TASKLIST(&e)->zname; 1521 p += dname_total_size(apex); 1522 memmove(p, &ttl, sizeof(uint32_t)); 1523 p += sizeof(uint32_t); 1524 memmove(p, &ns->name_size, sizeof(uint8_t)); 1525 p += sizeof(uint8_t); 1526 memmove(p, dname_name(ns), ns->name_size); 1527 p += ns->name_size; 1528 memmove(p, &em->name_size, sizeof(uint8_t)); 1529 p += sizeof(uint8_t); 1530 memmove(p, dname_name(em), em->name_size); 1531 p += em->name_size; 1532 memmove(p, rdata_atom_data(z->soa_rrset->rrs[0].rdatas[2]), 1533 sizeof(uint32_t)); 1534 p += sizeof(uint32_t); 1535 memmove(p, rdata_atom_data(z->soa_rrset->rrs[0].rdatas[3]), 1536 sizeof(uint32_t)); 1537 p += sizeof(uint32_t); 1538 memmove(p, rdata_atom_data(z->soa_rrset->rrs[0].rdatas[4]), 1539 sizeof(uint32_t)); 1540 p += sizeof(uint32_t); 1541 memmove(p, rdata_atom_data(z->soa_rrset->rrs[0].rdatas[5]), 1542 sizeof(uint32_t)); 1543 p += sizeof(uint32_t); 1544 memmove(p, rdata_atom_data(z->soa_rrset->rrs[0].rdatas[6]), 1545 sizeof(uint32_t)); 1546 } 1547 udb_ptr_unlink(&e, udb); 1548} 1549 1550void task_process_sync(struct udb_base* taskudb) 1551{ 1552 /* need to sync before other process uses the mmap? */ 1553 DEBUG(DEBUG_IPC,1, (LOG_INFO, "task procsync %s size %d", 1554 taskudb->fname, (int)taskudb->base_size)); 1555 (void)taskudb; 1556} 1557 1558void task_remap(struct udb_base* taskudb) 1559{ 1560 DEBUG(DEBUG_IPC,1, (LOG_INFO, "task remap %s size %d", 1561 taskudb->fname, (int)taskudb->glob_data->fsize)); 1562 udb_base_remap_process(taskudb); 1563} 1564 1565void task_clear(struct udb_base* taskudb) 1566{ 1567 udb_ptr t, n; 1568 udb_ptr_new(&t, taskudb, udb_base_get_userdata(taskudb)); 1569 udb_base_set_userdata(taskudb, 0); 1570 udb_ptr_init(&n, taskudb); 1571 while(!udb_ptr_is_null(&t)) { 1572 udb_ptr_set_rptr(&n, taskudb, &TASKLIST(&t)->next); 1573 udb_rptr_zero(&TASKLIST(&t)->next, taskudb); 1574 udb_ptr_free_space(&t, taskudb, TASKLIST(&t)->size); 1575 udb_ptr_set_ptr(&t, taskudb, &n); 1576 } 1577 udb_ptr_unlink(&t, taskudb); 1578 udb_ptr_unlink(&n, taskudb); 1579} 1580 1581void task_new_expire(struct udb_base* udb, udb_ptr* last, 1582 const struct dname* z, int expired) 1583{ 1584 udb_ptr e; 1585 if(!z) return; 1586 DEBUG(DEBUG_IPC,1, (LOG_INFO, "add expire info for zone %s", 1587 dname_to_string(z,NULL))); 1588 if(!task_create_new_elem(udb, last, &e, sizeof(struct task_list_d)+ 1589 dname_total_size(z), z)) { 1590 log_msg(LOG_ERR, "tasklist: out of space, cannot add expire"); 1591 return; 1592 } 1593 TASKLIST(&e)->task_type = task_expire; 1594 TASKLIST(&e)->yesno = expired; 1595 udb_ptr_unlink(&e, udb); 1596} 1597 1598void task_new_check_zonefiles(udb_base* udb, udb_ptr* last, 1599 const dname_type* zone) 1600{ 1601 udb_ptr e; 1602 xfrd_check_catalog_consumer_zonefiles(zone); 1603 DEBUG(DEBUG_IPC,1, (LOG_INFO, "add task checkzonefiles")); 1604 if(!task_create_new_elem(udb, last, &e, sizeof(struct task_list_d) + 1605 (zone?dname_total_size(zone):0), zone)) { 1606 log_msg(LOG_ERR, "tasklist: out of space, cannot add check_zones"); 1607 return; 1608 } 1609 TASKLIST(&e)->task_type = task_check_zonefiles; 1610 TASKLIST(&e)->yesno = (zone!=NULL); 1611 udb_ptr_unlink(&e, udb); 1612} 1613 1614void task_new_write_zonefiles(udb_base* udb, udb_ptr* last, 1615 const dname_type* zone) 1616{ 1617 udb_ptr e; 1618 DEBUG(DEBUG_IPC,1, (LOG_INFO, "add task writezonefiles")); 1619 if(!task_create_new_elem(udb, last, &e, sizeof(struct task_list_d) + 1620 (zone?dname_total_size(zone):0), zone)) { 1621 log_msg(LOG_ERR, "tasklist: out of space, cannot add writezones"); 1622 return; 1623 } 1624 TASKLIST(&e)->task_type = task_write_zonefiles; 1625 TASKLIST(&e)->yesno = (zone!=NULL); 1626 udb_ptr_unlink(&e, udb); 1627} 1628 1629void task_new_set_verbosity(udb_base* udb, udb_ptr* last, int v) 1630{ 1631 udb_ptr e; 1632 DEBUG(DEBUG_IPC,1, (LOG_INFO, "add task set_verbosity")); 1633 if(!task_create_new_elem(udb, last, &e, sizeof(struct task_list_d), 1634 NULL)) { 1635 log_msg(LOG_ERR, "tasklist: out of space, cannot add set_v"); 1636 return; 1637 } 1638 TASKLIST(&e)->task_type = task_set_verbosity; 1639 TASKLIST(&e)->yesno = v; 1640 udb_ptr_unlink(&e, udb); 1641} 1642 1643void 1644task_new_add_zone(udb_base* udb, udb_ptr* last, const char* zone, 1645 const char* pattern, unsigned zonestatid) 1646{ 1647 size_t zlen = strlen(zone); 1648 size_t plen = strlen(pattern); 1649 void *p; 1650 udb_ptr e; 1651 DEBUG(DEBUG_IPC,1, (LOG_INFO, "add task addzone %s %s", zone, pattern)); 1652 if(!task_create_new_elem(udb, last, &e, sizeof(struct task_list_d)+ 1653 zlen + 1 + plen + 1, NULL)) { 1654 log_msg(LOG_ERR, "tasklist: out of space, cannot add addz"); 1655 return; 1656 } 1657 TASKLIST(&e)->task_type = task_add_zone; 1658 TASKLIST(&e)->yesno = zonestatid; 1659 p = TASKLIST(&e)->zname; 1660 memcpy(p, zone, zlen+1); 1661 memmove((char*)p+zlen+1, pattern, plen+1); 1662 udb_ptr_unlink(&e, udb); 1663} 1664 1665void 1666task_new_del_zone(udb_base* udb, udb_ptr* last, const dname_type* dname) 1667{ 1668 udb_ptr e; 1669 DEBUG(DEBUG_IPC,1, (LOG_INFO, "add task delzone %s", dname_to_string(dname, 0))); 1670 if(!task_create_new_elem(udb, last, &e, sizeof(struct task_list_d) 1671 +dname_total_size(dname), dname)) { 1672 log_msg(LOG_ERR, "tasklist: out of space, cannot add delz"); 1673 return; 1674 } 1675 TASKLIST(&e)->task_type = task_del_zone; 1676 udb_ptr_unlink(&e, udb); 1677} 1678 1679void task_new_add_key(udb_base* udb, udb_ptr* last, struct key_options* key) 1680{ 1681 char* p; 1682 udb_ptr e; 1683 assert(key->name && key->algorithm && key->secret); 1684 DEBUG(DEBUG_IPC,1, (LOG_INFO, "add task addkey")); 1685 if(!task_create_new_elem(udb, last, &e, sizeof(struct task_list_d) 1686 +strlen(key->name)+1+strlen(key->algorithm)+1+ 1687 strlen(key->secret)+1, NULL)) { 1688 log_msg(LOG_ERR, "tasklist: out of space, cannot add addk"); 1689 return; 1690 } 1691 TASKLIST(&e)->task_type = task_add_key; 1692 p = (char*)TASKLIST(&e)->zname; 1693 memmove(p, key->name, strlen(key->name)+1); 1694 p+=strlen(key->name)+1; 1695 memmove(p, key->algorithm, strlen(key->algorithm)+1); 1696 p+=strlen(key->algorithm)+1; 1697 memmove(p, key->secret, strlen(key->secret)+1); 1698 udb_ptr_unlink(&e, udb); 1699} 1700 1701void task_new_del_key(udb_base* udb, udb_ptr* last, const char* name) 1702{ 1703 char* p; 1704 udb_ptr e; 1705 DEBUG(DEBUG_IPC,1, (LOG_INFO, "add task delkey")); 1706 if(!task_create_new_elem(udb, last, &e, sizeof(struct task_list_d) 1707 +strlen(name)+1, NULL)) { 1708 log_msg(LOG_ERR, "tasklist: out of space, cannot add delk"); 1709 return; 1710 } 1711 TASKLIST(&e)->task_type = task_del_key; 1712 p = (char*)TASKLIST(&e)->zname; 1713 memmove(p, name, strlen(name)+1); 1714 udb_ptr_unlink(&e, udb); 1715} 1716 1717void task_new_add_cookie_secret(udb_base* udb, udb_ptr* last, 1718 const char* secret) { 1719 udb_ptr e; 1720 char* p; 1721 size_t const secret_size = strlen(secret) + 1; 1722 1723 DEBUG(DEBUG_IPC, 1, (LOG_INFO, "add task add_cookie_secret")); 1724 1725 if(!task_create_new_elem(udb, last, &e, 1726 sizeof(struct task_list_d) + secret_size, NULL)) { 1727 log_msg(LOG_ERR, "tasklist: out of space, cannot add add_cookie_secret"); 1728 return; 1729 } 1730 TASKLIST(&e)->task_type = task_add_cookie_secret; 1731 p = (char*)TASKLIST(&e)->zname; 1732 memmove(p, secret, secret_size); 1733 udb_ptr_unlink(&e, udb); 1734} 1735 1736void task_new_drop_cookie_secret(udb_base* udb, udb_ptr* last) { 1737 udb_ptr e; 1738 DEBUG(DEBUG_IPC, 1, (LOG_INFO, "add task drop_cookie_secret")); 1739 if(!task_create_new_elem(udb, last, &e, sizeof(struct task_list_d), NULL)) { 1740 log_msg(LOG_ERR, "tasklist: out of space, cannot add drop_cookie_secret"); 1741 return; 1742 } 1743 TASKLIST(&e)->task_type = task_drop_cookie_secret; 1744 udb_ptr_unlink(&e, udb); 1745} 1746 1747void task_new_activate_cookie_secret(udb_base* udb, udb_ptr* last) { 1748 udb_ptr e; 1749 DEBUG(DEBUG_IPC, 1, (LOG_INFO, "add task activate_cookie_secret")); 1750 if(!task_create_new_elem(udb, last, &e, sizeof(struct task_list_d), NULL)) { 1751 log_msg(LOG_ERR, "tasklist: out of space, cannot add activate_cookie_secret"); 1752 return; 1753 } 1754 TASKLIST(&e)->task_type = task_activate_cookie_secret; 1755 udb_ptr_unlink(&e, udb); 1756} 1757 1758void task_new_add_pattern(udb_base* udb, udb_ptr* last, 1759 struct pattern_options* p) 1760{ 1761 region_type* temp; 1762 buffer_type* buffer; 1763 udb_ptr e; 1764 DEBUG(DEBUG_IPC,1, (LOG_INFO, "add task addpattern %s", p->pname)); 1765 temp = region_create(xalloc, free); 1766 buffer = buffer_create(temp, 4096); 1767 pattern_options_marshal(buffer, p); 1768 buffer_flip(buffer); 1769 if(!task_create_new_elem(udb, last, &e, sizeof(struct task_list_d) 1770 + buffer_limit(buffer), NULL)) { 1771 log_msg(LOG_ERR, "tasklist: out of space, cannot add addp"); 1772 region_destroy(temp); 1773 return; 1774 } 1775 TASKLIST(&e)->task_type = task_add_pattern; 1776 TASKLIST(&e)->yesno = buffer_limit(buffer); 1777 memmove(TASKLIST(&e)->zname, buffer_begin(buffer), 1778 buffer_limit(buffer)); 1779 udb_ptr_unlink(&e, udb); 1780 region_destroy(temp); 1781} 1782 1783void task_new_del_pattern(udb_base* udb, udb_ptr* last, const char* name) 1784{ 1785 char* p; 1786 udb_ptr e; 1787 DEBUG(DEBUG_IPC,1, (LOG_INFO, "add task delpattern %s", name)); 1788 if(!task_create_new_elem(udb, last, &e, sizeof(struct task_list_d) 1789 +strlen(name)+1, NULL)) { 1790 log_msg(LOG_ERR, "tasklist: out of space, cannot add delp"); 1791 return; 1792 } 1793 TASKLIST(&e)->task_type = task_del_pattern; 1794 p = (char*)TASKLIST(&e)->zname; 1795 memmove(p, name, strlen(name)+1); 1796 udb_ptr_unlink(&e, udb); 1797} 1798 1799void task_new_opt_change(udb_base* udb, udb_ptr* last, struct nsd_options* opt) 1800{ 1801 udb_ptr e; 1802 DEBUG(DEBUG_IPC,1, (LOG_INFO, "add task opt_change")); 1803 if(!task_create_new_elem(udb, last, &e, sizeof(struct task_list_d), 1804 NULL)) { 1805 log_msg(LOG_ERR, "tasklist: out of space, cannot add o_c"); 1806 return; 1807 } 1808 TASKLIST(&e)->task_type = task_opt_change; 1809#ifdef RATELIMIT 1810 TASKLIST(&e)->oldserial = opt->rrl_ratelimit; 1811 TASKLIST(&e)->newserial = opt->rrl_whitelist_ratelimit; 1812 TASKLIST(&e)->yesno = (uint64_t) opt->rrl_slip; 1813#else 1814 (void)opt; 1815#endif 1816 udb_ptr_unlink(&e, udb); 1817} 1818 1819void task_new_zonestat_inc(udb_base* udb, udb_ptr* last, unsigned sz) 1820{ 1821 udb_ptr e; 1822 DEBUG(DEBUG_IPC,1, (LOG_INFO, "add task zonestat_inc")); 1823 if(sz == 0) 1824 return; /* no need to decrease to 0 */ 1825 if(!task_create_new_elem(udb, last, &e, sizeof(struct task_list_d), 1826 NULL)) { 1827 log_msg(LOG_ERR, "tasklist: out of space, cannot add z_i"); 1828 return; 1829 } 1830 TASKLIST(&e)->task_type = task_zonestat_inc; 1831 TASKLIST(&e)->oldserial = (uint32_t)sz; 1832 udb_ptr_unlink(&e, udb); 1833} 1834 1835int 1836task_new_apply_xfr(udb_base* udb, udb_ptr* last, const dname_type* dname, 1837 uint32_t old_serial, uint32_t new_serial, uint64_t filenumber) 1838{ 1839 udb_ptr e; 1840 DEBUG(DEBUG_IPC,1, (LOG_INFO, "add task apply_xfr")); 1841 if(!task_create_new_elem(udb, last, &e, sizeof(struct task_list_d) 1842 +dname_total_size(dname), dname)) { 1843 log_msg(LOG_ERR, "tasklist: out of space, cannot add applyxfr"); 1844 return 0; 1845 } 1846 TASKLIST(&e)->oldserial = old_serial; 1847 TASKLIST(&e)->newserial = new_serial; 1848 TASKLIST(&e)->yesno = filenumber; 1849 TASKLIST(&e)->task_type = task_apply_xfr; 1850 udb_ptr_unlink(&e, udb); 1851 return 1; 1852} 1853 1854void 1855task_process_expire(namedb_type* db, struct task_list_d* task) 1856{ 1857 uint8_t ok; 1858 zone_type* z = namedb_find_zone(db, task->zname); 1859 assert(task->task_type == task_expire); 1860 if(!z) { 1861 DEBUG(DEBUG_IPC, 1, (LOG_WARNING, "zone %s %s but not in zonetree", 1862 dname_to_string(task->zname, NULL), 1863 task->yesno?"expired":"unexpired")); 1864 return; 1865 } 1866 DEBUG(DEBUG_IPC,1, (LOG_INFO, "xfrd: expire task zone %s %s", 1867 dname_to_string(task->zname,0), 1868 task->yesno?"expired":"unexpired")); 1869 /* find zone, set expire flag */ 1870 ok = !task->yesno; 1871 /* only update zone->is_ok if needed to minimize copy-on-write 1872 * of memory pages shared after fork() */ 1873 if(ok && !z->is_ok) 1874 z->is_ok = 1; 1875 else if(!ok && z->is_ok) 1876 z->is_ok = 0; 1877} 1878 1879static void 1880task_process_set_verbosity(struct task_list_d* task) 1881{ 1882 DEBUG(DEBUG_IPC,1, (LOG_INFO, "verbosity task %d", (int)task->yesno)); 1883 verbosity = task->yesno; 1884} 1885 1886static void 1887task_process_checkzones(struct nsd* nsd, udb_base* taskudb, udb_ptr* last_task, 1888 struct task_list_d* task) 1889{ 1890 /* on SIGHUP check if zone-text-files changed and if so, 1891 * reread. When from xfrd-reload, no need to fstat the files */ 1892 if(task->yesno) { 1893 struct zone_options* zo = zone_options_find(nsd->options, 1894 task->zname); 1895 if(zo) 1896 namedb_check_zonefile(nsd, taskudb, last_task, zo); 1897 } else { 1898 /* check all zones */ 1899 namedb_check_zonefiles(nsd, nsd->options, taskudb, last_task); 1900 } 1901} 1902 1903static void 1904task_process_writezones(struct nsd* nsd, struct task_list_d* task) 1905{ 1906 if(task->yesno) { 1907 struct zone_options* zo = zone_options_find(nsd->options, 1908 task->zname); 1909 if(zo) 1910 namedb_write_zonefile(nsd, zo); 1911 } else { 1912 namedb_write_zonefiles(nsd, nsd->options); 1913 } 1914} 1915 1916static void 1917task_process_add_zone(struct nsd* nsd, udb_base* udb, udb_ptr* last_task, 1918 struct task_list_d* task) 1919{ 1920 zone_type* z; 1921 const dname_type* zdname; 1922 const char* zname = (const char*)task->zname; 1923 const char* pname = zname + strlen(zname)+1; 1924 DEBUG(DEBUG_IPC,1, (LOG_INFO, "addzone task %s %s", zname, pname)); 1925 zdname = dname_parse(nsd->db->region, zname); 1926 if(!zdname) { 1927 log_msg(LOG_ERR, "can not parse zone name %s", zname); 1928 return; 1929 } 1930 /* create zone */ 1931 z = find_or_create_zone(nsd->db, zdname, nsd->options, zname, pname); 1932 if(!z) { 1933 region_recycle(nsd->db->region, (void*)zdname, 1934 dname_total_size(zdname)); 1935 log_msg(LOG_ERR, "can not add zone %s %s", zname, pname); 1936 return; 1937 } 1938 z->zonestatid = (unsigned)task->yesno; 1939 /* if zone is empty, attempt to read the zonefile from disk (if any) */ 1940 if(!z->soa_rrset && z->opts->pattern->zonefile) { 1941 namedb_read_zonefile(nsd, z, udb, last_task); 1942 } 1943} 1944 1945static void 1946task_process_del_zone(struct nsd* nsd, struct task_list_d* task) 1947{ 1948 zone_type* zone; 1949 struct zone_options* zopt; 1950 DEBUG(DEBUG_IPC,1, (LOG_INFO, "delzone task %s", dname_to_string( 1951 task->zname, NULL))); 1952 zone = namedb_find_zone(nsd->db, task->zname); 1953 if(!zone) 1954 return; 1955 1956#ifdef NSEC3 1957 nsec3_clear_precompile(nsd->db, zone); 1958 zone->nsec3_param = NULL; 1959#endif 1960 delete_zone_rrs(nsd->db, zone); 1961 1962 /* remove from zonetree, apex, soa */ 1963 zopt = zone->opts; 1964 namedb_zone_delete(nsd->db, zone); 1965 /* remove from options (zone_list already edited by xfrd) */ 1966 zone_options_delete(nsd->options, zopt); 1967} 1968 1969static void 1970task_process_add_key(struct nsd* nsd, struct task_list_d* task) 1971{ 1972 struct key_options key; 1973 key.name = (char*)task->zname; 1974 DEBUG(DEBUG_IPC,1, (LOG_INFO, "addkey task %s", key.name)); 1975 key.algorithm = key.name + strlen(key.name)+1; 1976 key.secret = key.algorithm + strlen(key.algorithm)+1; 1977 key_options_add_modify(nsd->options, &key); 1978 memset(key.secret, 0xdd, strlen(key.secret)); /* wipe secret */ 1979} 1980 1981static void 1982task_process_del_key(struct nsd* nsd, struct task_list_d* task) 1983{ 1984 char* name = (char*)task->zname; 1985 DEBUG(DEBUG_IPC,1, (LOG_INFO, "delkey task %s", name)); 1986 /* this is reload and nothing is using the TSIG key right now */ 1987 key_options_remove(nsd->options, name); 1988} 1989 1990static void 1991task_process_add_cookie_secret(struct nsd* nsd, struct task_list_d* task) { 1992 uint8_t secret_tmp[NSD_COOKIE_SECRET_SIZE]; 1993 ssize_t decoded_len; 1994 char* secret = (char*)task->zname; 1995 1996 DEBUG(DEBUG_IPC, 1, (LOG_INFO, "add_cookie_secret task %s", secret)); 1997 1998 if( strlen(secret) != 32 ) { 1999 log_msg(LOG_ERR, "invalid cookie secret: %s", secret); 2000 explicit_bzero(secret, strlen(secret)); 2001 return; 2002 } 2003 2004 decoded_len = hex_pton(secret, secret_tmp, NSD_COOKIE_SECRET_SIZE); 2005 if( decoded_len != 16 ) { 2006 explicit_bzero(secret_tmp, NSD_COOKIE_SECRET_SIZE); 2007 log_msg(LOG_ERR, "unable to parse cookie secret: %s", secret); 2008 explicit_bzero(secret, strlen(secret)); 2009 return; 2010 } 2011 explicit_bzero(secret, strlen(secret)); 2012 add_cookie_secret(nsd, secret_tmp); 2013 explicit_bzero(secret_tmp, NSD_COOKIE_SECRET_SIZE); 2014} 2015 2016static void 2017task_process_drop_cookie_secret(struct nsd* nsd, struct task_list_d* task) 2018{ 2019 (void)task; 2020 DEBUG(DEBUG_IPC, 1, (LOG_INFO, "drop_cookie_secret task")); 2021 if( nsd->cookie_count <= 1 ) { 2022 log_msg(LOG_ERR, "can not drop the only active cookie secret"); 2023 return; 2024 } 2025 drop_cookie_secret(nsd); 2026} 2027 2028static void 2029task_process_activate_cookie_secret(struct nsd* nsd, struct task_list_d* task) 2030{ 2031 (void)task; 2032 DEBUG(DEBUG_IPC, 1, (LOG_INFO, "activate_cookie_secret task")); 2033 if( nsd->cookie_count <= 1 ) { 2034 log_msg(LOG_ERR, "can not activate the only active cookie secret"); 2035 return; 2036 } 2037 activate_cookie_secret(nsd); 2038} 2039 2040static void 2041task_process_add_pattern(struct nsd* nsd, struct task_list_d* task) 2042{ 2043 region_type* temp = region_create(xalloc, free); 2044 buffer_type buffer; 2045 struct pattern_options *pat; 2046 buffer_create_from(&buffer, task->zname, task->yesno); 2047 pat = pattern_options_unmarshal(temp, &buffer); 2048 DEBUG(DEBUG_IPC,1, (LOG_INFO, "addpattern task %s", pat->pname)); 2049 pattern_options_add_modify(nsd->options, pat); 2050 region_destroy(temp); 2051} 2052 2053static void 2054task_process_del_pattern(struct nsd* nsd, struct task_list_d* task) 2055{ 2056 char* name = (char*)task->zname; 2057 DEBUG(DEBUG_IPC,1, (LOG_INFO, "delpattern task %s", name)); 2058 pattern_options_remove(nsd->options, name); 2059} 2060 2061static void 2062task_process_opt_change(struct nsd* nsd, struct task_list_d* task) 2063{ 2064 DEBUG(DEBUG_IPC,1, (LOG_INFO, "optchange task")); 2065#ifdef RATELIMIT 2066 nsd->options->rrl_ratelimit = task->oldserial; 2067 nsd->options->rrl_whitelist_ratelimit = task->newserial; 2068 nsd->options->rrl_slip = task->yesno; 2069 rrl_set_limit(nsd->options->rrl_ratelimit, nsd->options->rrl_whitelist_ratelimit, 2070 nsd->options->rrl_slip); 2071#else 2072 (void)nsd; (void)task; 2073#endif 2074} 2075 2076#ifdef USE_ZONE_STATS 2077static void 2078task_process_zonestat_inc(struct nsd* nsd, udb_base* udb, udb_ptr *last_task, 2079 struct task_list_d* task) 2080{ 2081 DEBUG(DEBUG_IPC,1, (LOG_INFO, "zonestat_inc task %u", (unsigned)task->oldserial)); 2082 nsd->zonestatdesired = (unsigned)task->oldserial; 2083 /* send echo to xfrd to increment on its end */ 2084 task_new_zonestat_inc(udb, last_task, nsd->zonestatdesired); 2085} 2086#endif 2087 2088static void 2089task_process_apply_xfr(struct nsd* nsd, udb_base* udb, udb_ptr *last_task, 2090 udb_ptr* task) 2091{ 2092 /* we have to use an udb_ptr task here, because the apply_xfr procedure 2093 * appends soa_info which may remap and change the pointer. */ 2094 zone_type* zone; 2095 FILE* df; 2096 DEBUG(DEBUG_IPC,1, (LOG_INFO, "applyxfr task %s", dname_to_string( 2097 TASKLIST(task)->zname, NULL))); 2098 zone = namedb_find_zone(nsd->db, TASKLIST(task)->zname); 2099 if(!zone) { 2100 /* assume the zone has been deleted and a zone transfer was 2101 * still waiting to be processed */ 2102 return; 2103 } 2104 2105 /* apply the XFR */ 2106 /* oldserial, newserial, yesno is filenumber */ 2107 df = xfrd_open_xfrfile(nsd, TASKLIST(task)->yesno, "r"); 2108 if(!df) { 2109 /* could not open file to update */ 2110 /* soainfo_gone will be communicated from server_reload, unless 2111 preceding updates have been applied */ 2112 zone->is_skipped = 1; 2113 return; 2114 } 2115 /* read and apply zone transfer */ 2116 switch(apply_ixfr_for_zone(nsd, zone, df, nsd->options, udb, last_task, 2117 TASKLIST(task)->yesno)) { 2118 case 1: /* Success */ 2119 break; 2120 2121 case 0: /* Failure */ 2122 /* soainfo_gone will be communicated from server_reload, unless 2123 preceding updates have been applied */ 2124 zone->is_skipped = 1; 2125 break; 2126 2127 case -1:/* Fatal */ 2128 exit(1); 2129 break; 2130 2131 default:break; 2132 } 2133 fclose(df); 2134} 2135 2136 2137void task_process_in_reload(struct nsd* nsd, udb_base* udb, udb_ptr *last_task, 2138 udb_ptr* task) 2139{ 2140 switch(TASKLIST(task)->task_type) { 2141 case task_expire: 2142 task_process_expire(nsd->db, TASKLIST(task)); 2143 break; 2144 case task_check_zonefiles: 2145 task_process_checkzones(nsd, udb, last_task, TASKLIST(task)); 2146 break; 2147 case task_write_zonefiles: 2148 task_process_writezones(nsd, TASKLIST(task)); 2149 break; 2150 case task_set_verbosity: 2151 task_process_set_verbosity(TASKLIST(task)); 2152 break; 2153 case task_add_zone: 2154 task_process_add_zone(nsd, udb, last_task, TASKLIST(task)); 2155 break; 2156 case task_del_zone: 2157 task_process_del_zone(nsd, TASKLIST(task)); 2158 break; 2159 case task_add_key: 2160 task_process_add_key(nsd, TASKLIST(task)); 2161 break; 2162 case task_del_key: 2163 task_process_del_key(nsd, TASKLIST(task)); 2164 break; 2165 case task_add_pattern: 2166 task_process_add_pattern(nsd, TASKLIST(task)); 2167 break; 2168 case task_del_pattern: 2169 task_process_del_pattern(nsd, TASKLIST(task)); 2170 break; 2171 case task_opt_change: 2172 task_process_opt_change(nsd, TASKLIST(task)); 2173 break; 2174#ifdef USE_ZONE_STATS 2175 case task_zonestat_inc: 2176 task_process_zonestat_inc(nsd, udb, last_task, TASKLIST(task)); 2177 break; 2178#endif 2179 case task_apply_xfr: 2180 task_process_apply_xfr(nsd, udb, last_task, task); 2181 break; 2182 case task_add_cookie_secret: 2183 task_process_add_cookie_secret(nsd, TASKLIST(task)); 2184 break; 2185 case task_drop_cookie_secret: 2186 task_process_drop_cookie_secret(nsd, TASKLIST(task)); 2187 break; 2188 case task_activate_cookie_secret: 2189 task_process_activate_cookie_secret(nsd, TASKLIST(task)); 2190 break; 2191 default: 2192 log_msg(LOG_WARNING, "unhandled task in reload type %d", 2193 (int)TASKLIST(task)->task_type); 2194 break; 2195 } 2196 udb_ptr_free_space(task, udb, TASKLIST(task)->size); 2197} 2198