From f449f278dd3c70e479a035f50a9bb817a9b433ba Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 17:24:08 +0200 Subject: Adding upstream version 3.2.6. Signed-off-by: Daniel Baumann --- src/knot/events/replan.c | 210 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 210 insertions(+) create mode 100644 src/knot/events/replan.c (limited to 'src/knot/events/replan.c') diff --git a/src/knot/events/replan.c b/src/knot/events/replan.c new file mode 100644 index 0000000..ed03fe1 --- /dev/null +++ b/src/knot/events/replan.c @@ -0,0 +1,210 @@ +/* Copyright (C) 2023 CZ.NIC, z.s.p.o. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ + +#include +#include + +#include "knot/dnssec/kasp/kasp_db.h" +#include "knot/events/replan.h" + +#define TIME_CANCEL 0 +#define TIME_IGNORE (-1) + +/*! + * \brief Move DDNS queue from old zone to new zone and replan if necessary. + * + * New zone will contain references from the old zone. New zone will free + * the data. + */ +static void replan_ddns(zone_t *zone, zone_t *old_zone) +{ + if (old_zone->ddns_queue_size == 0) { + return; + } + + ptrnode_t *node; + WALK_LIST(node, old_zone->ddns_queue) { + ptrlist_add(&zone->ddns_queue, node->d, NULL); + } + zone->ddns_queue_size = old_zone->ddns_queue_size; + + ptrlist_free(&old_zone->ddns_queue, NULL); + + zone_events_schedule_now(zone, ZONE_EVENT_UPDATE); +} + +/*! + * \brief Replan events that are already planned for the old zone. + * + * \notice Preserves notifailed. + */ +static void replan_from_zone(zone_t *zone, zone_t *old_zone) +{ + assert(zone); + assert(old_zone); + + replan_ddns(zone, old_zone); + + const zone_event_type_t types[] = { + ZONE_EVENT_REFRESH, + ZONE_EVENT_FLUSH, + ZONE_EVENT_BACKUP, + ZONE_EVENT_NOTIFY, + ZONE_EVENT_UFREEZE, + ZONE_EVENT_UTHAW, + ZONE_EVENT_INVALID + }; + + for (const zone_event_type_t *type = types; *type != ZONE_EVENT_INVALID; type++) { + time_t when = zone_events_get_time(old_zone, *type); + if (when > 0) { + zone_events_schedule_at(zone, *type, when); + } + } +} + +/*! + * \brief Replan DNSSEC if automatic signing enabled. + * + * This is required as the configuration could have changed. + */ +static void replan_dnssec(conf_t *conf, zone_t *zone) +{ + assert(conf); + assert(zone); + + conf_val_t val = conf_zone_get(conf, C_DNSSEC_SIGNING, zone->name); + if (conf_bool(&val)) { + zone_events_schedule_now(zone, ZONE_EVENT_DNSSEC); + } +} + +/*! + * \brief Replan events that depend on zone timers (REFRESH, EXPIRE, FLUSH, RESALT, PARENT DS QUERY). + */ +void replan_from_timers(conf_t *conf, zone_t *zone) +{ + assert(conf); + assert(zone); + + time_t now = time(NULL); + + time_t refresh = TIME_CANCEL; + if (zone_is_slave(conf, zone)) { + refresh = zone->timers.next_refresh; + if (zone->contents == NULL && zone->timers.last_refresh_ok) { // zone disappeared w/o expiry + refresh = now; + } + assert(refresh > 0); + } + + time_t expire_pre = TIME_IGNORE; + time_t expire = TIME_IGNORE; + if (zone_is_slave(conf, zone) && zone->contents != NULL) { + expire_pre = TIME_CANCEL; + expire = zone->timers.next_expire; + } + + time_t flush = TIME_IGNORE; + if (!zone_is_slave(conf, zone) || zone->contents != NULL) { + conf_val_t val = conf_zone_get(conf, C_ZONEFILE_SYNC, zone->name); + int64_t sync_timeout = conf_int(&val); + if (sync_timeout > 0) { + flush = zone->timers.last_flush + sync_timeout; + } + } + + time_t resalt = TIME_IGNORE; + time_t ds_check = TIME_CANCEL; + time_t ds_push = TIME_CANCEL; + conf_val_t val = conf_zone_get(conf, C_DNSSEC_SIGNING, zone->name); + if (conf_bool(&val)) { + conf_val_t policy = conf_zone_get(conf, C_DNSSEC_POLICY, zone->name); + conf_id_fix_default(&policy); + val = conf_id_get(conf, C_POLICY, C_NSEC3, &policy); + if (conf_bool(&val)) { + knot_time_t last_resalt = 0; + if (knot_lmdb_open(zone_kaspdb(zone)) == KNOT_EOK) { + (void)kasp_db_load_nsec3salt(zone_kaspdb(zone), zone->name, NULL, &last_resalt); + } + if (last_resalt == 0) { + resalt = now; + } else { + val = conf_id_get(conf, C_POLICY, C_NSEC3_SALT_LIFETIME, &policy); + if (conf_int(&val) > 0) { + resalt = last_resalt + conf_int(&val); + } + } + } + + ds_check = zone->timers.next_ds_check; + if (ds_check == 0) { + ds_check = TIME_IGNORE; + } + ds_push = zone->timers.next_ds_push; + if (ds_push == 0) { + ds_push = TIME_IGNORE; + } + } + + zone_events_schedule_at(zone, + ZONE_EVENT_REFRESH, refresh, + ZONE_EVENT_EXPIRE, expire_pre, + ZONE_EVENT_EXPIRE, expire, + ZONE_EVENT_FLUSH, flush, + ZONE_EVENT_DNSSEC, resalt, + ZONE_EVENT_DS_CHECK, ds_check, + ZONE_EVENT_DS_PUSH, ds_push); +} + +void replan_load_new(zone_t *zone, bool gen_catalog) +{ + if (gen_catalog) { + /* Catalog generation must wait until the zonedb + * is fully created. */ + zone_events_schedule_now(zone, ZONE_EVENT_LOAD); + } else { + /* Enqueue directly, make first load waitable, + * other events will cascade from load. */ + zone_events_enqueue(zone, ZONE_EVENT_LOAD); + } +} + +void replan_load_bootstrap(conf_t *conf, zone_t *zone) +{ + replan_from_timers(conf, zone); +} + +void replan_load_current(conf_t *conf, zone_t *zone, zone_t *old_zone) +{ + replan_from_zone(zone, old_zone); + + if (zone->contents != NULL || zone_expired(zone)) { + replan_from_timers(conf, zone); + replan_dnssec(conf, zone); + } else { + zone_events_schedule_now(zone, ZONE_EVENT_LOAD); + } +} + +void replan_load_updated(zone_t *zone, zone_t *old_zone) +{ + zone_notifailed_clear(zone); + replan_from_zone(zone, old_zone); + + // other events will cascade from load + zone_events_schedule_now(zone, ZONE_EVENT_LOAD); +} -- cgit v1.2.3