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