Home | History | Annotate | Line # | Download | only in include
      1 /*
      2  * zone.h -- (DNS) presentation format parser
      3  *
      4  * Copyright (c) 2022-2024, NLnet Labs. All rights reserved.
      5  *
      6  * SPDX-License-Identifier: BSD-3-Clause
      7  *
      8  */
      9 #ifndef ZONE_H
     10 #define ZONE_H
     11 
     12 /**
     13  * @file
     14  * @brief simdzone main header
     15  */
     16 
     17 #include <stdarg.h>
     18 #include <stdint.h>
     19 #include <stdbool.h>
     20 #include <stdio.h>
     21 #include <stddef.h>
     22 
     23 #include "zone/attributes.h"
     24 #include "zone/export.h"
     25 
     26 #if defined (__cplusplus)
     27 extern "C" {
     28 #endif
     29 
     30 /**
     31  * @defgroup class_codes Class codes
     32  *
     33  * Supported CLASSes.
     34  *
     35  * See @iana{DNS CLASSes,dns-parameters,dns-parameters-2} for a list of
     36  * classes registered by IANA.
     37  *
     38  * @{
     39  */
     40 /** Internet @rfc{1035} */
     41 #define ZONE_CLASS_IN (1u)
     42 /** CSNET @rfc{1035} @obsolete */
     43 #define ZONE_CLASS_CS (2u)
     44 /** CHAOS @rfc{1035} */
     45 #define ZONE_CLASS_CH (3u)
     46 /** Hesiod @rfc{1035} */
     47 #define ZONE_CLASS_HS (4u)
     48 /** Any (QCLASS) @rfc{1035} */
     49 #define ZONE_CLASS_ANY (255u)
     50 /** @} */
     51 
     52 /**
     53  * @defgroup type_codes Type codes
     54  *
     55  * Supported resource record (RR) TYPEs.
     56  *
     57  * See @iana{RR TYPEs,dns-parameters,dns-parameters-4} for a list of
     58  * types registered by IANA.
     59  *
     60  * @{
     61  */
     62 /** Host address @rfc{1035} */
     63 #define ZONE_TYPE_A (1u)
     64 /** Authoritative name server @rfc{1035} */
     65 #define ZONE_TYPE_NS (2u)
     66 /** Mail destination @rfc{1035} @obsolete */
     67 #define ZONE_TYPE_MD (3u)
     68 /** Mail forwarder @rfc{1035} @obsolete */
     69 #define ZONE_TYPE_MF (4u)
     70 /** Canonical name for an alias @rfc{1035} */
     71 #define ZONE_TYPE_CNAME (5u)
     72 /** Marks the start of authority @rfc{1035} */
     73 #define ZONE_TYPE_SOA (6u)
     74 /** Mailbox domain name @rfc{1035} @experimental */
     75 #define ZONE_TYPE_MB (7u)
     76 /** Mail group member @rfc{1035} @experimental */
     77 #define ZONE_TYPE_MG (8u)
     78 /** Mail rename domain name @rfc{1035} @experimental */
     79 #define ZONE_TYPE_MR (9u)
     80 /** Anything @rfc{883} @obsolete */
     81 #define ZONE_TYPE_NULL (10u)
     82 /** Well known service description @rfc{1035} */
     83 #define ZONE_TYPE_WKS (11u)
     84 /** Domain name pointer @rfc{1035} */
     85 #define ZONE_TYPE_PTR (12u)
     86 /** Host information @rfc{1035} */
     87 #define ZONE_TYPE_HINFO (13u)
     88 /** Mailbox or mail list information @rfc{1035} */
     89 #define ZONE_TYPE_MINFO (14u)
     90 /** Mail exchange @rfc{1035} */
     91 #define ZONE_TYPE_MX (15u)
     92 /** Text strings @rfc{1035} */
     93 #define ZONE_TYPE_TXT (16u)
     94 /** Responsible person @rfc{1035} */
     95 #define ZONE_TYPE_RP (17u)
     96 /** AFS Data Base location @rfc{1183} @rfc{5864} */
     97 #define ZONE_TYPE_AFSDB (18u)
     98 /** X.25 PSDN address @rfc{1183} */
     99 #define ZONE_TYPE_X25 (19u)
    100 /** ISDN address @rfc{1183} */
    101 #define ZONE_TYPE_ISDN (20u)
    102 /** Route Through @rfc{1183} */
    103 #define ZONE_TYPE_RT (21u)
    104 /** NSAP address, NSAP style A record @rfc{1706} */
    105 #define ZONE_TYPE_NSAP (22u)
    106 /** Domain name pointer, NSAP style @rfc{1348} @rfc{1637} */
    107 #define ZONE_TYPE_NSAP_PTR (23u)
    108 /** Signature @rfc{2535} */
    109 #define ZONE_TYPE_SIG (24u)
    110 /** Public key @rfc{2535} @rfc{2930} */
    111 #define ZONE_TYPE_KEY (25u)
    112 /** X.400 mail mapping information @rfc{2163} */
    113 #define ZONE_TYPE_PX (26u)
    114 /** Geographical Position @rfc{1712} */
    115 #define ZONE_TYPE_GPOS (27u)
    116 /** IPv6 Address @rfc{3596} */
    117 #define ZONE_TYPE_AAAA (28u)
    118 /** Location Information @rfc{1876} */
    119 #define ZONE_TYPE_LOC (29u)
    120 /** Next domain @rfc{3755} @rfc{2535} @obsolete */
    121 #define ZONE_TYPE_NXT (30u)
    122 /** Endpoint Identifier */
    123 #define ZONE_TYPE_EID (31u)
    124 /** Nimrod Locator */
    125 #define ZONE_TYPE_NIMLOC (32u)
    126 /** Server Selection @rfc{2782} */
    127 #define ZONE_TYPE_SRV (33u)
    128 /** ATM Address */
    129 #define ZONE_TYPE_ATMA (34u)
    130 /** Naming Authority Pointer @rfc{2915} @rfc{2168} @rfc{3403} */
    131 #define ZONE_TYPE_NAPTR (35u)
    132 /** Key Exchanger @rfc{2230} */
    133 #define ZONE_TYPE_KX (36u)
    134 /** CERT @rfc{4398}*/
    135 #define ZONE_TYPE_CERT (37u)
    136 /** IPv6 Address @rfc{3226} @rfc{2874} @rfc{6563} @obsolete */
    137 #define ZONE_TYPE_A6 (38u)
    138 /** DNAME @rfc{6672} */
    139 #define ZONE_TYPE_DNAME (39u)
    140 /** SINK @draft{eastlake, kitchen-sink} */
    141 #define ZONE_TYPE_SINK (40u)
    142 /** Address Prefix List @rfc{3123} */
    143 #define ZONE_TYPE_APL (42u)
    144 /** Delegation Signer @rfc{4034} @rfc{3658} */
    145 #define ZONE_TYPE_DS (43u)
    146 /** SSH Key Fingerprint @rfc{4255} */
    147 #define ZONE_TYPE_SSHFP (44u)
    148 /** IPsec public key @rfc{4025} */
    149 #define ZONE_TYPE_IPSECKEY (45u)
    150 /** Resource Record Signature @rfc{4034} @rfc{3755} */
    151 #define ZONE_TYPE_RRSIG (46u)
    152 /** Next Secure @rfc{4034} @rfc{3755} */
    153 #define ZONE_TYPE_NSEC (47u)
    154 /** DNS Public Key @rfc{4034} @rfc{3755} */
    155 #define ZONE_TYPE_DNSKEY (48u)
    156 /** DHCID @rfc{4701} */
    157 #define ZONE_TYPE_DHCID (49u)
    158 /** NSEC3 @rfc{5155} */
    159 #define ZONE_TYPE_NSEC3 (50u)
    160 /** NSEC3PARAM @rfc{5155} */
    161 #define ZONE_TYPE_NSEC3PARAM (51u)
    162 /** TLSA @rfc{6698} */
    163 #define ZONE_TYPE_TLSA (52u)
    164 /** S/MIME cert association @rfc{8162} */
    165 #define ZONE_TYPE_SMIMEA (53u)
    166 /** Host Identity Protocol @rfc{8005} */
    167 #define ZONE_TYPE_HIP (55u)
    168 /** NINFO */
    169 #define ZONE_TYPE_NINFO (56u)
    170 /** RKEY */
    171 #define ZONE_TYPE_RKEY (57u)
    172 /** Trust Anchor LINK @draft{ietf, dnsop-dnssec-trust-history} */
    173 #define ZONE_TYPE_TALINK (58u)
    174 /** Child DS @rfc{7344} */
    175 #define ZONE_TYPE_CDS (59u)
    176 /** DNSKEY(s) the Child wants reflected in DS @rfc{7344} */
    177 #define ZONE_TYPE_CDNSKEY (60u)
    178 /** OpenPGP Key @rfc{7929} */
    179 #define ZONE_TYPE_OPENPGPKEY (61u)
    180 /** Child-To-Parent Synchronization @rfc{7477} */
    181 #define ZONE_TYPE_CSYNC (62u)
    182 /** Zone message digest @rfc{8976} */
    183 #define ZONE_TYPE_ZONEMD (63u)
    184 /** Service binding @rfc{9460} */
    185 #define ZONE_TYPE_SVCB (64u)
    186 /** Service binding @rfc{9460} */
    187 #define ZONE_TYPE_HTTPS (65u)
    188 /** Endpoint discovery for delegation synchronization @draft{ietf, dnsop-generalized-notify} */
    189 #define ZONE_TYPE_DSYNC (66u)
    190 /** Sender Policy Framework @rfc{7208} */
    191 #define ZONE_TYPE_SPF (99u)
    192 /** Node Identifier @rfc{6742} */
    193 #define ZONE_TYPE_NID (104u)
    194 /** 32-bit Locator for ILNPv4-capable nodes @rfc{6742} */
    195 #define ZONE_TYPE_L32 (105u)
    196 /** 64-bit Locator for ILNPv6-capable nodes @rfc{6742} */
    197 #define ZONE_TYPE_L64 (106u)
    198 /** Name of an ILNP subnetwork @rfc{6742} */
    199 #define ZONE_TYPE_LP (107u)
    200 /** EUI-48 address @rfc{7043} */
    201 #define ZONE_TYPE_EUI48 (108u)
    202 /** EUI-64 address @rfc{7043} */
    203 #define ZONE_TYPE_EUI64 (109u)
    204 /** Uniform Resource Identifier @rfc{7553} */
    205 #define ZONE_TYPE_URI (256u)
    206 /** Certification Authority Restriction @rfc{6844} */
    207 #define ZONE_TYPE_CAA (257u)
    208 /** DNS Authoritative Source (DNS-AS) */
    209 #define ZONE_TYPE_AVC (258u)
    210 /** Digital Object Architecture @draft{durand, doa-over-dns} */
    211 #define ZONE_TYPE_DOA (259u)
    212 /** Automatic Multicast Tunneling Relay @rfc{8777} */
    213 #define ZONE_TYPE_AMTRELAY (260u)
    214 /** Resolver Information as Key/Value Pairs @rfc{9606} */
    215 #define ZONE_TYPE_RESINFO (261u)
    216 /** Public wallet address */
    217 #define ZONE_TYPE_WALLET (262u)
    218 /** BP Convergence Layer Adapter */
    219 #define ZONE_TYPE_CLA (263u)
    220 /** BP Node Number */
    221 #define ZONE_TYPE_IPN (264u)
    222 /** DNSSEC Trust Authorities */
    223 #define ZONE_TYPE_TA (32768u)
    224 /** DNSSEC Lookaside Validation @rfc{4431} @obsolete */
    225 #define ZONE_TYPE_DLV (32769u)
    226 /** @} */
    227 
    228 /**
    229  * @defgroup svc_params Service Parameter Keys
    230  *
    231  * Supported service parameters.
    232  *
    233  * See @iana{Service Parameter Keys (SvcParamKeys),dns-svcb,dns-svcparamkeys}
    234  * for a list of service parameter keys registered by IANA.
    235  *
    236  * @{
    237  */
    238 /** Parameters clients must not ignore @rfc{9460} */
    239 #define ZONE_SVC_PARAM_KEY_MANDATORY (0u)
    240 /** Application Layer Protocol Negotiation (ALPN) protocol identifiers @rfc{9460} */
    241 #define ZONE_SVC_PARAM_KEY_ALPN (1u)
    242 /** No support for default protocol (alpn must be specified) @rfc{9460} */
    243 #define ZONE_SVC_PARAM_KEY_NO_DEFAULT_ALPN (2u)
    244 /** TCP or UDP port for alternative endpoint @rfc{9460} */
    245 #define ZONE_SVC_PARAM_KEY_PORT (3u)
    246 /** IPv4 address hints @rfc{9460} */
    247 #define ZONE_SVC_PARAM_KEY_IPV4HINT (4u)
    248 /** Encrypted ClientHello (ECH) configuration @draft{ietf, tls-svcb-ech} */
    249 #define ZONE_SVC_PARAM_KEY_ECH (5u)
    250 /** IPv6 address hints @rfc{9460} */
    251 #define ZONE_SVC_PARAM_KEY_IPV6HINT (6u)
    252 /** URI template in relative form @rfc{9461} */
    253 #define ZONE_SVC_PARAM_KEY_DOHPATH (7u)
    254 /** Target is an Oblivious HTTP service @rfc{9540} */
    255 #define ZONE_SVC_PARAM_KEY_OHTTP (8u)
    256 /** Supported groups in TLS @draft{ietf, tls-key-share-prediction} */
    257 #define ZONE_SVC_PARAM_KEY_TLS_SUPPORTED_GROUPS (9u)
    258 /** Reserved ("invalid key") @rfc{9460} */
    259 #define ZONE_SVC_PARAM_KEY_INVALID_KEY (65535u)
    260 /** @} */
    261 
    262 /**
    263  * Number of bytes per block.
    264  *
    265  * Higher throughput is achieved by block-based operation. The size of a
    266  * block is determined by the word size of the CPU. To avoid pipeline flushes
    267  * as much as possible buffers are required to be padded by the number of
    268  * bytes in a single block.
    269  *
    270  * @warning The input buffer to @zone_parse_string is required to be
    271  *          null-terminated and padded, which is somewhat counter intuitive. A
    272  *          future release may lift this requirement (@issue{174}).
    273  */
    274 #define ZONE_BLOCK_SIZE (64)
    275 
    276 /**
    277  * Number of blocks per window.
    278  *
    279  * Master files can become quite large and are read in multiples of blocks.
    280  * The input buffer is expanded as needed.
    281  */
    282 #define ZONE_WINDOW_SIZE (256 * ZONE_BLOCK_SIZE) // 16KB
    283 
    284 /** Maximum size of domain name. */
    285 #define ZONE_NAME_SIZE (255)
    286 
    287 typedef struct zone_name_buffer zone_name_buffer_t;
    288 struct zone_name_buffer {
    289   /** Length of domain name stored in buffer. */
    290   size_t length;
    291   /** Maximum number of octets in a domain name plus padding. */
    292   uint8_t octets[ ZONE_NAME_SIZE + ZONE_BLOCK_SIZE ];
    293 };
    294 
    295 /** Maximum size of RDATA section. */
    296 #define ZONE_RDATA_SIZE (65535)
    297 
    298 typedef struct zone_rdata_buffer zone_rdata_buffer_t;
    299 struct zone_rdata_buffer {
    300   /** Maximum number of octets in RDATA section plus padding. */
    301   uint8_t octets[ ZONE_RDATA_SIZE + ZONE_BLOCK_SIZE ];
    302 };
    303 
    304 /**
    305  * @brief Tape capacity per-file.
    306  *
    307  * Tape capacity must be sufficiently large to hold every token from a single
    308  * worst-case read (e.g. 64 consecutive line feeds). Not likely to occur in
    309  * practice, therefore, to optimize throughput, allocate at least twice the
    310  * size so consecutive index operations can be performed.
    311  */
    312 #define ZONE_TAPE_SIZE ((100 * ZONE_BLOCK_SIZE) + ZONE_BLOCK_SIZE)
    313 
    314 typedef struct zone_file zone_file_t;
    315 struct zone_file {
    316   /** @private */
    317   zone_file_t *includer;
    318   /** @private */
    319   zone_name_buffer_t origin, owner;
    320   /** @private */
    321   uint16_t last_type;
    322   /** Last stated TTL. */
    323   uint32_t last_ttl;
    324   /** Last parsed TTL in $TTL entry. */
    325   uint32_t dollar_ttl;
    326   /** TTL passed to accept callback. */
    327   uint32_t *ttl;
    328   /** Default TTL passed to accept. */
    329   /** Last stated TTL is used as default unless $TTL entry was found. */
    330   uint32_t *default_ttl;
    331   /** @private */
    332   uint16_t last_class;
    333   /** Number of lines spanned by RR. */
    334   /** Non-terminating line feeds, i.e. escaped line feeds, line feeds in
    335       quoted sections or within parentheses, are counted, but deferred for
    336       consistency in error reports */
    337   size_t span;
    338   /** Starting line of RR. */
    339   size_t line;
    340   /** Filename in control directive. */
    341   char *name;
    342   /** Absolute path. */
    343   char *path;
    344   /** @private */
    345   FILE *handle;
    346   /** @private */
    347   bool grouped;
    348   /** @private */
    349   bool start_of_line;
    350   /** @private */
    351   uint8_t end_of_file;
    352   /** @private */
    353   struct {
    354     size_t index, length, size;
    355     char *data;
    356   } buffer;
    357   /** @private */
    358   /** scanner state is kept per-file */
    359   struct {
    360     uint64_t in_comment;
    361     uint64_t in_quoted;
    362     uint64_t is_escaped;
    363     uint64_t follows_contiguous;
    364   } state;
    365   /** @private */
    366   /** vector of tokens generated by the scanner guaranteed to be large
    367       enough to hold every token for a single read + terminators */
    368   struct { const char **head, **tail, *tape[ZONE_TAPE_SIZE + 2]; } fields;
    369   struct { const char **head, **tail, *tape[ZONE_TAPE_SIZE + 1]; } delimiters;
    370   struct { uint16_t *head, *tail, tape[ZONE_TAPE_SIZE + 1]; } newlines;
    371 };
    372 
    373 typedef struct zone_parser zone_parser_t;
    374 struct zone_parser;
    375 
    376 /**
    377  * @brief Signature of callback function that is invoked for log messages.
    378  *
    379  * By default messages are printed to stdout (info) and stderr (warnings,
    380  * errors). A custom log handler (callback) may be provided for better
    381  * integration of reporting.
    382  *
    383  * @note file maybe NULL if initial file does not exist.
    384  */
    385 typedef void(*zone_log_t)(
    386   zone_parser_t *,
    387   uint32_t, // priority
    388   const char *, // file
    389   size_t, // line
    390   const char *, // message
    391   void *); // user data
    392 
    393 /**
    394  * @brief Domain name and corresponding length in wire format.
    395  */
    396 typedef struct zone_name zone_name_t;
    397 struct zone_name {
    398   /** Length of domain name. */
    399   uint8_t length;
    400   /** Absolute, uncompressed, domain name in wire format. */
    401   const uint8_t *octets;
    402 };
    403 
    404 /**
    405  * @brief Signature of callback function invoked for each RR.
    406  *
    407  * Header is in host order, RDATA section is in network order.
    408  */
    409 typedef int32_t(*zone_accept_t)(
    410   zone_parser_t *,
    411   const zone_name_t *, // owner (length + octets)
    412   uint16_t, // type
    413   uint16_t, // class
    414   uint32_t, // ttl
    415   uint16_t, // rdlength
    416   const uint8_t *, // rdata
    417   void *); // user data
    418 
    419 /**
    420  * @brief Signature of callback function invoked on $INCLUDE.
    421  *
    422  * Signal file name in $INCLUDE directive to application. Useful for
    423  * dependency tracking, etc.
    424  */
    425 typedef int32_t(*zone_include_t)(
    426   zone_parser_t *,
    427   const char *, // name in $INCLUDE entry
    428   const char *, // fully qualified path
    429   void *); // user data
    430 
    431 /**
    432  * @brief Available configuration options.
    433  */
    434 typedef struct {
    435   /** Non-strict mode of operation. */
    436   /** Authoritative servers may choose to be more lenient when operating as
    437       a secondary as data may have been transferred over AXFR/IXFR that
    438       would have triggered an error otherwise. */
    439   bool secondary;
    440   /** Disable $INCLUDE directive. */
    441   /** Useful in setups where untrusted input may be offered. */
    442   bool no_includes;
    443   /** Maximum $INCLUDE depth. 0 for default. */
    444   uint32_t include_limit;
    445   /** Enable 1h2m3s notations for TTLS. */
    446   bool pretty_ttls;
    447   /** Origin in wire format. */
    448   zone_name_t origin;
    449   /** Default TTL to use. */
    450   uint32_t default_ttl;
    451   /** Default CLASS to use. */
    452   uint16_t default_class;
    453   struct {
    454     /** Priorities NOT to write out. */
    455     uint32_t mask;
    456     /** Callback invoked to write out log messages. */
    457     zone_log_t callback;
    458   } log;
    459   struct {
    460     /** Callback invoked for each RR. */
    461     zone_accept_t callback;
    462   } accept;
    463   struct {
    464     /** Callback invoked for each $INCLUDE entry. */
    465     zone_include_t callback;
    466   } include;
    467 } zone_options_t;
    468 
    469 /**
    470  * @brief Scratch buffer space reserved for parser.
    471  *
    472  * @note Future versions may leverage multiple buffers to improve throughput
    473  *       as parsing and committing resource records are disjunct operations.
    474  */
    475 typedef struct zone_buffers zone_buffers_t;
    476 struct zone_buffers {
    477   /** Number of name and rdata buffers available. */
    478   size_t size;
    479   /** Vector of name buffers to use as scratch buffer. */
    480   zone_name_buffer_t *owner;
    481   /** Vector of rdata buffers to use as scratch buffer. */
    482   zone_rdata_buffer_t *rdata;
    483 };
    484 
    485 /**
    486  * @brief Parser state.
    487  * @warning Do not modify directly.
    488  */
    489 struct zone_parser {
    490   /** @private */
    491   zone_options_t options;
    492   /** @private */
    493   void *user_data;
    494   struct {
    495     size_t size;
    496     struct {
    497       size_t active;
    498       zone_name_buffer_t *blocks;
    499     } owner;
    500     struct {
    501       size_t active;
    502       zone_rdata_buffer_t *blocks;
    503     } rdata;
    504   } buffers;
    505   /** @private */
    506   zone_name_buffer_t *owner;
    507   /** @private */
    508   zone_rdata_buffer_t *rdata;
    509   /** @private */
    510   zone_file_t *file, first;
    511 };
    512 
    513 /**
    514  * @defgroup return_codes Return codes
    515  *
    516  * @{
    517  */
    518 /** Success. */
    519 #define ZONE_SUCCESS (0)
    520 /** A syntax error occurred. */
    521 #define ZONE_SYNTAX_ERROR (-256)  // (-1 << 8)
    522 /** A semantic error occurred. */
    523 #define ZONE_SEMANTIC_ERROR (-512)  // (-2 << 8)
    524 /** Operation failed due to lack of memory. */
    525 #define ZONE_OUT_OF_MEMORY (-768)  // (-3 << 8)
    526 /** Bad parameter value. */
    527 #define ZONE_BAD_PARAMETER (-1024)  // (-4 << 8)
    528 /** Error reading zone file. */
    529 #define ZONE_READ_ERROR (-1280)  // (-5 << 8)
    530 /** Control directive or support for record type is not implemented. */
    531 #define ZONE_NOT_IMPLEMENTED (-1536)  // (-6 << 8)
    532 /** Specified file does not exist. */
    533 #define ZONE_NOT_A_FILE (-1792)  // (-7 << 8)
    534 /** Access to specified file is not allowed. */
    535 #define ZONE_NOT_PERMITTED (-2048)  // (-8 << 8)
    536 /** @} */
    537 
    538 /**
    539  * @brief Parse zone file
    540  *
    541  * Parse file containing resource records.
    542  *
    543  * @param[in]  parser     Zone parser
    544  * @param[in]  options    Settings used for parsing.
    545  * @param[in]  buffers    Scratch buffers used for parsing.
    546  * @param[in]  path       Path of master file to parse.
    547  * @param[in]  user_data  Pointer passed verbatim to callbacks.
    548  *
    549  * @returns @ref ZONE_SUCCESS on success or a negative number on error.
    550  */
    551 ZONE_EXPORT int32_t
    552 zone_parse(
    553   zone_parser_t *parser,
    554   const zone_options_t *options,
    555   zone_buffers_t *buffers,
    556   const char *path,
    557   void *user_data)
    558 zone_nonnull((1,2,3,4));
    559 
    560 /**
    561  * @brief Parse zone from string
    562  *
    563  * Parse string containing resource records in presentation format.
    564  *
    565  * @warning The input string must be null terminated and padded with at least
    566  *          @ref ZONE_BLOCK_SIZE bytes.
    567  *
    568  * @param[in]  parser     Zone parser
    569  * @param[in]  options    Settings used for parsing.
    570  * @param[in]  buffers    Scratch buffers used by parsing.
    571  * @param[in]  string     Input string.
    572  * @param[in]  length     Length of string (excluding null byte and padding).
    573  * @param[in]  user_data  Pointer passed verbatim to callbacks.
    574  *
    575  * @returns @ref ZONE_SUCCESS on success or a negative number on error.
    576  */
    577 ZONE_EXPORT int32_t
    578 zone_parse_string(
    579   zone_parser_t *parser,
    580   const zone_options_t *options,
    581   zone_buffers_t *buffers,
    582   const char *string,
    583   size_t length,
    584   void *user_data)
    585 zone_nonnull((1,2,3,4));
    586 
    587 /**
    588  * @defgroup log_priorities Log categories.
    589  *
    590  * @note No direct relation between log categories and error codes exists.
    591  *       Log categories communicate the importance of the log message, error
    592  *       codes communicate what went wrong to the caller.
    593  * @{
    594  */
    595 /** Error condition. */
    596 /** @hideinitializer */
    597 #define ZONE_ERROR (1u<<1)
    598 /** Warning condition. */
    599 /** @hideinitializer */
    600 #define ZONE_WARNING (1u<<2)
    601 /** Informational message. */
    602 /** @hideinitializer */
    603 #define ZONE_INFO (1u<<3)
    604 /** @} */
    605 
    606 /**
    607  * @brief Write message to active log handler.
    608  *
    609  * The zone parser operates on a per-record base and therefore cannot detect
    610  * errors that span records. e.g. SOA records being specified more than once.
    611  * The user may print a message using the active log handler, keeping the
    612  * error message format consistent.
    613  *
    614  * @param[in]  parser    Zone parser
    615  * @param[in]  priority  Log priority
    616  * @param[in]  format    Format string compatible with printf
    617  * @param[in]  ...       Variadic arguments corresponding to #format
    618  */
    619 ZONE_EXPORT void zone_log(
    620   zone_parser_t *parser,
    621   uint32_t priority,
    622   const char *format,
    623   ...)
    624 zone_nonnull((1,3))
    625 zone_format_printf(3,4);
    626 
    627 /**
    628  * @brief Write error message to active log handler.
    629  * @hideinitializer
    630  *
    631  * Shorthand to write out error message via @ref zone_log if error messages are
    632  * not to be discarded.
    633  *
    634  * @param[in]  parser  Zone parser
    635  * @param[in]  format  Format string
    636  * @param[in]  ...     Variadic arguments corresponding to #format
    637  */
    638 #define zone_error(parser, ...) \
    639   (((parser)->options.log.mask & ZONE_ERROR) ? \
    640      (void)0 : zone_log((parser), ZONE_ERROR, __VA_ARGS__))
    641 
    642 /**
    643  * @brief Write warning message to active log handler.
    644  * @hideinitializer
    645  *
    646  * Shorthand to write out warning message via @ref zone_log if warning messages
    647  * are not to be discarded.
    648  *
    649  * @param[in]  parser  Zone parser
    650  * @param[in]  format  Format string compatible with printf.
    651  * @param[in]  ...     Variadic arguments corresponding to @format.
    652  */
    653 #define zone_warning(parser, ...) \
    654   (((parser)->options.mask & ZONE_WARNING) ? \
    655      (void)0 : zone_log((parser), ZONE_WARNING, __VA_ARGS__))
    656 
    657 /**
    658  * @brief Write informational message to active log handler.
    659  * @hideinitializer
    660  *
    661  * Shorthand to write out informational message via @ref zone_log if
    662  * informational messages are not be discarded.
    663  *
    664  * @param[in]  parser  Zone parser.
    665  * @param[in]  format  Format string compatible with printf.
    666  * @param[in]  ...     Variadic arguments corresponding to @format.
    667  */
    668 #define zone_info(parser, ...) \
    669   (((parser)->options.mask & ZONE_INFO) ? \
    670      (void)0 : zone_log((parser), ZONE_INFO, __VA_ARGS__))
    671 
    672 #if defined(__cplusplus)
    673 }
    674 #endif
    675 
    676 #endif // ZONE_H
    677