1
1
/*
2
- * zone.h -- (DNS) zone parser
2
+ * zone.h -- (DNS) presentation format parser
3
3
*
4
4
* Copyright (c) 2022-2023, NLnet Labs. All rights reserved.
5
5
*
@@ -40,6 +40,8 @@ extern "C" {
40
40
#define ZONE_CH (3u)
41
41
/** Hesiod @rfc{1035} */
42
42
#define ZONE_HS (4u)
43
+ /** Any (QCLASS) @rfc{1035} */
44
+ #define ZONE_ANY (255u)
43
45
/** @} */
44
46
45
47
/**
@@ -133,11 +135,11 @@ extern "C" {
133
135
#define ZONE_NSEC (47u)
134
136
/** DNS Public Key @rfc{4034} @rfc{3755} */
135
137
#define ZONE_DNSKEY (48u)
136
- /** DHCID [RFC4701] */
138
+ /** DHCID @rfc{4701} */
137
139
#define ZONE_DHCID (49u)
138
- /** NSEC3 [RFC5155] */
140
+ /** NSEC3 @rfc{5155} */
139
141
#define ZONE_NSEC3 (50u)
140
- /** NSEC3PARAM [RFC5155] */
142
+ /** NSEC3PARAM @rfc{5155} */
141
143
#define ZONE_NSEC3PARAM (51u)
142
144
/** TLSA @rfc{6698} */
143
145
#define ZONE_TLSA (52u)
@@ -183,156 +185,9 @@ extern "C" {
183
185
#define ZONE_DLV (32769u)
184
186
/** @} */
185
187
186
- typedef struct zone_string zone_string_t ;
187
- struct zone_string {
188
- size_t length ;
189
- const char * data ;
190
- };
191
-
192
- // FIXME: probably best to rename this to mnemonic to stay with DNS terminology?
193
- typedef struct zone_symbol zone_symbol_t ;
194
- struct zone_symbol {
195
- struct {
196
- char data [24 ]; // zero padded for convenient vectorized comparison
197
- size_t length ;
198
- } key ;
199
- uint32_t value ;
200
- };
201
-
202
- typedef struct zone_table zone_table_t ;
203
- struct zone_table {
204
- size_t length ;
205
- const zone_symbol_t * symbols ; // sorted for use with bsearch
206
- };
207
-
208
- /**
209
- * @brief Type of value defined by field
210
- *
211
- * Fields are defined by their binary representation, NOT their textual
212
- * representation. e.g. time-to-live and timestamp fields are encoded as
213
- * 32-bit integers on the wire. @ref type_qualifiers are used to complement
214
- * the type information. e.g. @ref ZONE_TTL and @ref ZONE_TIME can be used to
215
- * provide extra information regarding the aforementioned types.
216
- */
217
- typedef enum {
218
- ZONE_INT8 ,
219
- ZONE_INT16 ,
220
- ZONE_INT32 ,
221
- ZONE_IP4 ,
222
- ZONE_IP6 ,
223
- ZONE_NAME ,
224
- ZONE_STRING ,
225
- // (B)inary (L)arge (Ob)ject. Inspired by relational database terminology.
226
- // Must be last.
227
- ZONE_BLOB ,
228
- ZONE_ILNP64 ,
229
- // hex fields
230
- // ZONE_EUI48 (ZONE_HEX6?)
231
- // ZONE_EUI64 (ZONE_HEX8?)
232
- // miscellaneous fields
233
- ZONE_SVC_PARAM , /**< SVCB service parameter */
234
- ZONE_TYPE_BITMAP , /**< NSEC type bitmap */
235
- ZONE_SERVICE_BITMAP /**< WKS service bitmap */
236
- } zone_type_t ;
237
-
238
- /**
239
- * @defgroup type_qualifiers Type qualifiers
240
- *
241
- * Type qualifiers provide additional information for RDATA fields. Types
242
- * indicate the binary representation of an RDATA field, qualifier(s) can be
243
- * used to communicate semantics. e.g. a time-to-live is presented on the
244
- * wire as a 32-bit integer, ZONE_TTL can be used to signal the field
245
- * represents a time-to-live value.
246
- *
247
- * @note Some types allow for more than one qualifier to be specified, hence
248
- * each qualifier is assigned a separate bit.
249
- *
250
- * @{
251
- */
252
- /**
253
- * @brief Type code (#ZONE_INT16)
254
- *
255
- * Type codes may appear in text by name or generic type notation @rfc{3597}.
256
- */
257
- #define ZONE_TYPE (1u << 0)
258
- /**
259
- * @brief Class code (#ZONE_INT16)
260
- *
261
- * Class codes may appear in text by name or generic class notation @rfc{3597}.
262
- */
263
- #define ZONE_CLASS (1u << 1)
264
- /**
265
- * @brief Time-to-live (TTL) (#ZONE_INT32)
266
- *
267
- * Time-to-live values may appear in text as numeric value (seconds) or in
268
- * "1h2m3s" notation (@e extension).
269
- */
270
- #define ZONE_TTL (1u << 2)
271
- /**
272
- * @brief Timestamp (#ZONE_INT32)
273
- *
274
- * Timestamps must be presented in text in "YYYYMMDDHHmmSS" notation.
275
- */
276
- #define ZONE_TIME (1u << 3)
277
- /** @brief Text representation is base16 (#ZONE_STRING or #ZONE_BLOB) */
278
- #define ZONE_BASE16 (1u << 4)
279
- /** @brief Text representation is base32 (#ZONE_BLOB) */
280
- #define ZONE_BASE32 (1u << 5)
281
- /** @brief Text representation is base64 (#ZONE_BLOB) */
282
- #define ZONE_BASE64 (1u << 6)
283
- /** @brief Name is compressed (#ZONE_NAME) */
284
- #define ZONE_COMPRESSED (1u << 7)
285
- /** @brief Name represents a mailbox (#ZONE_NAME) */
286
- #define ZONE_MAILBOX (1u << 8)
287
- /** @brief Name is converted to lower case for DNSSEC validation (#ZONE_NAME) */
288
- #define ZONE_LOWER_CASE (1u << 9)
289
- /** @brief Optional (#ZONE_NAME) */
290
- #define ZONE_OPTIONAL (1u << 10)
291
- /**
292
- * @brief May occur multiple times (#ZONE_STRING or #ZONE_SVC_PARAM)
293
- *
294
- * Field may occur multiple times. e.g. #ZONE_STRING in #ZONE_TXT or
295
- * #ZONE_SVC_PARAM in #ZONE_SVCB. Sequences must be the last field in the
296
- * record.
297
- */
298
- #define ZONE_SEQUENCE (1u << 11)
299
-
300
- #define ZONE_CAA_TAG (1u << 12)
301
- /** @} */
302
-
303
- typedef struct zone_field_info zone_field_info_t ;
304
- struct zone_field_info {
305
- zone_string_t name ;
306
- uint32_t type ;
307
- uint32_t qualifiers ;
308
- zone_table_t symbols ;
309
- };
310
-
311
- /**
312
- * @defgroup options Type options
313
- * @brief Options for record types
314
- *
315
- * @{
316
- */
317
- #define ZONE_ANY (1<<2)
318
- #define ZONE_EXPERIMENTAL (1<<3)
319
- #define ZONE_OBSOLETE (1<<4)
320
- /** @} */
321
-
322
- typedef struct zone_type_info zone_type_info_t ;
323
- struct zone_type_info {
324
- zone_symbol_t name ;
325
- uint32_t options ;
326
- struct {
327
- size_t length ;
328
- const zone_field_info_t * fields ;
329
- } rdata ;
330
- };
331
-
332
188
#define ZONE_BLOCK_SIZE (64)
333
189
#define ZONE_WINDOW_SIZE (256 * ZONE_BLOCK_SIZE) // 16KB
334
190
335
-
336
191
// tape capacity must be large enough to hold every token from a single
337
192
// worst-case read (e.g. 64 consecutive line feeds). in practice a single
338
193
// block will never contain 64 tokens, therefore, to optimize throughput,
@@ -350,10 +205,10 @@ struct zone_name_buffer {
350
205
uint8_t octets [ ZONE_NAME_SIZE + ZONE_PADDING_SIZE ];
351
206
};
352
207
208
+ // FIXME: explain need for NSEC padding
353
209
typedef struct zone_rdata_buffer zone_rdata_buffer_t ;
354
210
struct zone_rdata_buffer {
355
- size_t length ; /**< Length of RDATA stored in buffer */
356
- uint8_t octets [ ZONE_RDATA_SIZE + 4096 /* nsec padding */ ];
211
+ uint8_t octets [ ZONE_RDATA_SIZE + 4096 /* NSEC padding */ ];
357
212
};
358
213
359
214
// @private
@@ -425,65 +280,42 @@ struct zone_parser;
425
280
426
281
typedef void (* zone_log_t )(
427
282
zone_parser_t * ,
428
- const char * , // file
429
- size_t , // line
430
- const char * , // function
431
283
uint32_t , // category
432
284
const char * , // message
433
285
void * ); // user data
434
286
435
287
/**
436
288
* @brief Write error message to active log handler.
437
289
*
438
- * @note Direct use is discouraged. Use of #ZONE_LOG instead.
290
+ * The zone parser operates on a per-record base and therefore cannot detect
291
+ * errors that span records. e.g. SOA records being specified more than once.
292
+ * The user may print a message using the active log handler, keeping the
293
+ * error message format consistent.
439
294
*
440
295
* @param[in] parser Zone parser
441
- * @param[in] file Name of source file
442
- * @param[in] line Line number in source file
443
- * @param[in] function Name of function
444
296
* @param[in] category Log category
445
297
* @param[in] format Format string compatible with printf
446
298
* @param[in] ... Variadic arguments corresponding to #format
447
299
*/
448
300
ZONE_EXPORT void zone_log (
449
301
zone_parser_t * parser ,
450
- const char * file ,
451
- size_t line ,
452
- const char * function ,
453
302
uint32_t category ,
454
303
const char * format ,
455
304
...)
456
- zone_nonnull ((1 ,2 ,4 ,6 ))
457
- zone_format_printf (6 ,7 );
458
-
459
- /**
460
- * @brief Write log message to active log handler.
461
- *
462
- * The zone parser operates on a per-record base and therefore cannot detect
463
- * errors that span records. e.g. SOA records being specified more than once.
464
- * The user may print a message using the active log handler, keeping the
465
- * error message format consistent.
466
- *
467
- * @param[in] parser Zone parser
468
- * @param[in] category Log category
469
- * @param[in] format Format string compatible with printf
470
- * @param[in] ... Variadic arguments corresponding to @ref format
471
- */
472
- #define ZONE_LOG (parser , category , ...) \
473
- zone_log(parser, __FILE__, __LINE__, __func__, category, __VA_ARGS__)
305
+ zone_nonnull ((1 ,3 ))
306
+ zone_format_printf (3 ,4 );
474
307
475
308
typedef struct zone_name zone_name_t ;
476
309
struct zone_name {
477
310
uint8_t length ;
478
311
uint8_t * octets ;
479
312
};
480
313
481
- // invoked for each record (host order). header (owner, type, class and ttl)
314
+ // invoked for each resource record (host order). header (owner, type, class and ttl)
482
315
// fields are passed individually for convenience. rdata fields can be visited
483
316
// individually by means of the iterator
484
- typedef int32_t (* zone_add_t )(
317
+ typedef int32_t (* zone_accept_t )(
485
318
zone_parser_t * ,
486
- const zone_type_info_t * , // type information
487
319
const zone_name_t * , // owner (length + octets)
488
320
uint16_t , // type
489
321
uint16_t , // class
@@ -493,16 +325,17 @@ typedef int32_t(*zone_add_t)(
493
325
void * ); // user data
494
326
495
327
typedef struct {
496
- /** Lax mode of operation. */
328
+ /** Non-strict mode of operation. */
497
329
/** Authoritative servers may choose to be more lenient when operating as
498
- as a secondary as data may have been transferred over AXFR/IXFR that
330
+ a secondary as data may have been transferred over AXFR/IXFR that
499
331
would have triggered an error otherwise. */
500
- bool secondary ;
332
+ bool non_strict ;
501
333
/** Disable $INCLUDE directive. */
502
334
/** Useful in setups where untrusted input may be offered. */
503
335
bool no_includes ;
504
336
/** Enable 1h2m3s notations for TTLS. */
505
337
bool pretty_ttls ;
338
+ // FIXME: require origin to be in wire format? (#115)
506
339
const char * origin ;
507
340
uint32_t default_ttl ;
508
341
uint16_t default_class ;
@@ -512,13 +345,10 @@ typedef struct {
512
345
custom callback was specified. */
513
346
uint32_t categories ;
514
347
/** Callback used to write out log messages. */
515
- zone_log_t write ;
348
+ zone_log_t callback ;
516
349
} log ;
517
350
struct {
518
- zone_add_t add ;
519
- // FIXME: more callbacks to be added at a later stage to support efficient
520
- // (de)serialization of AXFR/IXFR in text representation.
521
- //zone_delete_t remove;
351
+ zone_accept_t callback ;
522
352
} accept ;
523
353
} zone_options_t ;
524
354
@@ -568,21 +398,21 @@ struct zone_parser {
568
398
/** Success */
569
399
#define ZONE_SUCCESS (0)
570
400
/** Syntax error */
571
- #define ZONE_SYNTAX_ERROR (-1 )
401
+ #define ZONE_SYNTAX_ERROR (-256) // (-1 << 8 )
572
402
/** Semantic error */
573
- #define ZONE_SEMANTIC_ERROR (-2 )
403
+ #define ZONE_SEMANTIC_ERROR (-512) // (-2 << 8 )
574
404
/** Operation failed due to lack of memory */
575
- #define ZONE_OUT_OF_MEMORY (-3 )
405
+ #define ZONE_OUT_OF_MEMORY (-768) // (-3 << 8 )
576
406
/** Bad parameter value */
577
- #define ZONE_BAD_PARAMETER (-4 )
407
+ #define ZONE_BAD_PARAMETER (-1024) // (-4 << 8 )
578
408
/** Error reading zone file */
579
- #define ZONE_IO_ERROR (-5 )
409
+ #define ZONE_READ_ERROR (-1280) // (-5 << 8 )
580
410
/** Control directive or support for record type is not implemented */
581
- #define ZONE_NOT_IMPLEMENTED (-6 )
411
+ #define ZONE_NOT_IMPLEMENTED (-1536) // (-6 << 8 )
582
412
/** Specified file does not exist */
583
- #define ZONE_NOT_A_FILE (-6 )
413
+ #define ZONE_NOT_A_FILE (-1792) // (-7 << 8 )
584
414
/** Access to specified file is not allowed */
585
- #define ZONE_NOT_PERMITTED (-7 )
415
+ #define ZONE_NOT_PERMITTED (-2048) // (-8 << 8 )
586
416
/** @} */
587
417
588
418
/**
0 commit comments