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