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