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