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