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