1 /*------------------------------------------------------------------------------
2 *
3 * Copyright (c) 2011-2021, EURid vzw. All rights reserved.
4 * The YADIFA TM software product is provided under the BSD 3-clause license:
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * * Neither the name of EURid nor the names of its contributors may be
16 * used to endorse or promote products derived from this software
17 * without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 *
31 *------------------------------------------------------------------------------
32 *
33 */
34
35 /** @defgroup
36 * @ingroup dnsdb
37 * @brief
38 *
39 *
40 *
41 * @{
42 */
43 /*------------------------------------------------------------------------------
44 *
45 * USE INCLUDES */
46 #include "dnsdb/dnsdb-config.h"
47 #include <stdio.h>
48 #include <stdlib.h>
49
50 #include <dnscore/dnscore.h>
51 #include <dnscore/logger.h>
52 #include <dnscore/timems.h>
53 #include <dnscore/rfc.h>
54
55 #include "dnsdb/zdb_types.h"
56 #include "dnsdb/zdb_icmtl.h"
57
58 #include "dnsdb/zdb-packed-ttlrdata.h"
59
60 #include "dnsdb/dnssec.h"
61 #include "dnsdb/zdb_record.h"
62 #include "dnsdb/dnssec-keystore.h"
63 #include <dnscore/dnskey-signature.h>
64 #include <dnscore/base32hex.h>
65
66 #include "dnsdb/zdb_zone_label_iterator.h"
67
68 #include "dnsdb/zdb-zone-maintenance.h"
69
70 extern logger_handle* g_database_logger;
71 #define MODULE_MSG_HANDLE g_database_logger
72
73 #define ZDB_ZONE_MAINTENANCE_DETAILED_LOG 0 /// @note 20180615 edf -- heavy, use with care
74 #define ZDB_ZONE_MAINTENANCE_IGNORE_TIME_QUOTA 0
75 #define DEBUG_SIGNATURE_REFRESH 0
76
77 #if ZDB_ZONE_MAINTENANCE_DETAILED_LOG
78 #pragma message("WARNING: ZDB_ZONE_MAINTENANCE_DETAILED_LOG is not set to 0")
79 #endif
80
81 #if ZDB_ZONE_MAINTENANCE_IGNORE_TIME_QUOTA
82 #pragma message("WARNING: ZDB_ZONE_MAINTENANCE_IGNORE_TIME_QUOTA is not set to 0")
83 #endif
84
85 #define ZDB_ZONE_MAINTENANCE_SAME_PASS_CLOSE 1
86 #define ZDB_ZONE_MAINTENANCE_RRSIG_COUNT_THRESHOLD 256 // after that many signatures, stop processing labels
87 #define ZDB_MAINTENANCE_BATCH_TIME_US_MAX 20000 // 10ms
88
89 #if ZDB_ZONE_MAINTENANCE_DETAILED_LOG
90 #pragma message("WARNING: ZDB_ZONE_MAINTENANCE_DETAILED_LOG IS NOT SET TO 0. SET IT BACK TO 0 IT IF YOU DON'T NEED IT!")
91 #pragma message("WARNING: ZDB_ZONE_MAINTENANCE_DETAILED_LOG IS NOT SET TO 0. SET IT BACK TO 0 IT IF YOU DON'T NEED IT!")
92 #pragma message("WARNING: ZDB_ZONE_MAINTENANCE_DETAILED_LOG IS NOT SET TO 0. SET IT BACK TO 0 IT IF YOU DON'T NEED IT!")
93 #endif
94
95 static bool
zdb_zone_maintenance_validate_sign_chain_store(zdb_zone_maintenance_ctx * mctx,zone_diff * diff,zdb_zone * zone,ptr_vector * rrset_to_sign,ptr_vector * remove,ptr_vector * add)96 zdb_zone_maintenance_validate_sign_chain_store(zdb_zone_maintenance_ctx *mctx, zone_diff *diff, zdb_zone *zone, ptr_vector *rrset_to_sign, ptr_vector *remove, ptr_vector *add)
97 {
98 ya_result ret;
99
100 log_debug("maintenance: validate-sign-chain-store: %{dnsname}", zone->origin);
101
102 #if ZDB_ZONE_MAINTENANCE_DETAILED_LOG
103 for(int i = 0; i <= ptr_vector_last_index(remove); ++i)
104 {
105 zone_diff_label_rr *rr = (zone_diff_label_rr*)ptr_vector_get(remove, i);
106 rdata_desc rd = {rr->rtype, rr->rdata_size, rr->rdata};
107
108 log_debug("before-validate: %{dnsname}: - %{dnsname} %9i %{typerdatadesc} ; (W+R)", zone->origin, rr->fqdn, rr->ttl, &rd);
109 }
110
111 for(int i = 0; i <= ptr_vector_last_index(add); ++i)
112 {
113 zone_diff_label_rr *rr = (zone_diff_label_rr*)ptr_vector_get(add, i);
114 rdata_desc rd = {rr->rtype, rr->rdata_size, rr->rdata};
115
116 log_debug("before-validate: %{dnsname}: + %{dnsname} %9i %{typerdatadesc} ; (W+R)", zone->origin, rr->fqdn, rr->ttl, &rd);
117 }
118 #endif
119
120 if(ISOK(ret = zone_diff_validate(diff)))
121 {
122 #if DEBUG
123 log_debug("maintenance: %{dnsname}: diff validated", diff->origin);
124 #endif
125 // store changes in vectors and get the RR sets to sign
126
127 #if ZDB_ZONE_MAINTENANCE_DETAILED_LOG
128 for(int i = 0; i <= ptr_vector_last_index(remove); ++i)
129 {
130 zone_diff_label_rr *rr = (zone_diff_label_rr*)ptr_vector_get(remove, i);
131 rdata_desc rd = {rr->rtype, rr->rdata_size, rr->rdata};
132
133 log_debug("before-get-changes: %{dnsname}: - %{dnsname} %9i %{typerdatadesc} ; (W+R)", zone->origin, rr->fqdn, rr->ttl, &rd);
134 }
135
136 for(int i = 0; i <= ptr_vector_last_index(add); ++i)
137 {
138 zone_diff_label_rr *rr = (zone_diff_label_rr*)ptr_vector_get(add, i);
139 rdata_desc rd = {rr->rtype, rr->rdata_size, rr->rdata};
140
141 log_debug("before-get-changes: %{dnsname}: + %{dnsname} %9i %{typerdatadesc} ; (W+R)", zone->origin, rr->fqdn, rr->ttl, &rd);
142 }
143 #endif
144 ptr_vector ksks = PTR_VECTOR_EMPTY;
145 ptr_vector zsks = PTR_VECTOR_EMPTY;
146
147 s32 mandatory_changes = zone_diff_get_changes(diff, rrset_to_sign, &ksks, &zsks, remove, add);
148
149 // sign the records, store the changes in vectors
150
151 #if ZDB_ZONE_MAINTENANCE_DETAILED_LOG
152 for(int i = 0; i <= ptr_vector_last_index(remove); ++i)
153 {
154 zone_diff_label_rr *rr = (zone_diff_label_rr*)ptr_vector_get(remove, i);
155 rdata_desc rd = {rr->rtype, rr->rdata_size, rr->rdata};
156
157 log_debug("before-diff-sign: %{dnsname}: - %{dnsname} %9i %{typerdatadesc} ; (W+R)", zone->origin, rr->fqdn, rr->ttl, &rd);
158 }
159
160 for(int i = 0; i <= ptr_vector_last_index(add); ++i)
161 {
162 zone_diff_label_rr *rr = (zone_diff_label_rr*)ptr_vector_get(add, i);
163 rdata_desc rd = {rr->rtype, rr->rdata_size, rr->rdata};
164
165 log_debug("before-diff-sign: %{dnsname}: + %{dnsname} %9i %{typerdatadesc} ; (W+R)", zone->origin, rr->fqdn, rr->ttl, &rd);
166 }
167 #endif
168
169 bool relevant_update = (mandatory_changes > 0);
170
171 if(relevant_update)
172 {
173 /*
174 * Signs the RRSETs using the ksk & zsk, applies the changes in remove and add vectors
175 */
176
177 dnssec_chain_store_diff(&mctx->nsec_chain_updater, diff, &zsks, remove, add);
178
179 zone_diff_sign(diff, zone, rrset_to_sign, &ksks, &zsks, remove, add);
180
181 #if ZDB_ZONE_MAINTENANCE_DETAILED_LOG
182 for(int i = 0; i <= ptr_vector_last_index(remove); ++i)
183 {
184 zone_diff_label_rr *rr = (zone_diff_label_rr*)ptr_vector_get(remove, i);
185 rdata_desc rd = {rr->rtype, rr->rdata_size, rr->rdata};
186
187 log_debug("before-nsec3-chain-store-diff: %{dnsname}: - [%02x] %{dnsname} %9i %{typerdatadesc} ; (W+R)", zone->origin, rr->state, rr->fqdn, rr->ttl, &rd);
188 }
189
190 for(int i = 0; i <= ptr_vector_last_index(add); ++i)
191 {
192 zone_diff_label_rr *rr = (zone_diff_label_rr*)ptr_vector_get(add, i);
193 rdata_desc rd = {rr->rtype, rr->rdata_size, rr->rdata};
194
195 log_debug("before-nsec3-chain-store-diff: %{dnsname}: + [%02x] %{dnsname} %9i %{typerdatadesc} ; (W+R)", zone->origin, rr->state, rr->fqdn, rr->ttl, &rd);
196 }
197 #endif
198 // zone_diff_get_chain_changes(diff, &dc);
199
200 dnssec_chain_store_diff(&mctx->nsec3_chains_updater, diff, &zsks, remove, add);
201
202 #if ZDB_ZONE_MAINTENANCE_DETAILED_LOG
203 for(int i = 0; i <= ptr_vector_last_index(remove); ++i)
204 {
205 zone_diff_label_rr *rr = (zone_diff_label_rr*)ptr_vector_get(remove, i);
206 rdata_desc rd = {rr->rtype, rr->rdata_size, rr->rdata};
207
208 log_debug("when-all-is-said-and-done: %{dnsname}: - [%02x] %{dnsname} %9i %{typerdatadesc} ; (W+R)", zone->origin, rr->state, rr->fqdn, rr->ttl, &rd);
209 }
210
211 for(int i = 0; i <= ptr_vector_last_index(add); ++i)
212 {
213 zone_diff_label_rr *rr = (zone_diff_label_rr*)ptr_vector_get(add, i);
214 rdata_desc rd = {rr->rtype, rr->rdata_size, rr->rdata};
215
216 log_debug("when-all-is-said-and-done: %{dnsname}: + [%02x] %{dnsname} %9i %{typerdatadesc} ; (W+R)", zone->origin, rr->state, rr->fqdn, rr->ttl, &rd);
217 }
218 #endif
219 }
220
221 dnssec_keystore_release_keys_from_vector(&zsks);
222 dnssec_keystore_release_keys_from_vector(&ksks);
223
224 ptr_vector_destroy(&zsks);
225 ptr_vector_destroy(&ksks);
226
227 return relevant_update;
228 }
229 else
230 {
231 log_err("maintenance: %{dnsname}: could not validate the diff", diff->origin);
232
233 return FALSE;
234 }
235 }
236
237 static void
zdb_zone_maintenance_ctx_init(zdb_zone_maintenance_ctx * mctx,zdb_zone * zone)238 zdb_zone_maintenance_ctx_init(zdb_zone_maintenance_ctx *mctx, zdb_zone *zone)
239 {
240 log_debug("maintenance: %{dnsname}: context init", zone->origin);
241 ZEROMEMORY(mctx, sizeof(zdb_zone_maintenance_ctx));
242 mctx->zone = zone;
243 }
244
245 static void
zdb_zone_maintenance_ctx_finalize(zdb_zone_maintenance_ctx * mctx)246 zdb_zone_maintenance_ctx_finalize(zdb_zone_maintenance_ctx *mctx)
247 {
248 log_debug("maintenance: %{dnsname}: context finalize", mctx->zone->origin);
249
250 log_debug("maintenance: %{dnsname}: context finalize: clearing KSK", mctx->zone->origin);
251
252 dnssec_keystore_release_keys_from_vector(&mctx->ksks);
253
254 log_debug("maintenance: %{dnsname}: context finalize: clearing ZSK", mctx->zone->origin);
255
256 dnssec_keystore_release_keys_from_vector(&mctx->zsks);
257
258 ptr_vector_destroy(&mctx->ksks);
259 ptr_vector_destroy(&mctx->zsks);
260
261 log_debug("maintenance: %{dnsname}: context finalize: finalising NSEC chain", mctx->zone->origin);
262
263 dnssec_chain_finalize(&mctx->nsec_chain_updater);
264
265 log_debug("maintenance: %{dnsname}: context finalize: finalising NSEC3 chain", mctx->zone->origin);
266
267 dnssec_chain_finalize(&mctx->nsec3_chains_updater);
268
269 log_debug("maintenance: %{dnsname}: context finalize: releasing active keys", mctx->zone->origin);
270
271 zdb_zone_release_active_keys(mctx->keys);
272
273 mctx->keys = NULL;
274
275 log_debug("maintenance: %{dnsname}: context finalize done", mctx->zone->origin);
276 }
277
278 /**
279 * Updates the signatures of a zone incrementally.
280 * Each call goes a bit further.
281 *
282 * @param zone
283 * @param signature_count_loose_limit
284 * @param present_signatures_are_verified
285 * @return
286 */
287
288 static ya_result
zdb_zone_maintenance_from(zdb_zone * zone,u8 * from_fqdn,size_t from_fqdn_size,s64 maxus,s32 rrsigcountmax)289 zdb_zone_maintenance_from(zdb_zone* zone, u8 *from_fqdn, size_t from_fqdn_size, s64 maxus, s32 rrsigcountmax)
290 {
291 yassert(((from_fqdn != NULL) && (from_fqdn_size > 0)) || ((from_fqdn == NULL) && (from_fqdn_size == 0)));
292 //bool from_fqdn_is_binary_digest = FALSE;
293
294 if(!zdb_zone_is_maintained(zone))
295 {
296 log_debug("maintenance: %{dnsname}: not maintained", zone->origin);
297 return ZDB_ERROR_ZONE_NOT_MAINTAINED;
298 }
299
300 u8 current_owner;
301 u8 current_reserved_owner;
302
303 while(!zdb_zone_try_double_lock_ex(zone, ZDB_ZONE_MUTEX_SIMPLEREADER, ZDB_ZONE_MUTEX_RRSIG_UPDATER, ¤t_owner, ¤t_reserved_owner))
304 {
305 log_debug("maintenance: %{dnsname}: cannot double-lock the zone for maintenance (%02x, %04x, %02x, %02x)", zone->origin, zone->_flags, zone->_status, current_owner, current_reserved_owner);
306
307 if((current_owner == ZDB_ZONE_MUTEX_RRSIG_UPDATER) || (current_reserved_owner == ZDB_ZONE_MUTEX_RRSIG_UPDATER))
308 {
309 // the zone is already being signed
310 return ZDB_ERROR_ZONE_IS_ALREADY_BEING_SIGNED;
311 }
312 else
313 {
314 // wait for the condition
315 mutex_lock(&zone->lock_mutex);
316 cond_timedwait(&zone->lock_cond, &zone->lock_mutex, 1000);
317 mutex_unlock(&zone->lock_mutex);
318 }
319 }
320
321 if((from_fqdn != NULL) && (from_fqdn[0] != 0))
322 {
323 log_debug("maintenance: %{dnsname}: starting from %{dnsname}", zone->origin, from_fqdn);
324 }
325 else
326 {
327 log_debug("maintenance: %{dnsname}: starting from the apex", zone->origin);
328 zdb_zone_clear_maintenance_queued(zone);
329 }
330
331 s64 start_time = timeus();
332
333 int maintenance_rrsig_count = 0;
334 int maintenance_nsec_count = 0;
335 int maintenance_nsec3_count = 0;
336 int maintenance_generate_nsec3_rrsig_count = 0;
337 int maintenance_generate_nsec3param_rrsig_count = 0;
338 bool nsecchainstate_changed = FALSE;
339
340 zdb_zone_maintenance_ctx mctx;
341 zdb_zone_maintenance_ctx_init(&mctx, zone);
342
343 u8 maintain_mode = zone_get_maintain_mode(zone);
344
345 zone_diff diff;
346 zone_diff_init(&diff, zone, TRUE);
347
348 switch(maintain_mode)
349 {
350 case ZDB_ZONE_MAINTAIN_NSEC3:
351 case ZDB_ZONE_MAINTAIN_NSEC3_OPTOUT:
352 {
353 diff.maintain_nsec3 = TRUE;
354 break;
355 }
356 case ZDB_ZONE_MAINTAIN_NSEC:
357 {
358 diff.maintain_nsec = TRUE;
359 break;
360 }
361 default:
362 {
363 break;
364 }
365 }
366
367 dnssec_chain_init(&mctx.nsec_chain_updater, dynupdate_nsec_chain_get_vtbl(), &diff);
368 if((maintain_mode & ZDB_ZONE_MAINTAIN_NSEC3_OPTOUT) != ZDB_ZONE_MAINTAIN_NSEC3_OPTOUT)
369 {
370 dnssec_chain_init(&mctx.nsec3_chains_updater, dynupdate_nsec3_chain_get_vtbl(), &diff);
371 }
372 else
373 {
374 dnssec_chain_init(&mctx.nsec3_chains_updater, dynupdate_nsec3_optout_chain_get_vtbl(), &diff);
375 }
376
377 // load all the active keys from the keyring of the zone
378 // compute a mask for all the keys that are private (usable)
379
380 log_debug("maintenance: %{dnsname}: fetching keys", zone->origin);
381
382 ptr_vector_init(&mctx.ksks);
383 ptr_vector_init(&mctx.zsks);
384 zone_diff_store_diff_dnskey_get_keys(&diff, &mctx.ksks, &mctx.zsks);
385
386 u64 ksk_mask = 0;
387 u64 zsk_mask = 0;
388
389 mctx.now = time(NULL);
390
391 for(int i = 0; i <= ptr_vector_last_index(&mctx.ksks); ++i)
392 {
393 const dnssec_key *key = (const dnssec_key*)ptr_vector_get(&mctx.ksks, i);
394
395 if(dnskey_is_private(key) && dnskey_is_activated(key, mctx.now))
396 {
397 ksk_mask |= 1ULL << i;
398 log_debug("maintenance: DNSKEY: %{dnsname}+%03d+%05d/%d is a private KSK", dnskey_get_domain(key), dnskey_get_algorithm(key), dnskey_get_tag_const(key), ntohs(dnskey_get_flags(key)));
399 }
400 else
401 {
402 log_debug("maintenance: DNSKEY: %{dnsname}+%03d+%05d/%d is not a private KSK", dnskey_get_domain(key), dnskey_get_algorithm(key), dnskey_get_tag_const(key), ntohs(dnskey_get_flags(key)));
403 }
404 }
405
406 for(int i = 0; i <= ptr_vector_last_index(&mctx.zsks); ++i)
407 {
408 const dnssec_key *key = (const dnssec_key*)ptr_vector_get(&mctx.zsks, i);
409
410 if(dnskey_is_private(key) && dnskey_is_activated(key, mctx.now))
411 {
412 zsk_mask |= 1ULL << i;
413 log_debug("maintenance: DNSKEY: %{dnsname}+%03d+%05d/%d is a private ZSK", dnskey_get_domain(key), dnskey_get_algorithm(key), dnskey_get_tag_const(key), ntohs(dnskey_get_flags(key)));
414 }
415 else
416 {
417 log_debug("maintenance: DNSKEY: %{dnsname}+%03d+%05d/%d is not a private ZSK", dnskey_get_domain(key), dnskey_get_algorithm(key), dnskey_get_tag_const(key), ntohs(dnskey_get_flags(key)));
418 }
419 }
420
421 mctx.ksk_mask = ksk_mask;
422 mctx.zsk_mask = zsk_mask;
423 mctx.ksk_count = ptr_vector_size(&mctx.ksks);
424 mctx.zsk_count = ptr_vector_size(&mctx.zsks);
425
426 log_debug("maintenance: DNSKEY: %{dnsname}: ksk mask=%p, count=%llx, zsk mask=%p, count = %i",
427 mctx.zone->origin,
428 mctx.ksk_mask, mctx.ksk_count, mctx.zsk_mask, mctx.zsk_count);
429
430 if(mctx.zsk_mask == 0)
431 {
432 zdb_zone_double_unlock(zone, ZDB_ZONE_MUTEX_SIMPLEREADER, ZDB_ZONE_MUTEX_RRSIG_UPDATER);
433
434 zone_diff_finalize(&diff);
435 zdb_zone_maintenance_ctx_finalize(&mctx);
436
437 return ZDB_ERROR_ZONE_NO_ZSK_PRIVATE_KEY_FILE;
438 }
439
440 ptr_vector remove = PTR_VECTOR_EMPTY;
441 ptr_vector add = PTR_VECTOR_EMPTY;
442
443 int loop_iterations = 0; // prevents loops to break in first iteration when the system is too slow (forever retrying)
444
445 bool diff_has_changes = FALSE;
446 bool actions_happened = FALSE;
447 bool last_label_of_zone_reached = FALSE;
448 //bool soa_updated = FALSE;
449
450 diff.has_active_ksk = ksk_mask != 0;
451 diff.has_active_zsk = zsk_mask != 0;
452
453 // the maximum number of labels we are allowed to process in one pass
454
455 int labels_at_once = mctx.zone->progressive_signature_update.labels_at_once;
456
457 ya_result ret;
458
459 log_debug("maintenance: %{dnsname}: has %i KSKs and %i ZSKs"/* (%i and %i)"*/, zone->origin, mctx.ksk_count, mctx.zsk_count/*, mctx_ksk_count, mctx_zsk_count*/);
460
461 // no rrset to sign, for now
462
463 ptr_vector rrset_to_sign = PTR_VECTOR_EMPTY;
464
465 // get a copy of the APEX
466
467 zone_diff_fqdn *apex = zone_diff_add_static_fqdn(&diff, diff.origin, zone->apex);
468
469 zdb_zone_label_iterator iter;
470
471 // initialises the "start-from" iterator
472
473 if(zone->progressive_signature_update.chain_index < 0)
474 {
475 if((from_fqdn == NULL) || (*from_fqdn == 0))
476 {
477 zdb_zone_label_iterator_init(&iter, zone);
478 // also reset the earliest resignature
479 mctx.zone->progressive_signature_update.earliest_signature_expiration = MAX_S32;
480 mctx.zone->progressive_signature_update.labels_at_once = ZDB_ZONE_MAINTENANCE_LABELS_AT_ONCE_DEFAULT;
481 }
482 else
483 {
484 zdb_zone_label_iterator_init_from(&iter, zone, from_fqdn);
485 }
486 }
487
488 // get the nsec status
489
490 nsec_zone_get_status(zone, &mctx.nsec_chain_status);
491 dnssec_chain_add_chain(&mctx.nsec_chain_updater, (dnssec_chain_head_t)zone->nsec.nsec, (mctx.nsec_chain_status & NSEC_ZONE_REMOVING) != 0);
492
493 // get all nsec3 statuses
494
495 mctx.nsec3_chain_count = MIN(nsec3_zone_get_chain_count(zone), ZDB_ZONE_MAINTENANCE_NSEC3CHAIN_MAX);
496 nsec3_zone_get_chains(zone, mctx.nsec3_chain, mctx.nsec3_chain_count);
497 for(u8 nsec3_chain_index = 0; nsec3_chain_index < mctx.nsec3_chain_count; ++nsec3_chain_index)
498 {
499 const u8 *nsec3param_rdata = mctx.nsec3_chain[nsec3_chain_index]->rdata;
500 nsec3_zone_get_status_from_rdata(zone, nsec3param_rdata, NSEC3_ZONE_RDATA_SIZE(mctx.nsec3_chain[nsec3_chain_index]), &mctx.nsec3_chain_status[nsec3_chain_index]);
501 dnssec_chain_add_chain(&mctx.nsec3_chains_updater, (dnssec_chain_head_t)mctx.nsec3_chain[nsec3_chain_index], (mctx.nsec3_chain_status[nsec3_chain_index] & NSEC3_ZONE_REMOVING) != 0);
502 }
503
504 /**************************************************************************************************************
505 *
506 * "Normal" database (chain_index < 0)
507 *
508 **************************************************************************************************************/
509
510 ptr_vector rrset_vector = PTR_VECTOR_EMPTY;
511 ptr_vector candidates = PTR_VECTOR_EMPTY;
512 ptr_vector chain_candidates = PTR_VECTOR_EMPTY;
513
514 int labels_to_process_count = labels_at_once;
515
516 u8 from_digest[256];
517
518 if(zone->progressive_signature_update.chain_index < 0)
519 {
520 for(;;)
521 {
522 if(zdb_zone_label_iterator_hasnext(&iter))
523 {
524 memcpy(&mctx.fqdn_stack.labels[0], &iter.dnslabels[0], (iter.top + 1) * sizeof(u8*));
525
526 mctx.fqdn_stack.size = iter.top; // MUST be called before zdb_zone_label_iterator_next(&iter)
527
528 zdb_rr_label *rr_label = zdb_zone_label_iterator_next(&iter);
529
530 // if we are under delegation : don't stop (resuming from under a delegation would require to fetch more data
531
532 bool under_delegation = ZDB_LABEL_UNDERDELEGATION(rr_label);
533
534 dnsname_stack_to_dnsname(&mctx.fqdn_stack, mctx.fqdn);
535
536 // if too many iterations : break
537
538 s64 now = timeus();
539
540 --labels_to_process_count;
541
542 if(!under_delegation)
543 {
544 if(labels_to_process_count < 0)
545 {
546 #if DEBUG
547 double dt = now - start_time;
548 dt /= ONE_SECOND_US_F;
549 log_debug("maintenance: %{dnsname}: time elapsed (%fs): fqdn quota spent: next one will be %{dnsnamestack}",
550 zone->origin, dt, &mctx.fqdn_stack);
551 #endif
552 break;
553 }
554
555 #if !ZDB_ZONE_MAINTENANCE_IGNORE_TIME_QUOTA
556 if((loop_iterations > 0) && (now - start_time >= maxus))
557 {
558 // too much time taken already
559 #if DEBUG
560 double dt = now - start_time;
561 dt /= ONE_SECOND_US_F;
562 log_debug("maintenance: %{dnsname}: time elapsed (%fs): time spent: next one will be %{dnsnamestack}",
563 zone->origin, dt, &mctx.fqdn_stack);
564 #endif
565 break;
566 }
567 #endif
568 }
569
570 ++loop_iterations;
571 #if DEBUG
572 log_debug2("maintenance: %{dnsname}: at %{dnsnamestack}", zone->origin, &mctx.fqdn_stack);
573 #endif
574 mctx.label = rr_label;
575
576 zone_diff_fqdn *diff_fqdn = zone_diff_add_static_fqdn(&diff, mctx.fqdn, rr_label);
577
578 maintenance_rrsig_count += zdb_zone_maintenance_rrsig(&mctx, diff_fqdn, &rrset_to_sign);
579 maintenance_nsec_count += zdb_zone_maintenance_nsec(&mctx, diff_fqdn, &rrset_to_sign);
580 maintenance_nsec3_count += zdb_zone_maintenance_nsec3(&mctx, diff_fqdn); // only affects the chain structure, hence the lack of "rrset_to_sign"
581
582 if(maintenance_rrsig_count + maintenance_nsec_count + maintenance_nsec3_count > 0)
583 {
584 // ++labels_to_process_count;
585 actions_happened = TRUE;
586
587 // if too many signatures are already to be generated, don't process more labels
588
589 if(maintenance_rrsig_count > rrsigcountmax)
590 {
591 labels_at_once = loop_iterations; // update the amount of labels projected in this update
592 labels_to_process_count = 0; // prevents doing more labels
593 }
594 }
595 }
596 else
597 {
598 #if DEBUG
599 log_debug("maintenance: %{dnsname}: reached the last label", zone->origin);
600 #endif
601 if(mctx.nsec3_chain_count > 0)
602 {
603 // if the chain is not empty in the zone
604
605 if(mctx.zone->nsec.nsec3->items != NULL)
606 {
607 log_debug("maintenance: %{dnsname}: will process NSEC3 chain(s)", zone->origin);
608 zone->progressive_signature_update.chain_index = 0;
609 nsec3_node *first = nsec3_get_first(&mctx.zone->nsec.nsec3->items);
610
611 memcpy(from_digest, first->digest, first->digest[0] + 1);
612 from_digest[first->digest[0] + 1] = 0;
613 //from_fqdn_is_binary_digest = TRUE;
614
615 log_debug("maintenance: %{dnsname}: starting work on NSEC3 chain %i", zone->origin, zone->progressive_signature_update.chain_index);
616 }
617 else
618 {
619 #if DEBUG
620 log_debug("maintenance: %{dnsname}: no chain to process after the last label", zone->origin);
621 #endif
622 last_label_of_zone_reached = TRUE;
623 }
624 }
625 else
626 {
627 #if DEBUG
628 log_debug("maintenance: %{dnsname}: no chain in the zone to be processed after the last label", zone->origin);
629 #endif
630 last_label_of_zone_reached = TRUE;
631 }
632
633 break;
634 }
635 } // while has labels ..
636 }
637 else
638 {
639 // if we are working in the NSEC3 chains, the index is >= 0
640 // then we also want to decode the base32hex encoding to work on the binary digest
641
642 from_digest[0] = base32hex_decode((const char*)&from_fqdn[1], from_fqdn[0], &from_digest[1]);
643 //from_fqdn_is_binary_digest = TRUE;
644
645 log_debug("maintenance: %{dnsname}: starting work on NSEC3 chain %i", zone->origin, zone->progressive_signature_update.chain_index);
646 }
647
648 // while no more normal labels are to be processed but NSEC3 chains are remaining
649
650 /**************************************************************************************************************
651 *
652 * "NSEC3" database
653 *
654 **************************************************************************************************************/
655
656 while(zone->progressive_signature_update.chain_index >= 0)
657 {
658 loop_iterations = 0;
659
660 //yassert(from_fqdn_is_binary_digest);
661
662 nsec3_zone *n3e = zdb_zone_get_nsec3chain(mctx.zone, zone->progressive_signature_update.chain_index);
663
664 nsec3_iterator iter;
665 nsec3_iterator_init_from(&n3e->items, &iter, from_digest); // binary form
666
667 for(;;)
668 {
669 if(nsec3_iterator_hasnext(&iter))
670 {
671 nsec3_zone_item *item = nsec3_iterator_next_node(&iter);
672 //u8 digest_len = NSEC3_NODE_DIGEST_SIZE(item);
673
674 // check signature
675 // mark signature for update
676 // actions_happened = TRUE;
677
678 s64 now = timeus();
679
680 if(item->rc <= 0)
681 {
682 double dt = now - start_time;
683 dt /= ONE_SECOND_US_F;
684 log_debug("maintenance: %{dnsname}: time elapsed (%fs): %{digest32h}.%{dnsname} has no owner (rc=%i, sc=%i)",
685 zone->origin, dt, item->digest, zone->origin, item->rc, item->sc);
686 }
687
688 --labels_to_process_count;
689
690 if(labels_to_process_count < 0)
691 {
692 #if DEBUG
693 double dt = now - start_time;
694 dt /= ONE_SECOND_US_F;
695 log_debug("maintenance: %{dnsname}: time elapsed (%fs): fqdn quota spent: next one will be %{digest32h}.%{dnsname}",
696 zone->origin, dt, item->digest, zone->origin);
697 #endif
698 u8 digest_len = NSEC3_NODE_DIGEST_SIZE(item);
699 mctx.fqdn[0] = base32hex_encode(NSEC3_NODE_DIGEST_PTR(item), digest_len, (char*)&mctx.fqdn[1]);
700 dnsname_copy(&mctx.fqdn[mctx.fqdn[0] + 1], zone->origin);
701
702 /************************************
703 * GOTO, breaking two loops at once.*
704 ************************************/
705
706 goto zdb_zone_maintenance_from_chain_iteration_loop_break;
707 }
708
709 #if !ZDB_ZONE_MAINTENANCE_IGNORE_TIME_QUOTA
710 if((loop_iterations > 0) && (now - start_time >= maxus))
711 {
712 // too much time taken already
713 #if DEBUG
714 double dt = now - start_time;
715 dt /= ONE_SECOND_US_F;
716 log_debug("maintenance: %{dnsname}: time elapsed (%fs): time spent: next one will be %{digest32h}.%{dnsname}",
717 zone->origin, dt, item->digest, zone->origin);
718 #endif
719 u8 digest_len = NSEC3_NODE_DIGEST_SIZE(item);
720 mctx.fqdn[0] = base32hex_encode(NSEC3_NODE_DIGEST_PTR(item), digest_len, (char*)&mctx.fqdn[1]);
721 dnsname_copy(&mctx.fqdn[mctx.fqdn[0] + 1], zone->origin);
722
723 /************************************
724 * GOTO, breaking two loops at once.*
725 ************************************/
726
727 goto zdb_zone_maintenance_from_chain_iteration_loop_break;
728 }
729 #endif
730 intptr nsec3_key_mask;
731
732 zdb_packed_ttlrdata *rrsig = item->rrsig;
733
734 bool delete_nsec3_rrsig = FALSE;
735
736 if(rrsig != NULL)
737 {
738 nsec3_key_mask = 0;
739 u32 key_matched = 0;
740
741 do
742 {
743 s32 key_index = -2;
744
745 // returns TRUE iff the signature needs to be removed, that covers "key not found"
746
747 bool rrsig_should_remove_signature_from_rdata_result = rrsig_should_remove_signature_from_rdata(
748 ZDB_PACKEDRECORD_PTR_RDATAPTR(rrsig), ZDB_PACKEDRECORD_PTR_RDATASIZE(rrsig),
749 &mctx.zsks, mctx.now, zone->sig_validity_regeneration_seconds, &key_index);
750 #if DEBUG_SIGNATURE_REFRESH
751 rdata_desc nsec3_rrsig_desc = {TYPE_RRSIG, ZDB_PACKEDRECORD_PTR_RDATASIZE(rrsig), ZDB_PACKEDRECORD_PTR_RDATAPTR(rrsig)};
752 log_debug("maintenance: %{dnsname}: should-remove: %{digest32h}.%{dnsname} %{typerdatadesc}: %s (%i)", zone->origin, item->digest, zone->origin, &nsec3_rrsig_desc,
753 (rrsig_should_remove_signature_from_rdata_result?"yes":"no"), key_index);
754 #endif
755 if(rrsig_should_remove_signature_from_rdata_result)
756 {
757 if(key_index >= 0)
758 {
759 // RRSIG will be removed, use the key_index to update the mask
760 nsec3_key_mask |= 1LL << key_index;
761 }
762 else
763 {
764 // the key was not found: remove the RRSIG
765 delete_nsec3_rrsig = TRUE; // this enables a "filter out"
766 }
767 }
768 else
769 {
770 key_matched |= 1LL << key_index;
771 }
772
773 rrsig = rrsig->next;
774 }
775 while(rrsig != NULL);
776
777 // keys whose signatures have not been found are added now
778
779 nsec3_key_mask |= key_matched ^ mctx.zsk_mask;
780 }
781 else
782 {
783 nsec3_key_mask = mctx.zsk_mask;
784 }
785 #if DEBUG || DEBUG_SIGNATURE_REFRESH
786 log_debug("maintenance: %{dnsname}: at %{digest32h}.%{dnsname} NSEC3: mask=%p/%p (has signature: %i, key-not-found: %i)",
787 zone->origin, item->digest, zone->origin,
788 nsec3_key_mask, mctx.zsk_mask, (rrsig != NULL), delete_nsec3_rrsig);
789
790 if(rrsig != NULL)
791 {
792 for(zdb_packed_ttlrdata *rr = rrsig; rr != NULL; rr = rr->next)
793 {
794 const void *rdata = ZDB_PACKEDRECORD_PTR_RDATAPTR(rr);
795 u16 rdata_size = ZDB_PACKEDRECORD_PTR_RDATASIZE(rr);
796 log_debug("maintenance: %{dnsname}: at %{digest32h}.%{dnsname} RRSIG: %5i %T -> %T",
797 zone->origin, item->digest, zone->origin,
798 rrsig_get_key_tag_from_rdata(rdata, rdata_size),
799 rrsig_get_valid_from_from_rdata(rdata, rdata_size),
800 rrsig_get_valid_until_from_rdata(rdata, rdata_size));
801 }
802 }
803 #endif
804 if((nsec3_key_mask != 0) || delete_nsec3_rrsig)
805 {
806 // generate signature or delete signatures
807
808 zone_diff_fqdn_rr_set *nsec3_diff_rrset = NULL;
809 #if DEBUG
810 zone_diff_fqdn* nsec3_diff_fqdn =
811 #endif
812 zone_diff_add_nsec3_ex(&diff, &mctx.zsks, mctx.zone->nsec.nsec3, item, mctx.zone->min_ttl, &nsec3_diff_rrset, mctx.now, zone->sig_validity_regeneration_seconds);
813
814 if(nsec3_diff_rrset != NULL)
815 {
816 #if DEBUG
817 log_debug("maintenance: %{dnsname}: %{dnsname}: NSEC3 should be signed", zone->origin, nsec3_diff_fqdn->fqdn);
818 #endif
819 nsec3_diff_rrset->key_mask = nsec3_key_mask;
820
821 ptr_vector_append(&rrset_to_sign, nsec3_diff_rrset);
822 ++maintenance_generate_nsec3_rrsig_count;
823 actions_happened = TRUE;
824 }
825 }
826
827 ++loop_iterations;
828 }
829 else // end of iteration
830 {
831 // if there is another chain, take its first digest (binary form)
832
833 if(++zone->progressive_signature_update.chain_index < mctx.nsec3_chain_count)
834 {
835 n3e = n3e->next;
836
837 if(n3e != NULL)
838 {
839 log_debug("maintenance: %{dnsname}: starting work on NSEC3 chain %i", zone->origin, zone->progressive_signature_update.chain_index);
840
841 nsec3_node *first = nsec3_get_first(&mctx.zone->nsec.nsec3->items);
842 memcpy(from_digest, first->digest, first->digest[0] + 1);
843 from_digest[first->digest[0] + 1] = 0;
844 //from_fqdn_is_binary_digest = TRUE;
845
846 break;
847 }
848 else
849 {
850 log_err("maintenance: %{dnsname}: NSEC3 chain smaller than expected", zone->origin);
851 #if DEBUG
852 log_debug("maintenance: %{dnsname}: no more chain after last label", zone->origin);
853 #endif
854 zone->progressive_signature_update.chain_index = -1;
855 last_label_of_zone_reached = TRUE;
856 mctx.fqdn[0] = 0;
857
858 /************************************
859 * GOTO, breaking two loops at once.*
860 ************************************/
861
862 goto zdb_zone_maintenance_from_chain_iteration_loop_break; // nothing else
863 }
864 }
865 else
866 {
867 zone->progressive_signature_update.chain_index = -1;
868 #if DEBUG
869 log_debug("maintenance: %{dnsname}: nothing to do after last label (NSEC3 rrsig to do: %i)", zone->origin, maintenance_generate_nsec3_rrsig_count);
870 #endif
871 last_label_of_zone_reached = TRUE;
872 mctx.fqdn[0] = 0;
873
874 /************************************
875 * GOTO, breaking two loops at once.*
876 ************************************/
877
878 goto zdb_zone_maintenance_from_chain_iteration_loop_break; // nothing else
879 }
880 }
881 } // for
882 } // while
883
884 zdb_zone_maintenance_from_chain_iteration_loop_break:
885
886 #if ZDB_ZONE_MAINTENANCE_DETAILED_LOG
887 log_debug("maintenance: %{dnsname}: last_label_of_zone_reached: %i, rrset_to_sign contains %i items",
888 zone->origin, last_label_of_zone_reached, ptr_vector_size(&rrset_to_sign));
889 #endif
890
891 diff_has_changes |= zone_diff_has_changes(&diff, &rrset_to_sign);
892
893 #if ZDB_ZONE_MAINTENANCE_DETAILED_LOG
894 log_debug("maintenance: %{dnsname}: diff_has_changes: %i, last_label_of_zone_reached: %i, rrset_to_sign contains %i items",
895 zone->origin, diff_has_changes, last_label_of_zone_reached, ptr_vector_size(&rrset_to_sign));
896 #endif
897
898 if(diff_has_changes && !last_label_of_zone_reached)
899 {
900 #if ZDB_ZONE_MAINTENANCE_DETAILED_LOG
901 for(int i = 0; i <= ptr_vector_last_index(&remove); ++i)
902 {
903 zone_diff_label_rr *rr = (zone_diff_label_rr*)ptr_vector_get(&remove, i);
904 rdata_desc rd = {rr->rtype, rr->rdata_size, rr->rdata};
905
906 log_debug("before-validate-sign: %{dnsname}: - %{dnsname} %9i %{typerdatadesc} ; (W+R)", zone->origin, rr->fqdn, rr->ttl, &rd);
907 }
908
909 for(int i = 0; i <= ptr_vector_last_index(&add); ++i)
910 {
911 zone_diff_label_rr *rr = (zone_diff_label_rr*)ptr_vector_get(&add, i);
912 rdata_desc rd = {rr->rtype, rr->rdata_size, rr->rdata};
913
914 log_debug("before-validate-sign: %{dnsname}: + %{dnsname} %9i %{typerdatadesc} ; (W+R)", zone->origin, rr->fqdn, rr->ttl, &rd);
915 }
916 #endif
917 }
918 else // not diff_has_changes
919 {
920 log_debug("maintenance: %{dnsname}: no changes", zone->origin);
921 }
922
923 if(last_label_of_zone_reached)
924 {
925 log_debug("maintenance: %{dnsname}: closing edited chains", zone->origin);
926
927 // add missing NSEC3PARAM
928 // remove TYPE65282
929 // update NSEC3
930 // update signatures
931
932 bool updated = FALSE;
933
934 if(zone_diff_will_have_rrset_type(apex, TYPE_NSEC3CHAINSTATE))
935 {
936 #if DEBUG
937 log_debug("maintenance: %{dnsname}: NSEC3CHAINSTATE will be present", zone->origin);
938 #endif
939 // NSEC3PARAM
940
941 zdb_packed_ttlrdata* nsec3chainstate = zdb_record_find(&zone->apex->resource_record_set, TYPE_NSEC3CHAINSTATE);
942
943 if(nsec3chainstate != NULL)
944 {
945 do
946 {
947 // find the nsec3param matching nsec3chainstate in nsec3param_rrset
948 // if no match has been found, add a new nsec3param
949
950 zone_diff_label_rr *rr = zone_diff_record_add(&diff, zone->apex, zone->origin, TYPE_NSEC3PARAM, 0,
951 ZDB_PACKEDRECORD_PTR_RDATASIZE(nsec3chainstate) - 1,
952 ZDB_PACKEDRECORD_PTR_RDATAPTR(nsec3chainstate)
953 );
954
955 // clears the opt-out flag that exists in the NSEC3CHAINSTATE record
956
957 u8* flagsp = &((u8*)rr->rdata)[1];
958 *flagsp = 0;
959
960 nsec3chainstate = nsec3chainstate->next;
961 }
962 while(nsec3chainstate != NULL);
963
964 yassert(apex != NULL);
965 zone_diff_fqdn_rr_set *nsec3chainstate_rrset = zone_diff_fqdn_rr_set_get(apex, TYPE_NSEC3CHAINSTATE);
966 yassert(nsec3chainstate_rrset != NULL);
967
968 zone_diff_fqdn_rr_set_set_state(nsec3chainstate_rrset, ZONE_DIFF_RR_REMOVE);
969 zone_diff_fqdn_rr_set *nsec3param_rrset = zone_diff_fqdn_rr_set_get(apex, TYPE_NSEC3PARAM);
970 yassert(nsec3param_rrset != NULL);
971 #if DEBUG
972 log_debug("maintenance: %{dnsname}: NSEC3PARAM should be signed", zone->origin);
973 #endif
974 nsec3param_rrset->key_mask = zsk_mask;
975 ptr_vector_append(&rrset_to_sign, nsec3param_rrset);
976
977 ++maintenance_generate_nsec3param_rrsig_count;
978 updated = TRUE;
979 actions_happened = TRUE;
980 }
981 }
982
983 if(zone_diff_will_have_rrset_type(apex, TYPE_NSECCHAINSTATE))
984 {
985 yassert(apex != NULL);
986 zone_diff_fqdn_rr_set *nsecchainstate_rrset = zone_diff_fqdn_rr_set_get(apex, TYPE_NSECCHAINSTATE);
987 yassert(nsecchainstate_rrset != NULL);
988 zone_diff_fqdn_rr_set_set_state(nsecchainstate_rrset, ZONE_DIFF_RR_REMOVE);
989
990 updated = TRUE;
991 nsecchainstate_changed = TRUE;
992 actions_happened = TRUE;
993 }
994
995 if(updated)
996 {
997 diff_has_changes = TRUE;
998
999 zdb_zone_maintenance_nsec(&mctx, apex, NULL);
1000 zdb_zone_maintenance_nsec3(&mctx, apex);
1001 }
1002 }
1003
1004 // if remove contains more than +- SOA and +- SOA RRSIG ...
1005
1006 if(actions_happened)
1007 {
1008 u32 soa_serial = 0;
1009 zdb_packed_ttlrdata* soa = zdb_record_find(&zone->apex->resource_record_set, TYPE_SOA);
1010 if(soa != NULL)
1011 {
1012 //zone_diff_record_remove(&diff, zone->apex, zone->origin, TYPE_SOA, soa->ttl, ZDB_PACKEDRECORD_PTR_RDATASIZE(soa), ZDB_PACKEDRECORD_PTR_RDATAPTR(soa));
1013 zone_diff_record_remove_automated(&diff, zone->apex, zone->origin, TYPE_SOA, soa->ttl, ZDB_PACKEDRECORD_PTR_RDATASIZE(soa), ZDB_PACKEDRECORD_PTR_RDATAPTR(soa));
1014 rr_soa_get_serial(ZDB_PACKEDRECORD_PTR_RDATAPTR(soa), ZDB_PACKEDRECORD_PTR_RDATASIZE(soa), &soa_serial);
1015 }
1016
1017 log_debug("maintenance: %{dnsname}: serial=%u actions: rrsig=%i nsec=%i nsec3=%i nsec3-rrsig=%i nsec3param=%i chain-state=%i", zone->origin,
1018 soa_serial,
1019 maintenance_rrsig_count,
1020 maintenance_nsec_count,
1021 maintenance_nsec3_count,
1022 maintenance_generate_nsec3_rrsig_count,
1023 maintenance_generate_nsec3param_rrsig_count,
1024 nsecchainstate_changed);
1025
1026 if(ISOK(zone_diff_set_soa(&diff, zone->apex)))
1027 {
1028 #if DEBUG
1029 log_debug1("maintenance: %{dnsname}: SOA should be signed", zone->origin);
1030 #endif
1031 yassert(apex != NULL);
1032 zone_diff_fqdn_rr_set *soa_rrset = zone_diff_fqdn_rr_set_get(apex, TYPE_SOA);
1033 soa_rrset->key_mask = zsk_mask;
1034 yassert(soa_rrset != NULL);
1035 ptr_vector_append(&rrset_to_sign, soa_rrset);
1036 }
1037
1038 #if ZDB_ZONE_MAINTENANCE_DETAILED_LOG
1039 for(int i = 0; i <= ptr_vector_last_index(&remove); ++i)
1040 {
1041 zone_diff_label_rr *rr = (zone_diff_label_rr*)ptr_vector_get(&remove, i);
1042 rdata_desc rd = {rr->rtype, rr->rdata_size, rr->rdata};
1043 log_debug("before-validate-sign: %{dnsname}: - %{dnsname} %9i %{typerdatadesc} ; (W+R)", zone->origin, rr->fqdn, rr->ttl, &rd);
1044 }
1045
1046 for(int i = 0; i <= ptr_vector_last_index(&add); ++i)
1047 {
1048 zone_diff_label_rr *rr = (zone_diff_label_rr*)ptr_vector_get(&add, i);
1049 rdata_desc rd = {rr->rtype, rr->rdata_size, rr->rdata};
1050 log_debug("before-validate-sign: %{dnsname}: + %{dnsname} %9i %{typerdatadesc} ; (W+R)", zone->origin, rr->fqdn, rr->ttl, &rd);
1051 }
1052 #endif
1053 /*
1054 * Does validation checks on the update.
1055 * Generates signatures for the specified RRSETs.
1056 */
1057
1058 diff_has_changes = zdb_zone_maintenance_validate_sign_chain_store(&mctx, &diff, zone, &rrset_to_sign, &remove, &add);
1059
1060 if(!diff_has_changes)
1061 {
1062 log_debug("maintenance: %{dnsname}: update contains nothing", zone->origin);
1063 }
1064
1065 #if ZDB_ZONE_MAINTENANCE_DETAILED_LOG
1066 for(int i = 0; i <= ptr_vector_last_index(&remove); ++i)
1067 {
1068 zone_diff_label_rr *rr = (zone_diff_label_rr*)ptr_vector_get(&remove, i);
1069 rdata_desc rd = {rr->rtype, rr->rdata_size, rr->rdata};
1070 log_debug("after-validate-sign: %{dnsname}: - %{dnsname} %9i %{typerdatadesc} ; (W+R)", zone->origin, rr->fqdn, rr->ttl, &rd);
1071 }
1072
1073 for(int i = 0; i <= ptr_vector_last_index(&add); ++i)
1074 {
1075 zone_diff_label_rr *rr = (zone_diff_label_rr*)ptr_vector_get(&add, i);
1076 rdata_desc rd = {rr->rtype, rr->rdata_size, rr->rdata};
1077 log_debug("after-validate-sign: %{dnsname}: + %{dnsname} %9i %{typerdatadesc} ; (W+R)", zone->origin, rr->fqdn, rr->ttl, &rd);
1078 }
1079 #endif
1080 }
1081
1082 ptr_vector_destroy(&rrset_to_sign);
1083
1084 ptr_vector_destroy(&chain_candidates);
1085 ptr_vector_destroy(&candidates);
1086 ptr_vector_destroy(&rrset_vector);
1087
1088 if(diff_has_changes)
1089 {
1090 log_debug("maintenance: %{dnsname}: writing and playing transaction", zone->origin);
1091
1092 ret = dynupdate_diff_write_to_journal_and_replay(zone, ZDB_ZONE_MUTEX_RRSIG_UPDATER, &remove, &add);
1093 }
1094 else
1095 {
1096 ret = 0;
1097 }
1098
1099 ptr_vector_destroy(&remove);
1100 ptr_vector_destroy(&add);
1101
1102 if(ISOK(ret))
1103 {
1104 if(ret < 32768)
1105 {
1106 if(ret > 0)
1107 {
1108 double r = 32768.0;
1109 r /= ret;
1110 r *= labels_at_once;
1111 if(r > 65535.0)
1112 {
1113 r = 65535;
1114 }
1115 mctx.zone->progressive_signature_update.labels_at_once = (u16)r;
1116 }
1117 else
1118 {
1119 mctx.zone->progressive_signature_update.labels_at_once = MAX_U16;
1120 }
1121
1122 log_debug("maintenance: %{dnsname}: adjusting up batch size to %i", zone->origin, mctx.zone->progressive_signature_update.labels_at_once);
1123 }
1124 else
1125 {
1126
1127 if(mctx.zone->progressive_signature_update.labels_at_once > 1)
1128 {
1129 mctx.zone->progressive_signature_update.labels_at_once /= 2;
1130 log_debug("maintenance: %{dnsname}: adjusting down batch size to %i", zone->origin, mctx.zone->progressive_signature_update.labels_at_once);
1131 }
1132 }
1133 }
1134
1135 log_debug("maintenance: %{dnsname}: releasing resources", zone->origin);
1136
1137 zdb_zone_double_unlock(zone, ZDB_ZONE_MUTEX_SIMPLEREADER, ZDB_ZONE_MUTEX_RRSIG_UPDATER);
1138
1139 zdb_zone_maintenance_ctx_finalize(&mctx);
1140
1141 zone_diff_finalize(&diff);
1142
1143 if(last_label_of_zone_reached)
1144 {
1145 if(ISOK(ret))
1146 {
1147 #if ZDB_ZONE_MAINTENANCE_SAME_PASS_CLOSE
1148 log_info("maintenance: %{dnsname}: done", zone->origin);
1149
1150 ret = 0; // so the caller do not try to call again right away.
1151 mctx.fqdn[0] = '\0';
1152 #else
1153 if(!diff_has_changes) // the end and no changes : closure must have happened
1154 {
1155 log_debug("maintenance: %{dnsname}: done, for now", zone->origin);
1156
1157 ret = 0; // so the caller do not try to call again right away.
1158 mctx.fqdn[0] = '\0';
1159 }
1160 else
1161 {
1162 log_debug("maintenance: %{dnsname}: done, but will allow for one last pass", zone->origin);
1163
1164 ret = 1; // else the potential closing of the chain will not happen
1165 }
1166 #endif
1167 }
1168 else
1169 {
1170 if(ret != ZDB_JOURNAL_MUST_SAFEGUARD_CONTINUITY)
1171 {
1172 log_warn("maintenance: %{dnsname}: reached the end, but with an error code: %r", zone->origin, ret);
1173 }
1174 else
1175 {
1176 log_debug("maintenance: %{dnsname}: reached the end, but zone must be stored", zone->origin);
1177 }
1178 }
1179 }
1180 else
1181 {
1182 if(ret == 0)
1183 {
1184 log_debug("maintenance: %{dnsname}: another pass will follow from %{dnsname}", zone->origin, mctx.fqdn);
1185
1186 ret = 1; // else the remaining will be postponed for a while
1187 }
1188 }
1189
1190 if(ISOK(ret))
1191 {
1192 size_t fqdn_len = dnsname_len(mctx.fqdn);
1193
1194 if((fqdn_len <= from_fqdn_size) && (from_fqdn != NULL))
1195 {
1196 log_debug("maintenance: %{dnsname}: saving the next node (%{dnsname})", zone->origin, mctx.fqdn);
1197 memcpy(from_fqdn, mctx.fqdn, fqdn_len); // if from_fqdn == 0, fqdl_len == 0
1198 //from_fqdn_is_binary_digest = FALSE;
1199 }
1200 else
1201 {
1202 log_debug("maintenance: %{dnsname}: cannot save the next node (%{dnsname}) as buffer size is too small (%llu < %llu)", zone->origin, mctx.fqdn, from_fqdn_size, fqdn_len);
1203 }
1204 }
1205 else
1206 {
1207 log_debug("maintenance: %{dnsname}: an error state occurred (%r), keeping previous state (%{dnsname}), ignoring next state (%{dnsname})", zone->origin, ret, from_fqdn, mctx.fqdn);
1208 }
1209 /*
1210 if(from_fqdn_is_binary_digest)
1211 {
1212 log_err("maintenance: %{dnsname}: next fqdn is binary digest %{digest32h}", zone->origin, from_fqdn);
1213 }
1214
1215 yassert(!from_fqdn_is_binary_digest);
1216 */
1217 s64 stop_time = timeus();
1218
1219 double dt = stop_time - start_time;
1220 if(dt < 0) dt = 0;
1221 dt /= ONE_SECOND_US_F;
1222
1223 log_debug("rrsig: %{dnsname}: %r (%.3fs)", zone->origin, ret, dt);
1224
1225 return ret;
1226 }
1227
1228 /**
1229 * Will double-lock for reader & rrsig-updater
1230 *
1231 * @param zone
1232 * @param signature_count_loose_limit
1233 * @param present_signatures_are_verified
1234 * @return 0 : all done, >0 : some done (some could be 0), <0 error
1235 */
1236
1237 ya_result
zdb_zone_maintenance(zdb_zone * zone)1238 zdb_zone_maintenance(zdb_zone* zone)
1239 {
1240 ya_result ret;
1241 u8 *prev_fqdn;
1242 s8 prev_chain_index;
1243 u8 in_out_fqdn[MAX_DOMAIN_LENGTH];
1244
1245 if(zone->progressive_signature_update.current_fqdn != NULL)
1246 {
1247 log_debug("maintenance: %{dnsname}: resuming from %{dnsname}", zone->origin, zone->progressive_signature_update.current_fqdn);
1248
1249 dnsname_copy(in_out_fqdn, zone->progressive_signature_update.current_fqdn);
1250 prev_fqdn = zone->progressive_signature_update.current_fqdn;
1251 prev_chain_index = zone->progressive_signature_update.chain_index;
1252 //dnsname_zfree(zone->progressive_signature_update.current_fqdn);
1253 zone->progressive_signature_update.current_fqdn = NULL;
1254 }
1255 else
1256 {
1257 prev_fqdn = NULL;
1258 prev_chain_index = -1;
1259 log_info("maintenance: %{dnsname}: zone maintenance started", zone->origin);
1260 in_out_fqdn[0] = 0;
1261 #if DEBUG
1262 memset(in_out_fqdn, 0, sizeof(in_out_fqdn));
1263 #endif
1264 zone->progressive_signature_update.current_fqdn = NULL;
1265 zone->progressive_signature_update.chain_index = -1;
1266 #if DEBUG
1267 log_debug("maintenance: %{dnsname}: interval=%is jitter=%is regeneration=%is (DEBUG)", zone->origin, zone->sig_validity_interval_seconds, zone->sig_validity_jitter_seconds, zone->sig_validity_regeneration_seconds);
1268 #endif
1269 }
1270
1271 ret = zdb_zone_maintenance_from(zone, in_out_fqdn, sizeof(in_out_fqdn), ZDB_MAINTENANCE_BATCH_TIME_US_MAX, ZDB_ZONE_MAINTENANCE_RRSIG_COUNT_THRESHOLD);
1272
1273 if(in_out_fqdn[0] != 0)
1274 {
1275 if(ISOK(ret))
1276 {
1277 zone->progressive_signature_update.current_fqdn = dnsname_zdup(in_out_fqdn);
1278 if(prev_fqdn != NULL)
1279 {
1280 dnsname_zfree(prev_fqdn);
1281 prev_fqdn = NULL;
1282 }
1283
1284 log_debug("maintenance: %{dnsname}: pausing at %{dnsname} (%r)", zone->origin, zone->progressive_signature_update.current_fqdn, ret);
1285 }
1286 else
1287 {
1288 if(prev_fqdn != NULL)
1289 {
1290 zone->progressive_signature_update.current_fqdn = prev_fqdn;
1291 zone->progressive_signature_update.chain_index = prev_chain_index;
1292 prev_fqdn = NULL;
1293 // prev_chain_index = -1;
1294 log_debug("maintenance: %{dnsname}: pausing at %{dnsname} (%r) (may try again)", zone->origin, zone->progressive_signature_update.current_fqdn, ret);
1295 }
1296 else
1297 {
1298 log_debug("maintenance: %{dnsname}: pausing (%r) (may try again)", zone->origin, ret);
1299 }
1300 }
1301 }
1302 else
1303 {
1304 if(prev_fqdn != NULL)
1305 {
1306 dnsname_zfree(prev_fqdn);
1307 prev_fqdn = NULL;
1308 }
1309
1310 log_debug("maintenance: %{dnsname}: done (%r)", zone->origin, ret);
1311 }
1312
1313 if(ret == 0)
1314 {
1315 log_info("maintenance: %{dnsname}: zone maintenance finished", zone->origin);
1316 }
1317
1318 return ret;
1319 }
1320
1321 ya_result
zdb_zone_sign(zdb_zone * zone)1322 zdb_zone_sign(zdb_zone* zone)
1323 {
1324 ya_result ret = zdb_zone_maintenance_from(zone, NULL, 0, ZDB_MAINTENANCE_BATCH_TIME_US_MAX, ZDB_ZONE_MAINTENANCE_RRSIG_COUNT_THRESHOLD);
1325 return ret;
1326 }
1327
1328 /** @} */
1329