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