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/include/module.h | 602 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 602 insertions(+) create mode 100644 src/knot/include/module.h (limited to 'src/knot/include/module.h') diff --git a/src/knot/include/module.h b/src/knot/include/module.h new file mode 100644 index 0000000..8190828 --- /dev/null +++ b/src/knot/include/module.h @@ -0,0 +1,602 @@ +/* Copyright (C) 2022 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 . + */ + +/*! + * \file + * + * \brief Knot DNS module interface. + * + * \addtogroup module + * @{ + */ + +#pragma once + +#include +#include +#include +#include + +#include +#include + +/*** Query module API. ***/ + +/*! Current module ABI version. */ +#define KNOTD_MOD_ABI_VERSION 400 +/*! Module configuration name prefix. */ +#define KNOTD_MOD_NAME_PREFIX "mod-" + +/*! Configuration check function context. */ +typedef struct { + const yp_item_t *item; /*!< Current item descriptor. */ + const uint8_t *id; /*!< Current section identifier. */ + size_t id_len; /*!< Current section identifier length. */ + const uint8_t *data; /*!< Current item data. */ + size_t data_len; /*!< Current item data length. */ + const char *err_str; /*!< Output error message. */ + struct knotd_conf_check_extra *extra; /*!< Private items (conf/tools.h). */ +} knotd_conf_check_args_t; + +/*! Module context. */ +typedef struct knotd_mod knotd_mod_t; + +/*! + * Module load callback. + * + * Responsibilities: + * - Query processing hooks registration + * - Optional module specific context initialization + * - Module configuration processing + * - Query statistics counters registration + * + * \param[in] mod Module context. + * + * \return Error code, KNOT_EOK if success. + */ +typedef int (*knotd_mod_load_f)(knotd_mod_t *mod); + +/*! + * Module unload callback. + * + * Responsibilities: + * - Optional module specific context deinitialization + * + * \param[in] mod Module context. + */ +typedef void (*knotd_mod_unload_f)(knotd_mod_t *mod); + +/*! + * Module configuration section check callback. + * + * Responsibilities: + * - Optional module configuration section items checks. + * + * \note Set args.err_str to proper error message if error. + * + * \param[in] args Configuration check arguments. + * + * \return Error code, KNOT_EOK if success. + */ +typedef int (*knotd_conf_check_f)(knotd_conf_check_args_t *args); + +/*! Module flags. */ +typedef enum { + KNOTD_MOD_FLAG_NONE = 0, /*!< Unspecified. */ + KNOTD_MOD_FLAG_OPT_CONF = 1 << 0, /*!< Optional module configuration. */ + KNOTD_MOD_FLAG_SCOPE_GLOBAL = 1 << 1, /*!< Can be specified as global module. */ + KNOTD_MOD_FLAG_SCOPE_ZONE = 1 << 2, /*!< Can be specified as zone module. */ + KNOTD_MOD_FLAG_SCOPE_ANY = KNOTD_MOD_FLAG_SCOPE_GLOBAL | + KNOTD_MOD_FLAG_SCOPE_ZONE, +} knotd_mod_flag_t; + +/*! Module API. */ +typedef struct { + uint32_t version; /*!< Embedded version of the module ABI. */ + const char *name; /*!< Module name. */ + knotd_mod_flag_t flags; /*!< Module flags. */ + knotd_mod_load_f load; /*!< Module load callback. */ + knotd_mod_unload_f unload; /*!< Module unload callback. */ + const yp_item_t *config; /*!< Module configuration schema. */ + knotd_conf_check_f config_check; /*!< Module configuration check callback. */ +} knotd_mod_api_t; + +/*! Static module API symbol must have a unique name. */ +#ifdef KNOTD_MOD_STATIC + #define KNOTD_MOD_API_NAME(mod_name) knotd_mod_api_##mod_name +#else + #define KNOTD_MOD_API_NAME(mod_name) knotd_mod_api +#endif + +/*! Module API instance initialization helper macro. */ +#define KNOTD_MOD_API(mod_name, mod_flags, mod_load, mod_unload, mod_conf, mod_conf_check) \ + __attribute__((visibility("default"))) \ + const knotd_mod_api_t KNOTD_MOD_API_NAME(mod_name) = { \ + .version = KNOTD_MOD_ABI_VERSION, \ + .name = KNOTD_MOD_NAME_PREFIX #mod_name, \ + .flags = mod_flags, \ + .load = mod_load, \ + .unload = mod_unload, \ + .config = mod_conf, \ + .config_check = mod_conf_check, \ + } + +/*** Configuration, statistics, logging,... API. ***/ + +/*! + * Checks reference item (YP_TREF) value if the destination exists. + * + * \note This function is intended to be used in module schema. + * + * \param[in] args Configuration check arguments. + * + * \return Error code, KNOT_EOK if success. + */ +int knotd_conf_check_ref(knotd_conf_check_args_t *args); + +/*! + * Gets optional module context. + * + * \param[in] mod Module context. + * + * \return Pointer to optional module context. + */ +void *knotd_mod_ctx(knotd_mod_t *mod); + +/*! + * Sets optional module context. + * + * \param[in] mod Module context. + * \param[in] ctx Optional module context. + */ +void knotd_mod_ctx_set(knotd_mod_t *mod, void *ctx); + +/*! + * Gets the zone name the module is configured for. + * + * \param[in] mod Module context. + * + * \return Zone name. + */ +const knot_dname_t *knotd_mod_zone(knotd_mod_t *mod); + +/*! + * Emits a module specific log message. + * + * \param[in] mod Module context. + * \param[in] priority Message priority (LOG_DEBUG...LOG_CRIT). + * \param[in] fmt Content of the message. + */ +void knotd_mod_log(knotd_mod_t *mod, int priority, const char *fmt, ...); + +/*! + * Emits a module specific log message (va_list variant). + * + * \param[in] mod Module context. + * \param[in] priority Message priority (LOG_DEBUG...LOG_CRIT). + * \param[in] fmt Content of the message. + * \param[in] args Variable argument list. + */ +void knotd_mod_vlog(knotd_mod_t *mod, int priority, const char *fmt, va_list args); + +/*! + * Statistics multi-counter index to name transformation callback. + * + * \param[in] idx Multi-counter index. + * \param[in] idx_count Number of subcounters. + * + * \return Index name string. + */ +typedef char* (*knotd_mod_idx_to_str_f)(uint32_t idx, uint32_t idx_count); + +/*! + * Registers a statistics counter. + * + * \param[in] mod Module context. + * \param[in] ctr_name Counter name + * \param[in] idx_count Number of subcounters (set 1 for single-counter). + * \param[in] idx_to_str Subcounter index to name transformation callback + * (set NULL for single-counter). + * + * \return Error code, KNOT_EOK if success. + */ +int knotd_mod_stats_add(knotd_mod_t *mod, const char *ctr_name, uint32_t idx_count, + knotd_mod_idx_to_str_f idx_to_str); + +/*! + * Increments a statistics counter. + * + * \param[in] mod Module context. + * \param[in] thr_id Index of worker thread. + * \param[in] ctr_id Counter id (counted in the order the counters were registered). + * \param[in] idx Subcounter index (set 0 for single-counter). + * \param[in] val Value increment. + */ +void knotd_mod_stats_incr(knotd_mod_t *mod, unsigned thr_id, uint32_t ctr_id, + uint32_t idx, uint64_t val); + +/*! + * Decrements a statistics counter. + * + * \param[in] mod Module context. + * \param[in] thr_id Index of worker thread. + * \param[in] ctr_id Counter id (counted in the order the counters were registered). + * \param[in] idx Subcounter index (set 0 for single-counter). + * \param[in] val Value decrement. + */ +void knotd_mod_stats_decr(knotd_mod_t *mod, unsigned thr_id, uint32_t ctr_id, + uint32_t idx, uint64_t val); + +/*! + * Sets a statistics counter value. + * + * \param[in] mod Module context. + * \param[in] thr_id Index of worker thread. + * \param[in] ctr_id Counter id (counted in the order the counters were registered). + * \param[in] idx Subcounter index (set 0 for single-counter). + * \param[in] val Value. + */ +void knotd_mod_stats_store(knotd_mod_t *mod, unsigned thr_id, uint32_t ctr_id, + uint32_t idx, uint64_t val); + +/*! Configuration single-value abstraction. */ +typedef union { + int64_t integer; + unsigned option; + bool boolean; + const char *string; + const knot_dname_t *dname; + struct { + struct sockaddr_storage addr; + struct sockaddr_storage addr_max; + int addr_mask; + }; + struct { + const uint8_t *data; + size_t data_len; + }; +} knotd_conf_val_t; + +/*! Configuration value. */ +typedef struct { + knotd_conf_val_t single; /*!< Single-valued item data. */ + knotd_conf_val_t *multi; /*!< Multi-valued item data. */ + size_t count; /*!< Number of items (0 if default single value). */ +} knotd_conf_t; + +/*! Environment items. */ +typedef enum { + KNOTD_CONF_ENV_VERSION = 0, /*!< Software version. */ + KNOTD_CONF_ENV_HOSTNAME = 1, /*!< Current hostname. */ + KNOTD_CONF_ENV_WORKERS_UDP = 2, /*!< Current number of UDP workers. */ + KNOTD_CONF_ENV_WORKERS_TCP = 3, /*!< Current number of TCP workers. */ + KNOTD_CONF_ENV_WORKERS_XDP = 4, /*!< Current number of UDP-over-XDP workers. */ +} knotd_conf_env_t; + +/*! + * Gets general configuration value. + * + * \param[in] mod Module context. + * \param[in] section_name Section name. + * \param[in] item_name Section item name. + * \param[in] id Section identifier (NULL for simple section). + * + * \return Configuration value. + */ +knotd_conf_t knotd_conf(knotd_mod_t *mod, const yp_name_t *section_name, + const yp_name_t *item_name, const knotd_conf_t *id); + +/*! + * Gets environment value. + * + * \param[in] mod Module context. + * \param[in] env Environment item. + * + * \return Configuration value. + */ +knotd_conf_t knotd_conf_env(knotd_mod_t *mod, knotd_conf_env_t env); + +/*! + * Gets number of answering threads. + * + * \param[in] mod Module context. + * + * \return Number of worker threads. + */ +unsigned knotd_mod_threads(knotd_mod_t *mod); + +/*! + * Gets module configuration value. + * + * \param[in] mod Module context. + * \param[in] item_name Module section item name. + * + * \return Configuration value. + */ +knotd_conf_t knotd_conf_mod(knotd_mod_t *mod, const yp_name_t *item_name); + +/*! + * Gets zone configuration value. + * + * \param[in] mod Module context. + * \param[in] item_name Zone section item name. + * \param[in] zone Zone name. + * + * \return Configuration value. + */ +knotd_conf_t knotd_conf_zone(knotd_mod_t *mod, const yp_name_t *item_name, + const knot_dname_t *zone); + +/*! + * Gets module configuration value during the checking phase. + * + * \note This function is intended to be used in 'knotd_conf_check_f' callbacks. + * + * \param[in] args + * \param[in] item_name + * + * \return Configuration value. + */ +knotd_conf_t knotd_conf_check_item(knotd_conf_check_args_t *args, + const yp_name_t *item_name); + +/*! + * \brief Checks if address is in at least one of given ranges. + * + * \param[in] range + * \param[in] addr + * + * \return true if addr is in at least one range, false otherwise. + */ +bool knotd_conf_addr_range_match(const knotd_conf_t *range, + const struct sockaddr_storage *addr); + +/*! + * Deallocates multi-valued configuration values. + * + * \param[in] conf Configuration value. + */ +void knotd_conf_free(knotd_conf_t *conf); + +/*** Query processing API. ***/ + +/*! + * DNS query type. + * + * This type encompasses the different query types distinguished by both the + * OPCODE and the QTYPE. + */ +typedef enum { + KNOTD_QUERY_TYPE_INVALID, /*!< Invalid query. */ + KNOTD_QUERY_TYPE_NORMAL, /*!< Normal query. */ + KNOTD_QUERY_TYPE_AXFR, /*!< Request for AXFR transfer. */ + KNOTD_QUERY_TYPE_IXFR, /*!< Request for IXFR transfer. */ + KNOTD_QUERY_TYPE_NOTIFY, /*!< NOTIFY query. */ + KNOTD_QUERY_TYPE_UPDATE, /*!< Dynamic update. */ +} knotd_query_type_t; + +/*! Supported transport protocols. */ +typedef enum { + KNOTD_QUERY_PROTO_UDP = KNOT_PROBE_PROTO_UDP, /*!< Pure UDP. */ + KNOTD_QUERY_PROTO_TCP = KNOT_PROBE_PROTO_TCP, /*!< Pure TCP. */ + KNOTD_QUERY_PROTO_QUIC = KNOT_PROBE_PROTO_QUIC, /*!< QUIC/UDP. */ +} knotd_query_proto_t; + +/*! Query processing specific flags. */ +typedef enum { + KNOTD_QUERY_FLAG_COOKIE = 1 << 0, /*!< Valid DNS Cookie indication. */ +} knotd_query_flag_t; + +/*! Query processing data context parameters. */ +typedef struct { + knotd_query_proto_t proto; /*!< Transport protocol used. */ + knotd_query_flag_t flags; /*!< Current query flags. */ + const struct sockaddr_storage *remote; /*!< Current remote address. */ + int socket; /*!< Current network socket. */ + unsigned thread_id; /*!< Current thread id. */ + void *server; /*!< Server object private item. */ + const struct knot_xdp_msg *xdp_msg; /*!< Possible XDP message context. */ + uint32_t measured_rtt; /*!< Measured RTT in usecs: QUIC or TCP-XDP. */ +} knotd_qdata_params_t; + +/*! Query processing data context. */ +typedef struct { + knot_pkt_t *query; /*!< Query to be solved. */ + knotd_query_type_t type; /*!< Query packet type. */ + const knot_dname_t *name; /*!< Currently processed name. */ + uint16_t rcode; /*!< Resulting RCODE (Whole extended RCODE). */ + uint16_t rcode_tsig; /*!< Resulting TSIG RCODE. */ + int rcode_ede; /*!< Resulting Extended (EDE) RCODE. */ + knot_rrset_t opt_rr; /*!< OPT record. */ + knot_sign_context_t sign; /*!< Signing context. */ + knot_edns_client_subnet_t *ecs; /*!< EDNS Client Subnet option. */ + bool err_truncated; /*!< Set TC and AA bits if an error reply. */ + + /*! Persistent items on processing reset. */ + knot_mm_t *mm; /*!< Memory context. */ + knotd_qdata_params_t *params; /*!< Low-level processing parameters. */ + + struct knotd_qdata_extra *extra; /*!< Private items (process_query.h). */ +} knotd_qdata_t; + +/*! + * Gets the local (destination) address of the query. + * + * \param[in] qdata Query data. + * \param[out] buff Auxiliary buffer (not used for XDP). + * + * \return Local address or NULL if error. + */ +const struct sockaddr_storage *knotd_qdata_local_addr(knotd_qdata_t *qdata, + struct sockaddr_storage *buff); + +/*! + * Gets the remote (source) address of the query. + * + * \param[in] qdata Query data. + * + * \return Remote address or NULL if error. + */ +const struct sockaddr_storage *knotd_qdata_remote_addr(knotd_qdata_t *qdata); + +/*! + * Gets the measured TCP round-trip-time. + * + * \param[in] qdata Query data. + * + * \return RTT in microseconds or 0 if error or not available. + */ +uint32_t knotd_qdata_rtt(knotd_qdata_t *qdata); + +/*! + * Gets the current zone name. + * + * \param[in] qdata Query data. + * + * \return Zone name. + */ +const knot_dname_t *knotd_qdata_zone_name(knotd_qdata_t *qdata); + +/*! + * Gets the current zone apex rrset of the given type. + * + * \param[in] qdata Query data. + * \param[in] type Rrset type. + * + * \return A copy of the zone apex rrset. + */ +knot_rrset_t knotd_qdata_zone_apex_rrset(knotd_qdata_t *qdata, uint16_t type); + +/*! General query processing states. */ +typedef enum { + KNOTD_STATE_NOOP = 0, /*!< No response. */ + KNOTD_STATE_DONE = 4, /*!< Finished. */ + KNOTD_STATE_FAIL = 5, /*!< Error. */ + KNOTD_STATE_FINAL = 6, /*!< Finished and finalized (QNAME, EDNS, TSIG). */ +} knotd_state_t; + +/*! brief Internet query processing states. */ +typedef enum { + KNOTD_IN_STATE_BEGIN, /*!< Begin name resolution. */ + KNOTD_IN_STATE_NODATA, /*!< Positive result with NO data. */ + KNOTD_IN_STATE_HIT, /*!< Positive result. */ + KNOTD_IN_STATE_MISS, /*!< Negative result. */ + KNOTD_IN_STATE_DELEG, /*!< Result is delegation. */ + KNOTD_IN_STATE_FOLLOW, /*!< Resolution not complete (CNAME/DNAME chain). */ + KNOTD_IN_STATE_TRUNC, /*!< Finished, packet size limit encountered. */ + KNOTD_IN_STATE_ERROR, /*!< Resolution failed. */ +} knotd_in_state_t; + +/*! Query module processing stages. */ +typedef enum { + KNOTD_STAGE_BEGIN = 0, /*!< Before query processing. */ + KNOTD_STAGE_PREANSWER, /*!< Before section processing. */ + KNOTD_STAGE_ANSWER, /*!< Answer section processing. */ + KNOTD_STAGE_AUTHORITY, /*!< Authority section processing. */ + KNOTD_STAGE_ADDITIONAL, /*!< Additional section processing. */ + KNOTD_STAGE_END, /*!< After query processing. */ +} knotd_stage_t; + +/*! + * General processing hook. + * + * \param[in] state Current processing state. + * \param[in,out] pkt Response packet. + * \param[in] qdata Query data. + * \param[in] mod Module context. + * + * \return Next processing state. + */ +typedef knotd_state_t (*knotd_mod_hook_f) + (knotd_state_t state, knot_pkt_t *pkt, knotd_qdata_t *qdata, knotd_mod_t *mod); + +/*! + * Internet class processing hook. + * + * \param[in] state Current processing state. + * \param[in,out] pkt Response packet. + * \param[in] qdata Query data. + * \param[in] mod Module context. + * + * \return Next processing state. + */ +typedef knotd_in_state_t (*knotd_mod_in_hook_f) + (knotd_in_state_t state, knot_pkt_t *pkt, knotd_qdata_t *qdata, knotd_mod_t *mod); + +/*! + * Registers general processing module hook. + * + * \param[in] mod Module context. + * \param[in] stage Processing stage (KNOTD_STAGE_BEGIN or KNOTD_STAGE_END). + * \param[in] hook Module hook. + * + * \return Error code, KNOT_EOK if success. + */ +int knotd_mod_hook(knotd_mod_t *mod, knotd_stage_t stage, knotd_mod_hook_f hook); + +/*! + * Registers Internet class module hook. + * + * \param[in] mod Module context. + * \param[in] stage Processing stage (KNOTD_STAGE_ANSWER..KNOTD_STAGE_ADDITIONAL). + * \param[in] hook Module hook. + * + * \return Error code, KNOT_EOK if success. + */ +int knotd_mod_in_hook(knotd_mod_t *mod, knotd_stage_t stage, knotd_mod_in_hook_f hook); + +/*** DNSSEC API. ***/ + +/*! + * Initializes DNSSEC signing context. + * + * \param[in] mod Module context. + * + * \return Error code, KNOT_EOK if success. + */ +int knotd_mod_dnssec_init(knotd_mod_t *mod); + +/*! + * Loads available DNSSEC signing keys. + * + * \param[in] mod Module context. + * \param[in] verbose Print key summary into log indication. + * + * \return Error code, KNOT_EOK if success. + */ +int knotd_mod_dnssec_load_keyset(knotd_mod_t *mod, bool verbose); + +/*! + * Frees up resources before re-loading DNSSEC signing keys. + * + * \param[in] mod Module context. + */ +void knotd_mod_dnssec_unload_keyset(knotd_mod_t *mod); + +/*! + * Generates RRSIGs for given RRSet. + * + * \param[in] mod Module context. + * \param[out] rrsigs Output RRSIG RRSet. + * \param[in] rrset Input RRSet to generate RRSIGs for. + * \param[in] mm Memory context. + * + * \return Error code, KNOT_EOK if success. + */ +int knotd_mod_dnssec_sign_rrset(knotd_mod_t *mod, knot_rrset_t *rrsigs, + const knot_rrset_t *rrset, knot_mm_t *mm); + +/*! @} */ -- cgit v1.2.3