Bug Summary

File:src/usr.sbin/nsd/difffile.c
Warning:line 1397, column 4
Dereference of null pointer (loaded from field 'base')

Annotated Source Code

Press '?' to see keyboard shortcuts

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