diff options
Diffstat (limited to 'src/libzscanner/scanner.h')
-rw-r--r-- | src/libzscanner/scanner.h | 405 |
1 files changed, 405 insertions, 0 deletions
diff --git a/src/libzscanner/scanner.h b/src/libzscanner/scanner.h new file mode 100644 index 0000000..b45ca48 --- /dev/null +++ b/src/libzscanner/scanner.h @@ -0,0 +1,405 @@ +/* Copyright (C) 2021 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/>. + */ + +/*! + * \file + * + * \brief Zone scanner core interface. + * + * \addtogroup zscanner + * @{ + */ + +#pragma once + +#include <stdbool.h> +#include <stddef.h> +#include <stdint.h> + +#include "libzscanner/error.h" + +/*! \brief Maximal length of rdata. */ +#define ZS_MAX_RDATA_LENGTH 65535 +/*! \brief Maximal length of domain name. */ +#define ZS_MAX_DNAME_LENGTH 255 +/*! \brief Maximal length of domain name label. */ +#define ZS_MAX_LABEL_LENGTH 63 + +/*! \brief Length of ipv4 address in the wire format. */ +#define ZS_INET4_ADDR_LENGTH 4 +/*! \brief Length of ipv6 address in the wire format. */ +#define ZS_INET6_ADDR_LENGTH 16 + +/*! \brief Number of bitmap windows. */ +#define ZS_BITMAP_WINDOWS 256 + +/*! \brief Ragel call stack size (see Ragel internals). */ +#define ZS_RAGEL_STACK_SIZE 16 + +/*! \brief Auxiliary structure for storing bitmap window items (see RFC4034). */ +typedef struct { + uint8_t bitmap[32]; + uint8_t length; +} zs_win_t; + +/*! \brief Auxiliary structure for storing one APL record (see RFC3123). */ +typedef struct { + uint8_t excl_flag; + uint16_t addr_family; + uint8_t prefix_length; +} zs_apl_t; + +/*! \brief Auxiliary structure for storing LOC information (see RFC1876). */ +typedef struct { + uint32_t d1, d2; + uint32_t m1, m2; + uint32_t s1, s2; + uint32_t alt; + uint64_t siz, hp, vp; + int8_t lat_sign, long_sign, alt_sign; +} zs_loc_t; + +/*! \brief Auxiliary structure for storing SVCB information. */ +typedef struct { + uint8_t *params_position; + uint8_t *mandatory_position; + uint8_t *param_position; + int32_t last_key; +} zs_svcb_t; + +/*! \brief Scanner states describing the result. */ +typedef enum { + ZS_STATE_NONE, /*!< Initial state (no data). */ + ZS_STATE_DATA, /*!< A record parsed. */ + ZS_STATE_ERROR, /*!< An error occurred. */ + ZS_STATE_INCLUDE, /*!< An include directive (see include_filename, buffer). */ + ZS_STATE_EOF, /*!< The end of the current input reached. */ + ZS_STATE_STOP /*!< Early stop (possibly set from a callback). */ +} zs_state_t; + +/*! + * \brief Context structure for zone scanner. + * + * This structure contains following items: + * - Copies of Ragel internal variables. The scanner can be called many times + * on smaller parts of zone file/memory. So it is necessary to preserve + * internal values between subsequent scanner callings. + * - Auxiliary variables which are used during processing zone data. + * - Pointers to callback functions and pointer to any arbitrary data which + * can be used in callback functions. + * - Zone file and error information. + * - Output variables (r_ prefix) containing all parts of zone record. These + * data are useful during processing via callback function. + */ +typedef struct zs_scanner zs_scanner_t; // Forward declaration due to arguments. +struct zs_scanner { + /*! Current state (Ragel internals). */ + int cs; + /*! Stack top (Ragel internals). */ + int top; + /*! Call stack (Ragel internals). */ + int stack[ZS_RAGEL_STACK_SIZE]; + + /*! Indicates whether current record is multiline. */ + bool multiline; + /*! Auxiliary number for all numeric operations. */ + uint64_t number64; + /*! Auxiliary variable for time and other numeric operations. */ + uint64_t number64_tmp; + /*! Auxiliary variable for float numeric operations. */ + uint32_t decimals; + /*! Auxiliary variable for float numeric operations. */ + uint32_t decimal_counter; + + /*! Auxiliary variable for item length (label, base64, ...). */ + uint32_t item_length; + /*! Auxiliary index for item length position in array. */ + uint32_t item_length_position; + /*! Auxiliary pointer to item length. */ + uint8_t *item_length_location; + /*! Auxiliary 2-byte length locator. */ + uint8_t *item_length2_location; + /*! Auxiliary buffer length. Is zero if no comment after a valid record. */ + uint32_t buffer_length; + /*! Auxiliary buffer. Contains a comment after a valid record. */ + uint8_t buffer[ZS_MAX_RDATA_LENGTH]; + /*! Auxiliary buffer for current included file name. */ + char include_filename[ZS_MAX_RDATA_LENGTH]; + /*! Absolute path for relative includes. */ + char *path; + + /*! Auxiliary array of bitmap window blocks. */ + zs_win_t windows[ZS_BITMAP_WINDOWS]; + /*! Last window block which is used (-1 means no window). */ + int16_t last_window; + /*! Auxiliary apl structure. */ + zs_apl_t apl; + /*! Auxiliary loc structure. */ + zs_loc_t loc; + /*! Auxiliary svcb structure. */ + zs_svcb_t svcb; + /*! Auxiliary IP address storage. */ + uint8_t addr[ZS_INET6_ADDR_LENGTH]; + /*! Allow text strings longer than 255 characters. */ + bool long_string; + /*! Comma separated string list indication (svcb parsing). */ + bool comma_list; + + /*! Pointer to the actual dname storage (origin/owner/rdata). */ + uint8_t *dname; + /*! Pointer to the actual dname length storage. */ + uint32_t *dname_length; + /*! + * Temporary dname length which is copied to dname_length after + * dname processing. + */ + uint32_t dname_tmp_length; + /*! Position of the last free r_data byte. */ + uint32_t r_data_tail; + + /*! Length of the current origin. */ + uint32_t zone_origin_length; + /*! + * Wire format of the current origin (ORIGIN directive sets this). + * + * \note Maximal dname length check is after each valid label. + */ + uint8_t zone_origin[ZS_MAX_DNAME_LENGTH + ZS_MAX_LABEL_LENGTH]; + /*! Value of the default class. */ + uint16_t default_class; + /*! Value of the current default ttl (TTL directive sets this). */ + uint32_t default_ttl; + + /*! The current processing state. */ + zs_state_t state; + + /*! Processing callbacks and auxiliary data. */ + struct { + /*! Automatic zone processing using record/error callbacks. */ + bool automatic; + /*! Callback function for correct zone record. */ + void (*record)(zs_scanner_t *); + /*! Callback function for wrong situations. */ + void (*error)(zs_scanner_t *); + /*! Callback function for pure comment line. */ + void (*comment)(zs_scanner_t *); + /*! Arbitrary data useful inside callback functions. */ + void *data; + } process; + + /*! Input parameters. */ + struct { + /*! Start of the block. */ + const char *start; + /*! Current parser position. */ + const char *current; + /*! End of the block. */ + const char *end; + /*! Indication for the final block parsing. */ + bool eof; + /*! Indication of being mmap()-ed (malloc()-ed otherwise). */ + bool mmaped; + } input; + + /*! File input parameters. */ + struct { + /*! Zone file name. */ + char *name; + /*!< File descriptor. */ + int descriptor; + } file; + + struct { + /*! Last occurred error/warning code. */ + int code; + /*! Error/warning counter. */ + uint64_t counter; + /*! Indicates serious error - parsing cannot continue. */ + bool fatal; + } error; + + /*! Zone data line counter. */ + uint64_t line_counter; + + /*! Length of the current record owner. */ + uint32_t r_owner_length; + /*! + * Owner of the current record. + * + * \note Maximal dname length check is after each valid label. + */ + uint8_t r_owner[ZS_MAX_DNAME_LENGTH + ZS_MAX_LABEL_LENGTH]; + /*! Class of the current record. */ + uint16_t r_class; + /*! TTL of the current record. */ + uint32_t r_ttl; + /*! Type of the current record data. */ + uint16_t r_type; + /*! Length of the current rdata. */ + uint32_t r_data_length; + /*! Current rdata. */ + uint8_t r_data[ZS_MAX_RDATA_LENGTH]; + + /* + * Example: a. IN 60 MX 1 b. ; A comment + * + * r_owner_length = 3 + * r_owner = 016100 + * r_class = 1 + * r_ttl = 60 + * r_type = 15 + * r_data_length = 5 + * r_data = 0001016200 + * buffer_length = 11 + * buffer = " A comment" + */ +}; + +/*! + * \brief Initializes the scanner context. + * + * \note Error code is stored in the scanner context. + * + * \param scanner Scanner context. + * \param origin Initial zone origin. + * \param rclass Zone class value. + * \param ttl Initial ttl value. + * + * \retval 0 if success. + * \retval -1 if error. + */ +int zs_init( + zs_scanner_t *scanner, + const char *origin, + const uint16_t rclass, + const uint32_t ttl +); + +/*! + * \brief Deinitializes the scanner context. + * + * \param scanner Scanner context. + */ +void zs_deinit( + zs_scanner_t *scanner +); + +/*! + * \brief Sets the scanner to parse a zone data string. + * + * \note Error code is stored in the scanner context. + * + * \param scanner Scanner context. + * \param input Input zone data string to parse. + * \param size Size of the input string. + * + * \retval 0 if success. + * \retval -1 if error. + */ +int zs_set_input_string( + zs_scanner_t *scanner, + const char *input, + size_t size +); + +/*! + * \brief Sets the scanner to parse a zone file. + * + * \note Error code is stored in the scanner context. + * + * \param scanner Scanner context. + * \param file_name Name of the file to parse. + * + * \retval 0 if success. + * \retval -1 if error. + */ +int zs_set_input_file( + zs_scanner_t *scanner, + const char *file_name +); + +/*! + * \brief Sets the scanner processing callbacks for automatic processing. + * + * \note Error code is stored in the scanner context. + * + * \param scanner Scanner context. + * \param process_record Processing callback function (may be NULL). + * \param process_error Error callback function (may be NULL). + * \param data Arbitrary data useful in callback functions. + * + * \retval 0 if success. + * \retval -1 if error. + */ +int zs_set_processing( + zs_scanner_t *scanner, + void (*process_record)(zs_scanner_t *), + void (*process_error)(zs_scanner_t *), + void *data +); + +/*! + * \brief Sets the scanner comment processing callback for automatic processing. + * + * \note If the comment is after a valid resource record, the callback is + * executed before a record processing callback! + * \note Optional data must be set via zs_set_processing. + * + * \param scanner Scanner context. + * \param process_comment Processing callback function (may be NULL). + * + * \retval 0 if success. + * \retval -1 if error. + */ +int zs_set_processing_comment( + zs_scanner_t *scanner, + void (*process_comment)(zs_scanner_t *) +); + +/*! + * \brief Parses one record from the input. + * + * The following processing should be based on the scanner->state. + * + * \note Error code and other information are stored in the scanner context. + * + * \param scanner Scanner context. + * + * \retval 0 if success. + * \retval -1 if error. + */ +int zs_parse_record( + zs_scanner_t *scanner +); + +/*! + * \brief Launches automatic parsing of the whole input. + * + * For each correctly recognized record, the record callback is executed. + * If any syntax error occurs, the error callback is executed. + * + * \note Error code and other information are stored in the scanner context. + * + * \param scanner Scanner context. + * + * \retval 0 if success. + * \retval -1 if error. + */ +int zs_parse_all( + zs_scanner_t *scanner +); + +/*! @} */ |