summaryrefslogtreecommitdiffstats
path: root/src/knot/zone/zone.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/knot/zone/zone.h')
-rw-r--r--src/knot/zone/zone.h290
1 files changed, 290 insertions, 0 deletions
diff --git a/src/knot/zone/zone.h b/src/knot/zone/zone.h
new file mode 100644
index 0000000..ae8991e
--- /dev/null
+++ b/src/knot/zone/zone.h
@@ -0,0 +1,290 @@
+/* Copyright (C) 2022 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+ 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 <https://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include "contrib/semaphore.h"
+#include "knot/catalog/catalog_update.h"
+#include "knot/conf/conf.h"
+#include "knot/conf/confio.h"
+#include "knot/journal/journal_basic.h"
+#include "knot/journal/serialization.h"
+#include "knot/events/events.h"
+#include "knot/updates/changesets.h"
+#include "knot/zone/contents.h"
+#include "knot/zone/timers.h"
+#include "libknot/dname.h"
+#include "libknot/dynarray.h"
+#include "libknot/packet/pkt.h"
+
+struct zone_update;
+struct zone_backup_ctx;
+
+/*!
+ * \brief Zone flags.
+ *
+ * When updating check create_zone_reload() if the flag mask is ok.
+ */
+typedef enum {
+ ZONE_FORCE_AXFR = 1 << 0, /*!< Force AXFR as next transfer. */
+ ZONE_FORCE_RESIGN = 1 << 1, /*!< Force zone re-sign. */
+ ZONE_FORCE_FLUSH = 1 << 2, /*!< Force zone flush. */
+ ZONE_FORCE_KSK_ROLL = 1 << 3, /*!< Force KSK/CSK rollover. */
+ ZONE_FORCE_ZSK_ROLL = 1 << 4, /*!< Force ZSK rollover. */
+ ZONE_IS_CATALOG = 1 << 5, /*!< This is a catalog. */
+ ZONE_IS_CAT_MEMBER = 1 << 6, /*!< This zone exists according to a catalog. */
+ ZONE_XFR_FROZEN = 1 << 7, /*!< Outgoing AXFR/IXFR temporarily disabled. */
+ ZONE_USER_FLUSH = 1 << 8, /*!< User-triggered flush. */
+} zone_flag_t;
+
+/*!
+ * \brief Track unsuccessful NOTIFY targets.
+ */
+typedef uint64_t notifailed_rmt_hash;
+knot_dynarray_declare(notifailed_rmt, notifailed_rmt_hash, DYNARRAY_VISIBILITY_NORMAL, 4);
+
+/*!
+ * \brief Zone purging parameter flags.
+ */
+typedef enum {
+ PURGE_ZONE_BEST = 1 << 0, /*!< Best effort -- continue on failures. */
+ PURGE_ZONE_LOG = 1 << 1, /*!< Log a purged zone even if requested less. */
+ PURGE_ZONE_NOSYNC = 1 << 2, /*!< Remove even zone files with disabled syncing. */
+ PURGE_ZONE_TIMERS = 1 << 3, /*!< Purge the zone timers. */
+ PURGE_ZONE_ZONEFILE = 1 << 4, /*!< Purge the zone file. */
+ PURGE_ZONE_JOURNAL = 1 << 5, /*!< Purge the zone journal. */
+ PURGE_ZONE_KASPDB = 1 << 6, /*!< Purge KASP DB. */
+ PURGE_ZONE_CATALOG = 1 << 7, /*!< Purge the catalog. */
+} purge_flag_t;
+
+#define PURGE_ZONE_FULL ~0U /*!< Purge everything possible. */
+ /*!< Standard purge (respect C_ZONEFILE_SYNC param). */
+#define PURGE_ZONE_ALL (PURGE_ZONE_FULL ^ PURGE_ZONE_NOSYNC)
+ /*!< All data. */
+#define PURGE_ZONE_DATA (PURGE_ZONE_TIMERS | PURGE_ZONE_ZONEFILE | PURGE_ZONE_JOURNAL | \
+ PURGE_ZONE_KASPDB | PURGE_ZONE_CATALOG)
+
+/*!
+ * \brief Structure for holding DNS zone.
+ */
+typedef struct zone
+{
+ knot_dname_t *name;
+ zone_contents_t *contents;
+ zone_flag_t flags;
+ bool is_catalog_flag; //!< Lock-less indication of ZONE_IS_CATALOG flag.
+
+ /*! \brief Dynamic configuration zone change type. */
+ conf_io_type_t change_type;
+
+ /*! \brief Zonefile parameters. */
+ struct {
+ struct timespec mtime;
+ uint32_t serial;
+ bool exists;
+ bool resigned;
+ bool retransfer;
+ uint8_t bootstrap_cnt; //!< Rebootstrap count (not related to zonefile).
+ } zonefile;
+
+ /*! \brief Zone events. */
+ zone_timers_t timers; //!< Persistent zone timers.
+ zone_events_t events; //!< Zone events timers.
+
+ /*! \brief Track unsuccessful NOTIFY targets. */
+ notifailed_rmt_dynarray_t notifailed;
+
+ /*! \brief DDNS queue and lock. */
+ pthread_mutex_t ddns_lock;
+ size_t ddns_queue_size;
+ list_t ddns_queue;
+
+ /*! \brief Control update context. */
+ struct zone_update *control_update;
+
+ /*! \brief Ensue one COW transaction on zone's trees at a time. */
+ knot_sem_t cow_lock;
+
+ /*! \brief Pointer on running server with e.g. KASP db, journal DB, catalog... */
+ struct server *server;
+
+ /*! \brief Zone backup context (NULL unless backup pending). */
+ struct zone_backup_ctx *backup_ctx;
+
+ /*! \brief Catalog-generate feature. */
+ knot_dname_t *catalog_gen;
+ catalog_update_t *cat_members;
+ const char *catalog_group;
+
+ /*! \brief Preferred master lock. Also used for flags access. */
+ pthread_mutex_t preferred_lock;
+ /*! \brief Preferred master for remote operation. */
+ struct sockaddr_storage *preferred_master;
+
+ /*! \brief Query modules. */
+ list_t query_modules;
+ struct query_plan *query_plan;
+} zone_t;
+
+/*!
+ * \brief Creates new zone with empty zone content.
+ *
+ * \param name Zone name.
+ *
+ * \return The initialized zone structure or NULL if an error occurred.
+ */
+zone_t* zone_new(const knot_dname_t *name);
+
+/*!
+ * \brief Deallocates the zone structure.
+ *
+ * \note The function also deallocates all bound structures (contents, etc.).
+ *
+ * \param zone_ptr Zone to be freed.
+ */
+void zone_free(zone_t **zone_ptr);
+
+/*!
+ * \brief Clear zone contents (->SERVFAIL), reset modules, plan LOAD.
+ *
+ * \param conf Current configuration.
+ * \param zone Zone to be re-set.
+ */
+void zone_reset(conf_t *conf, zone_t *zone);
+
+/*!
+ * \brief Purges selected zone components.
+ *
+ * \param conf Current configuration.
+ * \param zone Zone to be purged.
+ * \param params Zone components to be purged and the purging mode
+ * (with PURGE_ZONE_BEST try to purge everything requested,
+ * otherwise exit on the first failure).
+ *
+ * \return KNOT_E*
+ */
+int selective_zone_purge(conf_t *conf, zone_t *zone, purge_flag_t params);
+
+/*!
+ * \brief Clears possible control update transaction.
+ *
+ * \param zone Zone to be cleared.
+ */
+void zone_control_clear(zone_t *zone);
+
+/*!
+ * \brief Common database getters.
+ */
+knot_lmdb_db_t *zone_journaldb(const zone_t *zone);
+knot_lmdb_db_t *zone_kaspdb(const zone_t *zone);
+catalog_t *zone_catalog(const zone_t *zone);
+catalog_update_t *zone_catalog_upd(const zone_t *zone);
+
+/*!
+ * \brief Only for RO journal operations.
+ */
+inline static zone_journal_t zone_journal(zone_t *zone)
+{
+ zone_journal_t j = { zone_journaldb(zone), zone->name, NULL };
+ return j;
+}
+
+int zone_change_store(conf_t *conf, zone_t *zone, changeset_t *change, changeset_t *extra);
+int zone_diff_store(conf_t *conf, zone_t *zone, const zone_diff_t *diff);
+int zone_changes_clear(conf_t *conf, zone_t *zone);
+int zone_in_journal_store(conf_t *conf, zone_t *zone, zone_contents_t *new_contents);
+
+/*! \brief Synchronize zone file with journal. */
+int zone_flush_journal(conf_t *conf, zone_t *zone, bool verbose);
+
+bool zone_journal_has_zij(zone_t *zone);
+
+/*!
+ * \brief Clear failed_notify list before planning new NOTIFY.
+ */
+void zone_notifailed_clear(zone_t *zone);
+void zone_schedule_notify(zone_t *zone, time_t delay);
+
+/*!
+ * \brief Atomically switch the content of the zone.
+ */
+zone_contents_t *zone_switch_contents(zone_t *zone, zone_contents_t *new_contents);
+
+/*! \brief Checks if the zone is slave. */
+bool zone_is_slave(conf_t *conf, const zone_t *zone);
+
+/*! \brief Sets the address as a preferred master address. */
+void zone_set_preferred_master(zone_t *zone, const struct sockaddr_storage *addr);
+
+/*! \brief Clears the current preferred master address. */
+void zone_clear_preferred_master(zone_t *zone);
+
+/*! \brief Sets a zone flag. */
+void zone_set_flag(zone_t *zone, zone_flag_t flag);
+
+/*! \brief Unsets a zone flag. */
+void zone_unset_flag(zone_t *zone, zone_flag_t flag);
+
+/*! \brief Returns if a flag is set (and optionally clears it). */
+zone_flag_t zone_get_flag(zone_t *zone, zone_flag_t flag, bool clear);
+
+/*! \brief Get zone SOA RR. */
+const knot_rdataset_t *zone_soa(const zone_t *zone);
+
+/*! \brief Get zone SOA EXPIRE field, or 0 if empty zone. */
+uint32_t zone_soa_expire(const zone_t *zone);
+
+/*! \brief Check if zone is expired according to timers. */
+bool zone_expired(const zone_t *zone);
+
+/*!
+ * \brief Set default timers for new zones or invalidate if not valid.
+ */
+void zone_timers_sanitize(conf_t *conf, zone_t *zone);
+
+typedef struct {
+ bool address; //!< Fallback to next remote address is required.
+ bool remote; //!< Fallback to next remote server is required.
+} zone_master_fallback_t;
+
+typedef int (*zone_master_cb)(conf_t *conf, zone_t *zone, const conf_remote_t *remote,
+ void *data, zone_master_fallback_t *fallback);
+
+/*!
+ * \brief Perform an action with all configured master servers.
+ *
+ * The function iterates over available masters. For each master, the callback
+ * function is called once for its every adresses until the callback function
+ * succeeds (\ref KNOT_EOK is returned) and then the iteration continues with
+ * the next master.
+ *
+ * \return Error code from the last callback or KNOT_ENOMASTER.
+ */
+int zone_master_try(conf_t *conf, zone_t *zone, zone_master_cb callback,
+ void *callback_data, const char *err_str);
+
+/*! \brief Write zone contents to zonefile, but into different directory. */
+int zone_dump_to_dir(conf_t *conf, zone_t *zone, const char *dir);
+
+int zone_set_master_serial(zone_t *zone, uint32_t serial);
+
+int zone_get_master_serial(zone_t *zone, uint32_t *serial);
+
+int zone_set_lastsigned_serial(zone_t *zone, uint32_t serial);
+
+int zone_get_lastsigned_serial(zone_t *zone, uint32_t *serial);
+
+int slave_zone_serial(zone_t *zone, conf_t *conf, uint32_t *serial);