diff --git a/CHANGELOG.md b/CHANGELOG.md index 331ed5e..877d42f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,9 +9,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added +- Support for EID, NIMLOC, SINK, TALINK, DSYNC, DOA, AMTRELAY and IPN RR types. ### Fixed +- Empty base16 and base64 in CDS and CDNSKEY can be represented with a '0'. + As specified in Section 4 of RFC 8078. ## [0.2.1] - 2025-01-17 diff --git a/include/zone.h b/include/zone.h index 35ee6ec..905f450 100644 --- a/include/zone.h +++ b/include/zone.h @@ -119,8 +119,14 @@ extern "C" { #define ZONE_TYPE_LOC (29u) /** Next domain @rfc{3755} @rfc{2535} @obsolete */ #define ZONE_TYPE_NXT (30u) +/** Endpoint Identifier */ +#define ZONE_TYPE_EID (31u) +/** Nimrod Locator */ +#define ZONE_TYPE_NIMLOC (32u) /** Server Selection @rfc{2782} */ #define ZONE_TYPE_SRV (33u) +/** ATM Address */ +#define ZONE_TYPE_ATMA (34u) /** Naming Authority Pointer @rfc{2915} @rfc{2168} @rfc{3403} */ #define ZONE_TYPE_NAPTR (35u) /** Key Exchanger @rfc{2230} */ @@ -131,6 +137,8 @@ extern "C" { #define ZONE_TYPE_A6 (38u) /** DNAME @rfc{6672} */ #define ZONE_TYPE_DNAME (39u) +/** SINK @draft{eastlake, kitchen-sink} */ +#define ZONE_TYPE_SINK (40u) /** Address Prefix List @rfc{3123} */ #define ZONE_TYPE_APL (42u) /** Delegation Signer @rfc{4034} @rfc{3658} */ @@ -161,6 +169,8 @@ extern "C" { #define ZONE_TYPE_NINFO (56u) /** RKEY */ #define ZONE_TYPE_RKEY (57u) +/** Trust Anchor LINK @draft{ietf, dnsop-dnssec-trust-history} */ +#define ZONE_TYPE_TALINK (58u) /** Child DS @rfc{7344} */ #define ZONE_TYPE_CDS (59u) /** DNSKEY(s) the Child wants reflected in DS @rfc{7344} */ @@ -176,6 +186,8 @@ extern "C" { /** Service binding @rfc{9460} */ #define ZONE_TYPE_HTTPS (65u) /** Sender Policy Framework @rfc{7208} */ +#define ZONE_TYPE_DSYNC (66u) +/** Endpoint discovery for delegation synchronization @draft{ietf, dnsop-generalized-notify} */ #define ZONE_TYPE_SPF (99u) /** Node Identifier @rfc{6742} */ #define ZONE_TYPE_NID (104u) @@ -195,12 +207,18 @@ extern "C" { #define ZONE_TYPE_CAA (257u) /** DNS Authoritative Source (DNS-AS) */ #define ZONE_TYPE_AVC (258u) +/** Digital Object Architecture @draft{durand, doa-over-dns} */ +#define ZONE_TYPE_DOA (259u) +/** Automatic Multicast Tunneling Relay @rfc{8777} */ +#define ZONE_TYPE_AMTRELAY (260u) /** Resolver Information as Key/Value Pairs @rfc{9606} */ #define ZONE_TYPE_RESINFO (261u) /** Public wallet address */ #define ZONE_TYPE_WALLET (262u) /** BP Convergence Layer Adapter */ #define ZONE_TYPE_CLA (263u) +/** BP Node Number */ +#define ZONE_TYPE_IPN (264u) /** DNSSEC Trust Authorities */ #define ZONE_TYPE_TA (32768u) /** DNSSEC Lookaside Validation @rfc{4431} @obsolete */ diff --git a/scripts/check-RR-types.sh b/scripts/check-RR-types.sh index 36cba1f..c00df73 100755 --- a/scripts/check-RR-types.sh +++ b/scripts/check-RR-types.sh @@ -17,7 +17,7 @@ RECORDS=`xmlstarlet select --template --match "/_:registry/_:registry[@id='dns-p rm ${TEMPFILE} for RECORD in ${RECORDS} do - TYPE=`echo ${RECORD} | awk -F# '{ print $1 }'` + TYPE=`echo ${RECORD} | awk -F# '{ print $1 }'|sed 's/-/_/g'` VALUE=`echo ${RECORD} | awk -F# '{ print $2 }'` RECORD_TYPE=`echo ${RECORD} | awk -F# '{ print $3 }'` RECORD_REF=`echo ${RECORD} | awk -F# '{ print $4 }'` diff --git a/scripts/hash.c b/scripts/hash.c index 46c254c..c43a816 100644 --- a/scripts/hash.c +++ b/scripts/hash.c @@ -55,12 +55,16 @@ static const tuple_t types_and_classes[] = { { "AAAA", 28, true }, { "LOC", 29, true }, { "NXT", 30, true }, + { "EID", 31, true }, + { "NIMLOC", 32, true }, { "SRV", 33, true }, + { "ATMA", 34, true }, { "NAPTR", 35, true }, { "KX", 36, true }, { "CERT", 37, true }, { "A6", 38, true }, { "DNAME", 39, true }, + { "SINK", 40, true }, { "APL", 42, true }, { "DS", 43, true }, { "SSHFP", 44, true }, @@ -76,6 +80,7 @@ static const tuple_t types_and_classes[] = { { "HIP", 55, true }, { "NINFO", 56, true }, { "RKEY", 57, true }, + { "TALINK", 58, true }, { "CDS", 59, true }, { "CDNSKEY", 60, true }, { "OPENPGPKEY", 61, true }, @@ -83,6 +88,7 @@ static const tuple_t types_and_classes[] = { { "ZONEMD", 63, true }, { "SVCB", 64, true }, { "HTTPS", 65, true }, + { "DSYNC", 66, true }, { "SPF", 99, true }, { "NID", 104, true }, { "L32", 105, true }, @@ -93,9 +99,12 @@ static const tuple_t types_and_classes[] = { { "URI", 256, true }, { "CAA", 257, true }, { "AVC", 258, true }, + { "DOA", 259, true }, + { "AMTRELAY", 260, true }, { "RESINFO", 261, true }, { "WALLET", 262, true }, { "CLA", 263, true }, + { "IPN", 264, true }, { "TA", 32768, true }, { "DLV", 32769, true } }; @@ -127,9 +136,9 @@ static void print_table(uint64_t magic) for (size_t j=i+8; i < j; i++) { uint16_t code; switch(keys[i].code) { - case 32768: code = 265; // index of TA in types array in generic/types.h + case 32768: code = 270; // index of TA in types array in generic/types.h break; - case 32769: code = 266; // index of DLV in types array in generic/types.h + case 32769: code = 271; // index of DLV in types array in generic/types.h break; default : code = keys[i].code; break; diff --git a/src/fallback/parser.c b/src/fallback/parser.c index 5b78432..18a1ec8 100644 --- a/src/fallback/parser.c +++ b/src/fallback/parser.c @@ -35,6 +35,7 @@ #include "generic/apl.h" #include "generic/svcb.h" #include "generic/cert.h" +#include "generic/atma.h" #include "generic/algorithm.h" #include "generic/types.h" #include "generic/type.h" diff --git a/src/generic/atma.h b/src/generic/atma.h new file mode 100644 index 0000000..1dbb0be --- /dev/null +++ b/src/generic/atma.h @@ -0,0 +1,215 @@ +/* + * atma.h -- ATMA parser (see: https://web.archive.org/web/20190112072924/http://www.broadband-forum.org/ftp/pub/approved-specs/af-dans-0152.000.pdf ) + * + * Copyright (c) 2025, NLnet Labs. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ +#ifndef ATMA_H +#define ATMA_H + +static const uint8_t bad_atma_chars[256] = { + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0x00 - 0x07 + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0x08 - 0x0f + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0x10 - 0x17 + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0x18 - 0x1f + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0x20 - 0x27 + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, // 0x28 - 0x2f + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x30 - 0x37 + 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0x38 - 0x3f + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0x40 - 0x47 + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0x48 - 0x4f + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0x50 - 0x57 + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0x58 - 0x5f + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0x60 - 0x67 + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0x68 - 0x6f + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0x70 - 0x77 + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0x78 - 0x7f + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0x80 - 0x87 + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0x88 - 0x8f + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0x90 - 0x97 + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0x98 - 0x9f + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0xa0 - 0xa7 + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0xa8 - 0xaf + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0xb0 - 0xb7 + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0xb8 - 0xbf + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0xc0 - 0xc7 + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0xc8 - 0xcf + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0xd0 - 0xd7 + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0xd8 - 0xdf + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0xe0 - 0xe7 + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0xe0 - 0xe7 + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0xf8 - 0xff + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0xf8 - 0xff +}; + +static const uint8_t atma_increment[256] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x01 - 0x07 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x08 - 0x0f + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x10 - 0x17 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x18 - 0x1f + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x20 - 0x27 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x28 - 0x2f + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0x30 - 0x37 + 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x38 - 0x3f + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x40 - 0x47 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x48 - 0x4f + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x50 - 0x57 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x58 - 0x5f + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x60 - 0x67 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x68 - 0x6f + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x70 - 0x77 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x78 - 0x7f + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x80 - 0x87 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x88 - 0x8f + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x90 - 0x97 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x98 - 0x9f + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xa0 - 0xa7 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xa8 - 0xaf + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xb0 - 0xb7 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xb8 - 0xbf + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xc0 - 0xc7 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xc8 - 0xcf + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xd0 - 0xd7 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xd8 - 0xdf + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xe0 - 0xe7 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xe0 - 0xe7 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xf8 - 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xf8 - 0x00 +}; + + +nonnull_all +static really_inline int32_t parse_atma_e164( + parser_t *parser, + const type_info_t *type, + const rdata_info_t *field, + rdata_t *rdata, + const token_t *token) +{ + uint32_t bad_chars = 0; + for (size_t count=1; count < token->length; count++) { + const uint8_t octet = (uint8_t)token->data[count]; + *rdata->octets = octet; + rdata->octets += atma_increment[octet]; + bad_chars |= bad_atma_chars[octet]; + } + if (bad_chars) + SEMANTIC_ERROR(parser, "Invalid %s in %s", NAME(field), NAME(type)); + + return 0; +} + +nonnull((1,2,4,5)) +static really_inline int atma_stream_decode( + struct base16_state *state, + const char *src, + size_t srclen, + uint8_t *out, + size_t *outlen) +{ + int ret = 0; + const uint8_t *s = (const uint8_t *) src; + uint8_t *o = (uint8_t *) out; + uint32_t q; + + // Use local temporaries to avoid cache thrashing: + size_t olen = 0; + size_t slen = srclen; + struct base16_state st; + st.eof = state->eof; + st.bytes = state->bytes; + st.carry = state->carry; + + if (st.eof) { + *outlen = 0; + return ret; + } + + // Duff's device again: + switch (st.bytes) + { +#if defined(__SUNPRO_C) +#pragma error_messages(off, E_STATEMENT_NOT_REACHED) +#endif + for (;;) +#if defined(__SUNPRO_C) +#pragma error_messages(default, E_STATEMENT_NOT_REACHED) +#endif + { + case 0: + base16_dec_loop_generic_32(&s, &slen, &o, &olen); + if (slen-- == 0) { + ret = 1; + break; + } + if ((q = base16_table_dec_32bit_d0[*s++]) == 256) { + st.eof = BASE16_EOF; + break; + } else if (q == 257) { + continue; + } + st.carry = (uint8_t)q; + st.bytes = 1; + + // fallthrough + + case 1: + if (slen-- == 0) { + ret = 1; + break; + } + if ((q = base16_table_dec_32bit_d1[*s++]) == 256) { + st.eof = BASE16_EOF; + break; + } else if (q == 257) { + continue; + } + *o++ = st.carry | (uint8_t)q; + st.carry = 0; + st.bytes = 0; + olen++; + } + } + + state->eof = st.eof; + state->bytes = st.bytes; + state->carry = st.carry; + *outlen = olen; + return ret; +} + +nonnull((1,3,4)) +static really_inline int atma_decode( + const char *src, size_t srclen, uint8_t *out, size_t *outlen) +{ + struct base16_state state = { .eof = 0, .bytes = 0, .carry = 0 }; + return atma_stream_decode(&state, src, srclen, out, outlen) & !state.bytes; +} + +nonnull_all +static really_inline int32_t parse_atma( + parser_t *parser, + const type_info_t *type, + const rdata_info_t *field, + rdata_t *rdata, + const token_t *token) +{ + if (token->length && (char)*token->data == '+') { + *rdata->octets++ = 1; + if ((uintptr_t)rdata->limit - (uintptr_t)rdata->octets < token->length) + SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(field), NAME(type)); + return parse_atma_e164(parser, type, field, rdata, token); + } + size_t length = token->length / 2; + if ((uintptr_t)rdata->limit - (uintptr_t)rdata->octets < length) + SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(field), NAME(type)); + *rdata->octets++ = 0; + if (!atma_decode(token->data, token->length, rdata->octets, &length)) + SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(field), NAME(type)); + rdata->octets += length; + return 0; +} + +#endif // ATMA_H diff --git a/src/generic/base16.h b/src/generic/base16.h index 3510944..a9e4e98 100644 --- a/src/generic/base16.h +++ b/src/generic/base16.h @@ -27,7 +27,7 @@ static const uint32_t base16_table_dec_32bit_d0[256] = { 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, - 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 257, 256, 0, 16, 32, 48, 64, 80, 96, 112, 128, 144, 256, 256, 256, 256, 256, 256, 256, 160, 176, 192, 208, 224, 240, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, @@ -52,7 +52,7 @@ static const uint32_t base16_table_dec_32bit_d1[256] = { 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, - 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 257, 256, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 256, 256, 256, 256, 256, 256, 256, 10, 11, 12, 13, 14, 15, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, diff --git a/src/generic/number.h b/src/generic/number.h index e75874d..81dcc92 100644 --- a/src/generic/number.h +++ b/src/generic/number.h @@ -69,6 +69,26 @@ static really_inline int32_t scan_int32( return sum <= 4294967295u; } +nonnull((1,3)) +static really_inline int32_t scan_int64( + const char *data, size_t length, uint64_t *number) +{ + uint64_t sum = (uint8_t)data[0] - '0'; + + if (sum > 9 || !length || length > 20) + return 0; + + for (size_t count=1; count < length; count++) { + const uint8_t digit = (uint8_t)data[count] - '0'; + sum = sum * 10 + digit; + if (digit > 9) + return 0; + } + + *number = sum; + return 1; /* TODO: detect overflow */ +} + nonnull_all static really_inline int32_t parse_int8( parser_t *parser, @@ -118,4 +138,21 @@ static really_inline int32_t parse_int32( return 0; } +nonnull_all +static really_inline int32_t parse_int64( + parser_t *parser, + const type_info_t *type, + const rdata_info_t *field, + rdata_t *rdata, + const token_t *token) +{ + uint64_t number; + if (!scan_int64(token->data, token->length, &number)) + SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(field), NAME(type)); + number = htobe64(number); + memcpy(rdata->octets, &number, 8); + rdata->octets += 8; + return 0; +} + #endif // NUMBER_H diff --git a/src/generic/type.h b/src/generic/type.h index bab3a00..d0fca19 100644 --- a/src/generic/type.h +++ b/src/generic/type.h @@ -18,38 +18,38 @@ static const struct { const mnemonic_t *mnemonic; int32_t code; } types_and_classes[256] = { - V(0), V(0), V(0), V(0), V(0), V(0), V(0), T(20), - T(3), V(0), V(0), V(0), V(0), T(261), V(0), V(0), - T(60), V(0), V(0), T(105), V(0), V(0), V(0), T(258), - V(0), V(0), V(0), V(0), T(30), V(0), T(28), V(0), - V(0), T(16), V(0), V(0), T(56), T(14), T(22), V(0), - V(0), T(13), V(0), T(47), T(21), V(0), T(65), T(27), - V(0), V(0), V(0), V(0), V(0), T(1), T(62), V(0), - V(0), C(1), V(0), T(44), V(0), V(0), T(33), V(0), - V(0), V(0), V(0), V(0), T(63), V(0), T(266), V(0), - C(3), T(99), T(37), V(0), V(0), V(0), C(2), T(43), - V(0), T(50), C(4), T(51), V(0), V(0), V(0), T(2), - T(49), T(42), T(19), T(23), V(0), T(6), V(0), V(0), - V(0), V(0), T(29), V(0), T(7), V(0), V(0), V(0), - V(0), T(57), V(0), V(0), V(0), V(0), V(0), T(36), - T(15), V(0), V(0), T(26), T(11), V(0), V(0), V(0), - V(0), V(0), V(0), V(0), T(104), V(0), T(8), V(0), - V(0), V(0), T(38), V(0), T(9), V(0), T(64), V(0), - V(0), V(0), V(0), V(0), V(0), V(0), T(39), T(52), - T(24), V(0), T(5), T(106), V(0), V(0), V(0), V(0), - T(265), V(0), V(0), V(0), V(0), T(25), V(0), T(18), - T(48), V(0), T(53), V(0), V(0), V(0), T(59), V(0), - V(0), V(0), V(0), V(0), T(4), V(0), T(10), V(0), - V(0), V(0), V(0), V(0), V(0), T(55), V(0), V(0), - V(0), V(0), V(0), V(0), V(0), V(0), V(0), V(0), - V(0), V(0), V(0), V(0), V(0), V(0), V(0), V(0), - V(0), V(0), T(61), T(12), V(0), V(0), V(0), V(0), - V(0), T(108), V(0), V(0), T(257), V(0), V(0), V(0), - T(35), V(0), T(263), V(0), V(0), V(0), V(0), T(107), - V(0), V(0), V(0), V(0), T(17), V(0), T(45), V(0), - V(0), V(0), V(0), V(0), V(0), V(0), T(46), V(0), - V(0), T(109), V(0), V(0), V(0), V(0), V(0), V(0), - V(0), V(0), V(0), V(0), T(262), V(0), T(256), V(0) + V(0), V(0), V(0), V(0), V(0), V(0), T(34), V(0), + V(0), V(0), T(30), V(0), V(0), T(57), V(0), T(16), + V(0), V(0), T(56), T(14), T(12), V(0), V(0), T(13), + T(61), V(0), T(105), V(0), V(0), V(0), T(32), T(258), + V(0), T(107), T(47), V(0), V(0), V(0), T(17), V(0), + T(257), V(0), V(0), V(0), V(0), V(0), V(0), V(0), + T(65), V(0), V(0), T(18), V(0), T(1), V(0), T(263), + V(0), V(0), V(0), V(0), T(51), V(0), V(0), T(106), + T(3), V(0), V(0), T(31), V(0), V(0), V(0), V(0), + V(0), T(50), T(44), T(104), T(10), V(0), V(0), V(0), + V(0), V(0), T(55), V(0), T(28), V(0), V(0), V(0), + V(0), V(0), V(0), V(0), V(0), V(0), V(0), T(39), + T(35), V(0), V(0), T(5), T(29), T(262), V(0), V(0), + T(109), V(0), T(264), V(0), V(0), V(0), V(0), V(0), + V(0), T(21), V(0), V(0), V(0), V(0), V(0), V(0), + T(37), C(1), T(58), V(0), V(0), V(0), V(0), V(0), + V(0), V(0), V(0), C(3), V(0), T(52), T(11), T(20), + V(0), T(261), V(0), V(0), V(0), T(48), V(0), V(0), + V(0), T(25), C(2), T(43), V(0), V(0), C(4), T(60), + V(0), V(0), T(7), T(2), V(0), V(0), T(46), T(22), + V(0), V(0), V(0), V(0), V(0), V(0), V(0), T(64), + V(0), T(260), V(0), V(0), V(0), V(0), T(38), V(0), + V(0), T(259), T(59), V(0), V(0), V(0), T(42), T(36), + T(8), T(15), V(0), T(26), T(27), T(6), V(0), T(99), + V(0), V(0), V(0), V(0), V(0), V(0), V(0), T(53), + T(9), T(63), T(33), V(0), T(271), T(270), V(0), T(40), + V(0), V(0), T(24), T(19), V(0), V(0), V(0), V(0), + V(0), V(0), V(0), T(108), V(0), V(0), V(0), T(62), + V(0), V(0), V(0), V(0), V(0), T(66), T(4), V(0), + V(0), V(0), T(256), V(0), T(49), V(0), V(0), V(0), + V(0), V(0), T(45), V(0), V(0), T(23), V(0), V(0), + V(0), V(0), V(0), V(0), V(0), V(0), V(0), V(0) }; #undef V @@ -110,7 +110,7 @@ static really_inline uint8_t hash(uint64_t prefix) prefix = le64toh(prefix); uint32_t value = (uint32_t)((prefix >> 32) ^ prefix); // magic value is generated using hash.c, rerun when adding types - return (uint8_t)((value * 3523548378ull) >> 32); + return (uint8_t)((value * 3537259401ull) >> 32); } nonnull_all diff --git a/src/generic/types.h b/src/generic/types.h index 1e388df..de972e3 100644 --- a/src/generic/types.h +++ b/src/generic/types.h @@ -87,6 +87,8 @@ static really_inline int32_t check_bytes( #define check_int32(...) check_bytes(__VA_ARGS__, sizeof(uint32_t)) +#define check_int64(...) check_bytes(__VA_ARGS__, sizeof(uint64_t)) + #define check_ip4(...) check_bytes(__VA_ARGS__, 4) #define check_ip6(...) check_bytes(__VA_ARGS__, 16) @@ -1112,6 +1114,27 @@ static int32_t parse_nxt_rdata( return accept_rr(parser, type, rdata); } +nonnull_all +static int32_t check_eid_rr( + parser_t *parser, const type_info_t *type, const rdata_t *rdata) +{ + if ((uintptr_t)rdata->octets - (uintptr_t)parser->rdata->octets <= 0) + SYNTAX_ERROR(parser, "Invalid %s record", NAME(type)); + return accept_rr(parser, type, rdata); +} + +nonnull_all +static int32_t parse_eid_rdata( + parser_t *parser, const type_info_t *type, rdata_t *rdata, token_t *token) +{ + int32_t code; + const rdata_info_t *fields = type->rdata.fields; + + if ((code = parse_base16_sequence(parser, type, &fields[1], rdata, token)) < 0) + return code; + return check_eid_rr(parser, type, rdata); +} + nonnull_all static int32_t check_srv_rr( parser_t *parser, const type_info_t *type, const rdata_t *rdata) @@ -1161,6 +1184,32 @@ static int32_t parse_srv_rdata( return accept_rr(parser, type, rdata); } +nonnull_all +static int32_t check_atma_rr( + parser_t *parser, const type_info_t *type, const rdata_t *rdata) +{ + assert(rdata->octets >= parser->rdata->octets); + if ((uintptr_t)rdata->octets - (uintptr_t)parser->rdata->octets > 2) + return accept_rr(parser, type, rdata); + SYNTAX_ERROR(parser, "Invalid %s", NAME(type)); +} + +nonnull_all +static int32_t parse_atma_rdata( + parser_t *parser, const type_info_t *type, rdata_t *rdata, token_t *token) +{ + int32_t code; + const rdata_info_t *fields = type->rdata.fields; + + if ((code = have_contiguous(parser, type, &fields[0], token)) < 0) + return code; + if ((code = parse_atma(parser, type, &fields[0], rdata, token)) < 0) + return code; + if ((code = take_delimiter(parser, type, token)) < 0) + return code; + return accept_rr(parser, type, rdata); +} + nonnull_all static int32_t check_naptr_rr( parser_t *parser, const type_info_t *type, const rdata_t *rdata) @@ -1245,6 +1294,41 @@ static int32_t parse_cert_rdata( return accept_rr(parser, type, rdata); } +nonnull_all +static int32_t check_sink_rr( + parser_t *parser, const type_info_t *type, const rdata_t *rdata) +{ + // FIXME: implement actual checks + (void)type; + + assert(rdata->octets >= parser->rdata->octets); + if ((uintptr_t)rdata->octets - (uintptr_t)parser->rdata->octets < 3) + SYNTAX_ERROR(parser, "Invalid %s", NAME(type)); + return accept_rr(parser, type, rdata); +} + +nonnull_all +static int32_t parse_sink_rdata( + parser_t *parser, const type_info_t *type, rdata_t *rdata, token_t *token) +{ + int32_t code; + const rdata_info_t *fields = type->rdata.fields; + + if ((code = have_contiguous(parser, type, &fields[0], token)) < 0) + return code; + if ((code = parse_int8(parser, type, &fields[0], rdata, token)) < 0) + return code; + if ((code = take_contiguous(parser, type, &fields[1], token)) < 0) + return code; + if ((code = parse_int8(parser, type, &fields[1], rdata, token)) < 0) + return code; + take(parser, token); + if ((code = parse_base64_sequence(parser, type, &fields[3], rdata, token)) < 0) + return code; + + return accept_rr(parser, type, rdata); +} + nonnull_all static int32_t check_apl_rr( parser_t *parser, const type_info_t *type, const rdata_t *rdata) @@ -1312,7 +1396,7 @@ static int32_t check_ds_rr( SEMANTIC_ERROR(parser, "Invalid digest in %s", NAME(type)); } - if (c >= n) + if (c > n) SYNTAX_ERROR(parser, "Invalid %s", NAME(type)); return accept_rr(parser, type, rdata); } @@ -1337,7 +1421,8 @@ static int32_t parse_ds_rdata( if ((code = parse_int8(parser, type, &fields[2], rdata, token)) < 0) return code; take(parser, token); - if ((code = parse_base16_sequence(parser, type, &fields[3], rdata, token)) < 0) + if (!(token->length == 1 && (char)*token->data == '0') + && (code = parse_base16_sequence(parser, type, &fields[3], rdata, token)) < 0) return code; const uint8_t digest_algorithm = parser->rdata->octets[3]; @@ -1707,7 +1792,7 @@ static int32_t check_dnskey_rr( (r = check(&c, check_int8(parser, type, &f[2], o+c, n-c)))) return r; - if (c >= n) + if (c > n) SYNTAX_ERROR(parser, "Invalid %s", NAME(type)); return accept_rr(parser, type, rdata); } @@ -1732,7 +1817,8 @@ static int32_t parse_dnskey_rdata( if ((code = parse_algorithm(parser, type, &fields[2], rdata, token)) < 0) return code; take(parser, token); - if ((code = parse_base64_sequence(parser, type, &fields[3], rdata, token)) < 0) + if (!(token->length == 1 && (char)*token->data == '0') + && (code = parse_base64_sequence(parser, type, &fields[3], rdata, token)) < 0) return code; return accept_rr(parser, type, rdata); @@ -2189,6 +2275,70 @@ static int32_t parse_https_rdata( return accept_rr(parser, type, rdata); } +nonnull_all +static int32_t check_dsync_rr( + parser_t *parser, const type_info_t *type, const rdata_t *rdata) +{ + int32_t r; + size_t c = 0; + const size_t n = (uintptr_t)rdata->octets - (uintptr_t)parser->rdata->octets; + const uint8_t *o = parser->rdata->octets; + const rdata_info_t *f = type->rdata.fields; + + if ((r = check(&c, check_int16(parser, type, &f[0], o, n))) || + (r = check(&c, check_int8(parser, type, &f[1], o+c, n-c))) || + (r = check(&c, check_int16(parser, type, &f[2], o+c, n-c))) || + (r = check(&c, check_name(parser, type, &f[3], o+c, n-c)))) + return r; + + const uint8_t dsync_scheme = o[2]; + uint16_t dsync_type; + memcpy(&dsync_type, o, sizeof(dsync_type)); + dsync_type = be16toh(dsync_type); + if (dsync_scheme == 1 && dsync_type != ZONE_TYPE_CDS + && dsync_type != ZONE_TYPE_CSYNC) + SEMANTIC_ERROR(parser, "Wrong type for scheme 1 in %s", NAME(type)); + + if (c > n) + SYNTAX_ERROR(parser, "Invalid %s", NAME(type)); + return accept_rr(parser, type, rdata); +} + +nonnull_all +static int32_t parse_dsync_rdata( + parser_t *parser, const type_info_t *type, rdata_t *rdata, token_t *token) +{ + int32_t code; + const rdata_info_t *fields = type->rdata.fields; + + if ((code = have_contiguous(parser, type, &fields[0], token)) < 0) + return code; + if ((code = parse_type(parser, type, &fields[0], rdata, token)) < 0) + return code; + if ((code = take_contiguous(parser, type, &fields[1], token)) < 0) + return code; + if ((code = parse_int8(parser, type, &fields[1], rdata, token)) < 0) + return code; + if ((code = take_contiguous(parser, type, &fields[2], token)) < 0) + return code; + if ((code = parse_int16(parser, type, &fields[2], rdata, token)) < 0) + return code; + if ((code = take_contiguous(parser, type, &fields[3], token)) < 0) + return code; + if ((code = parse_name(parser, type, &fields[3], rdata, token)) < 0) + return code; + + const uint8_t dsync_scheme = parser->rdata->octets[2]; + uint16_t dsync_type; + memcpy(&dsync_type, parser->rdata->octets, sizeof(dsync_type)); + dsync_type = be16toh(dsync_type); + if (dsync_scheme == 1 && dsync_type != ZONE_TYPE_CDS + && dsync_type != ZONE_TYPE_CSYNC) + SEMANTIC_ERROR(parser, "Wrong type for scheme 1 in %s", NAME(type)); + + return accept_rr(parser, type, rdata); +} + nonnull_all static int32_t check_nid_rr( parser_t *parser, const type_info_t *type, const rdata_t *rdata) @@ -2438,6 +2588,255 @@ static int32_t parse_caa_rdata( return accept_rr(parser, type, rdata); } +nonnull_all +static int32_t check_doa_rr( + parser_t *parser, const type_info_t *type, const rdata_t *rdata) +{ + int32_t r; + size_t c = 0; + const size_t n = (uintptr_t)rdata->octets - (uintptr_t)parser->rdata->octets; + const uint8_t *o = parser->rdata->octets; + const rdata_info_t *f = type->rdata.fields; + + if ((r = check(&c, check_int32(parser, type, &f[0], o, n))) || + (r = check(&c, check_int32(parser, type, &f[1], o+c, n-c))) || + (r = check(&c, check_int8(parser, type, &f[2], o+c, n-c))) || + (r = check(&c, check_string(parser, type, &f[3], o+c, n-c)))) + return r; + if (c > n) + SYNTAX_ERROR(parser, "Invalid %s", NAME(type)); + return accept_rr(parser, type, rdata); +} + +nonnull_all +static int32_t parse_doa_rdata( + parser_t *parser, const type_info_t *type, rdata_t *rdata, token_t *token) +{ + int32_t code; + const rdata_info_t *fields = type->rdata.fields; + + if ((code = have_contiguous(parser, type, &fields[0], token)) < 0) + return code; + if ((code = parse_int32(parser, type, &fields[0], rdata, token)) < 0) + return code; + if ((code = take_contiguous(parser, type, &fields[1], token)) < 0) + return code; + if ((code = parse_int32(parser, type, &fields[1], rdata, token)) < 0) + return code; + if ((code = take_contiguous(parser, type, &fields[2], token)) < 0) + return code; + if ((code = parse_int8(parser, type, &fields[2], rdata, token)) < 0) + return code; + if ((code = take_quoted_or_contiguous(parser, type, &fields[3], token)) < 0) + return code; + if ((code = parse_string(parser, type, &fields[3], rdata, token)) < 0) + return code; + take(parser, token); + if (!(token->length == 1 && ((char)*token->data == '0' || (char)*token->data == '-')) + && (code = parse_base64_sequence(parser, type, &fields[4], rdata, token)) < 0) + return code; + return accept_rr(parser, type, rdata); +} + +nonnull_all +static int32_t check_amtrelay_rr( + parser_t *parser, const type_info_t *type, const rdata_t *rdata); + +nonnull_all +static int32_t parse_amtrelay_rdata( + parser_t *parser, const type_info_t *type, rdata_t *rdata, token_t *token); + +diagnostic_push() +gcc_diagnostic_ignored(missing-field-initializers) +clang_diagnostic_ignored(missing-field-initializers) + +static const rdata_info_t amtrelay_ipv4_rdata_fields[] = { + FIELD("precedence"), + FIELD("discovery optional"), + FIELD("type"), + FIELD("relay") +}; + +static const type_info_t amtrelay_ipv4[] = { + TYPE("AMTRELAY", ZONE_TYPE_AMTRELAY, ZONE_CLASS_IN, FIELDS(amtrelay_ipv4_rdata_fields), + check_amtrelay_rr, parse_amtrelay_rdata), +}; + +static const rdata_info_t amtrelay_ipv6_rdata_fields[] = { + FIELD("precedence"), + FIELD("discovery optional"), + FIELD("type"), + FIELD("relay") +}; + +static const type_info_t amtrelay_ipv6[] = { + TYPE("AMTRELAY", ZONE_TYPE_AMTRELAY, ZONE_CLASS_IN, FIELDS(amtrelay_ipv6_rdata_fields), + check_amtrelay_rr, parse_amtrelay_rdata), +}; + +diagnostic_pop() + +nonnull_all +static int32_t check_amtrelay_rr( + parser_t *parser, const type_info_t *type, const rdata_t *rdata) +{ + int32_t r; + size_t c = 0; + const size_t n = (uintptr_t)rdata->octets - (uintptr_t)parser->rdata->octets; + const uint8_t *o = parser->rdata->octets; + const type_info_t *t = type; + const rdata_info_t *f = type->rdata.fields; + + if ((r = check(&c, check_int8(parser, type, &f[0], o, n))) || + (r = check(&c, check_int8(parser, type, &f[2], o+c, n-c)))) + return r; + + switch (parser->rdata->octets[1] & 0x7f) { + case 1: /* IPv4 address */ + t = (const type_info_t *)amtrelay_ipv4; + f = amtrelay_ipv4_rdata_fields; + if ((r = check(&c, check_ip4(parser, t, &f[3], o+c, n-c))) < 0) + return r; + break; + case 2: /* IPv6 address */ + t = (const type_info_t *)amtrelay_ipv6; + f = amtrelay_ipv6_rdata_fields; + if ((r = check(&c, check_ip6(parser, t, &f[3], o+c, n-c))) < 0) + return r; + break; + case 0: /* no gateway */ + break; + case 3: /* domain name */ + if ((r = check(&c, check_name(parser, t, &f[3], o+c, n-c))) < 0) + return r; + break; + default: + SYNTAX_ERROR(parser, "Invalid %s", NAME(type)); + } + if (c < n) + SYNTAX_ERROR(parser, "Trailing data in %s", NAME(t)); + return accept_rr(parser, t, rdata); +} + +nonnull_all +static int32_t parse_amtrelay_rdata( + parser_t *parser, const type_info_t *type, rdata_t *rdata, token_t *token) +{ + int32_t code; + const rdata_info_t *fields = type->rdata.fields; + uint8_t *octets = rdata->octets; + uint8_t D; + + if ((code = have_contiguous(parser, type, &fields[0], token)) < 0) + return code; + if ((code = parse_int8(parser, type, &fields[0], rdata, token)) < 0) + return code; + + if ((code = take_contiguous(parser, type, &fields[1], token)) < 0) + return code; + if (token->length != 1) + SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(&fields[1]), NAME(type)); + switch((char)*token->data) { + case '0': + D = 0x00; + break; + case '1': + D = 0x80; + break; + default : + SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(&fields[1]), NAME(type)); + } + + if ((code = take_contiguous(parser, type, &fields[2], token)) < 0) + return code; + if ((code = parse_int8(parser, type, &fields[2], rdata, token)) < 0) + return code; + + if (octets[1]) { + if ((code = take_contiguous(parser, type, &fields[3], token)) < 0) + return code; + switch (octets[1]) { + case 1: /* IPv4 address */ + type = (const type_info_t *)amtrelay_ipv4; + fields = type->rdata.fields; + if ((code = parse_ip4(parser, type, &fields[3], rdata, token)) < 0) + return code; + break; + case 2: /* IPv6 address */ + type = (const type_info_t *)amtrelay_ipv6; + fields = type->rdata.fields; + if ((code = parse_ip6(parser, type, &fields[3], rdata, token)) < 0) + return code; + break; + case 3: /* domain name */ + if ((code = parse_name(parser, type, &fields[3], rdata, token)) < 0) + return code; + break; + default: + SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(&fields[3]), NAME(type)); + } + } + octets[1] |= D; + if ((code = take_delimiter(parser, type, token)) < 0) + return code; + return accept_rr(parser, type, rdata); +} + +nonnull_all +static int32_t check_ipn_rr( + parser_t *parser, const type_info_t *type, const rdata_t *rdata) +{ + int32_t r; + size_t c = 0; + const size_t n = (uintptr_t)rdata->octets - (uintptr_t)parser->rdata->octets; + const uint8_t *o = parser->rdata->octets; + const rdata_info_t *f = type->rdata.fields; + + if ((r = check(&c, check_int64(parser, type, &f[0], o, n)))) + return r; + if (c > n) + SYNTAX_ERROR(parser, "Invalid %s", NAME(type)); + return accept_rr(parser, type, rdata); +} + +nonnull_all +static int32_t parse_ipn_rdata( + parser_t *parser, const type_info_t *type, rdata_t *rdata, token_t *token) +{ + int32_t code; + const rdata_info_t *fields = type->rdata.fields; + token_t left, right; + + /* draft-johnson-dns-ipn-cla-07 Section 3.1. IPN: + * Presentation format for these resource records are either a 64 bit + * unsigned decimal integer, or two 32 bit unsigned decimal integers + * delimited by a period with the most significant 32 bits first and least + * significant 32 bits last. + */ + if ((code = have_contiguous(parser, type, &fields[0], token)) < 0) + return code; + if (!(right.data = memchr(token->data, '.', token->length))) { + if ((code = parse_int64(parser, type, &fields[0], rdata, token)) < 0) + return code; + if ((code = take_delimiter(parser, type, token)) < 0) + return code; + return accept_rr(parser, type, rdata); + } + left.code = token->code; + left.data = token->data; + left.length = (size_t)(right.data - token->data); + right.code = token->code; + right.data += 1; + right.length = token->length - left.length - 1; + if ((code = parse_int32(parser, type, &fields[0], rdata, &left)) < 0) + return code; + if ((code = parse_int32(parser, type, &fields[0], rdata, &right)) < 0) + return code; + if ((code = take_delimiter(parser, type, token)) < 0) + return code; + return accept_rr(parser, type, rdata); +} + nonnull_all static int32_t check_generic_rr( parser_t *parser, const type_info_t *type, const rdata_t *rdata) @@ -2654,6 +3053,14 @@ static const rdata_info_t nxt_rdata_fields[] = { FIELD("type bit map") }; +static const rdata_info_t eid_rdata_fields[] = { + FIELD("end point identifier") +}; + +static const rdata_info_t nimloc_rdata_fields[] = { + FIELD("nimrod locator") +}; + static const rdata_info_t srv_rdata_fields[] = { FIELD("priority"), FIELD("weight"), @@ -2661,6 +3068,10 @@ static const rdata_info_t srv_rdata_fields[] = { FIELD("target") }; +static const rdata_info_t atma_rdata_fields[] = { + FIELD("address") +}; + static const rdata_info_t naptr_rdata_fields[] = { FIELD("order"), FIELD("preference"), @@ -2698,6 +3109,12 @@ static const rdata_info_t dname_rdata_fields[] = { FIELD("source") }; +static const rdata_info_t sink_rdata_fields[] = { + FIELD("coding"), + FIELD("subcoding"), + FIELD("data") +}; + static const rdata_info_t apl_rdata_fields[] = { FIELD("prefix") }; @@ -2818,6 +3235,12 @@ static const rdata_info_t rkey_rdata_fields[] = { FIELD("publickey") }; +// https://www.iana.org/assignments/dns-parameters/TALINK/talink-completed-template +static const rdata_info_t talink_rdata_fields[] = { + FIELD("start or previous"), + FIELD("end or next") +}; + static const rdata_info_t openpgpkey_rdata_fields[] = { FIELD("key") }; @@ -2847,6 +3270,13 @@ static const rdata_info_t https_rdata_fields[] = { FIELD("params") }; +static const rdata_info_t dsync_rdata_fields[] = { + FIELD("rrtype"), + FIELD("scheme"), + FIELD("port"), + FIELD("target") +}; + static const rdata_info_t spf_rdata_fields[] = { FIELD("text") }; @@ -2899,6 +3329,25 @@ static const rdata_info_t avc_rdata_fields[] = { FIELD("text") }; +// draft-durand-doa-over-dns-02 +static const rdata_info_t doa_rdata_fields[] = { + FIELD("enterprise"), + FIELD("type"), + FIELD("location"), + FIELD("media type"), + FIELD("data") +}; + +// RFC 8777 +// AMTRELAY is different because the rdata depends on the type +static const rdata_info_t amtrelay_rdata_fields[] = { + FIELD("precedence"), + FIELD("discovery optional"), + FIELD("type"), + FIELD("relay"), +}; + + // RFC 9606 static const rdata_info_t resinfo_rdata_fields[] = { FIELD("text") @@ -2914,6 +3363,12 @@ static const rdata_info_t cla_rdata_fields[] = { FIELD("text") }; +// https://www.iana.org/assignments/dns-parameters/IPN/ipn-completed-template +// and https://datatracker.ietf.org/doc/draft-johnson-dns-ipn-cla/07/ +static const rdata_info_t ipn_rdata_fields[] = { + FIELD("CBHE Node Number") +}; + static const rdata_info_t ta_rdata_fields[] = { FIELD("key"), FIELD("algorithm"), @@ -2992,15 +3447,14 @@ static const type_info_t types[] = { check_loc_rr, parse_loc_rdata), TYPE("NXT", ZONE_TYPE_NXT, ZONE_CLASS_ANY, FIELDS(nxt_rdata_fields), // obsolete check_nxt_rr, parse_nxt_rdata), - - UNKNOWN_TYPE(31), - UNKNOWN_TYPE(32), - + TYPE("EID", ZONE_TYPE_EID, ZONE_CLASS_IN, FIELDS(eid_rdata_fields), + check_eid_rr, parse_eid_rdata), + TYPE("NIMLOC", ZONE_TYPE_NIMLOC, ZONE_CLASS_IN, FIELDS(nimloc_rdata_fields), + check_eid_rr, parse_eid_rdata), TYPE("SRV", ZONE_TYPE_SRV, ZONE_CLASS_IN, FIELDS(srv_rdata_fields), check_srv_rr, parse_srv_rdata), - - UNKNOWN_TYPE(34), - + TYPE("ATMA", ZONE_TYPE_ATMA, ZONE_CLASS_IN, FIELDS(atma_rdata_fields), + check_atma_rr, parse_atma_rdata), TYPE("NAPTR", ZONE_TYPE_NAPTR, ZONE_CLASS_IN, FIELDS(naptr_rdata_fields), check_naptr_rr, parse_naptr_rdata), TYPE("KX", ZONE_TYPE_KX, ZONE_CLASS_IN, FIELDS(kx_rdata_fields), @@ -3013,7 +3467,8 @@ static const type_info_t types[] = { TYPE("DNAME", ZONE_TYPE_DNAME, ZONE_CLASS_ANY, FIELDS(dname_rdata_fields), check_ns_rr, parse_ns_rdata), - UNKNOWN_TYPE(40), + TYPE("SINK", ZONE_TYPE_SINK, ZONE_CLASS_ANY, FIELDS(sink_rdata_fields), + check_sink_rr, parse_sink_rdata), UNKNOWN_TYPE(41), TYPE("APL", ZONE_TYPE_APL, ZONE_CLASS_IN, FIELDS(apl_rdata_fields), @@ -3048,10 +3503,9 @@ static const type_info_t types[] = { TYPE("NINFO", ZONE_TYPE_NINFO, ZONE_CLASS_ANY, FIELDS(ninfo_rdata_fields), check_txt_rr, parse_txt_rdata), TYPE("RKEY", ZONE_TYPE_RKEY, ZONE_CLASS_ANY, FIELDS(rkey_rdata_fields), - check_dnskey_rr, parse_dnskey_rdata), - - UNKNOWN_TYPE(58), - + check_dnskey_rr, parse_dnskey_rdata), + TYPE("TALINK", ZONE_TYPE_TALINK, ZONE_CLASS_ANY, FIELDS(talink_rdata_fields), + check_minfo_rr, parse_minfo_rdata), TYPE("CDS", ZONE_TYPE_CDS, ZONE_CLASS_ANY, FIELDS(cds_rdata_fields), check_ds_rr, parse_ds_rdata), TYPE("CDNSKEY", ZONE_TYPE_CDNSKEY, ZONE_CLASS_ANY, FIELDS(cdnskey_rdata_fields), @@ -3066,8 +3520,8 @@ static const type_info_t types[] = { check_svcb_rr, parse_svcb_rdata), TYPE("HTTPS", ZONE_TYPE_HTTPS, ZONE_CLASS_IN, FIELDS(https_rdata_fields), check_https_rr, parse_https_rdata), - - UNKNOWN_TYPE(66), + TYPE("DSYNC", ZONE_TYPE_DSYNC, ZONE_CLASS_ANY, FIELDS(dsync_rdata_fields), + check_dsync_rr, parse_dsync_rdata), UNKNOWN_TYPE(67), UNKNOWN_TYPE(68), UNKNOWN_TYPE(69), @@ -3275,23 +3729,29 @@ static const type_info_t types[] = { check_caa_rr, parse_caa_rdata), TYPE("AVC", ZONE_TYPE_AVC, ZONE_CLASS_ANY, FIELDS(avc_rdata_fields), check_txt_rr, parse_txt_rdata), - - UNKNOWN_TYPE(259), - UNKNOWN_TYPE(260), - + TYPE("DOA", ZONE_TYPE_DOA, ZONE_CLASS_ANY, FIELDS(doa_rdata_fields), + check_doa_rr, parse_doa_rdata), + TYPE("AMTRELAY", ZONE_TYPE_AMTRELAY, ZONE_CLASS_ANY, FIELDS(amtrelay_rdata_fields), + check_amtrelay_rr, parse_amtrelay_rdata), TYPE("RESINFO", ZONE_TYPE_RESINFO, ZONE_CLASS_ANY, FIELDS(resinfo_rdata_fields), check_txt_rr, parse_txt_rdata), TYPE("WALLET", ZONE_TYPE_WALLET, ZONE_CLASS_ANY, FIELDS(wallet_rdata_fields), check_txt_rr, parse_txt_rdata), TYPE("CLA", ZONE_TYPE_CLA, ZONE_CLASS_ANY, FIELDS(cla_rdata_fields), check_txt_rr, parse_txt_rdata), + TYPE("IPN", ZONE_TYPE_IPN, ZONE_CLASS_ANY, FIELDS(ipn_rdata_fields), + check_ipn_rr, parse_ipn_rdata), - UNKNOWN_TYPE(264), + UNKNOWN_TYPE(265), + UNKNOWN_TYPE(266), + UNKNOWN_TYPE(267), + UNKNOWN_TYPE(268), + UNKNOWN_TYPE(269), - /* Map 32768 in hash.c to 265 */ + /* Map 32768 in hash.c to 270 */ TYPE("TA", ZONE_TYPE_TA, ZONE_CLASS_ANY, FIELDS(ta_rdata_fields), // obsolete check_ds_rr, parse_ds_rdata), - /* Map 32769 in hash.c to 266 */ + /* Map 32769 in hash.c to 271 */ TYPE("DLV", ZONE_TYPE_DLV, ZONE_CLASS_ANY, FIELDS(dlv_rdata_fields), // obsolete check_ds_rr, parse_ds_rdata) }; diff --git a/src/haswell/parser.c b/src/haswell/parser.c index a0be7be..e45042c 100644 --- a/src/haswell/parser.c +++ b/src/haswell/parser.c @@ -36,6 +36,7 @@ #include "generic/apl.h" #include "generic/svcb.h" #include "generic/cert.h" +#include "generic/atma.h" #include "generic/algorithm.h" #include "generic/types.h" #include "westmere/type.h" diff --git a/src/westmere/parser.c b/src/westmere/parser.c index 2354f30..1ad349e 100644 --- a/src/westmere/parser.c +++ b/src/westmere/parser.c @@ -36,6 +36,7 @@ #include "generic/apl.h" #include "generic/svcb.h" #include "generic/cert.h" +#include "generic/atma.h" #include "generic/algorithm.h" #include "generic/types.h" #include "westmere/type.h" diff --git a/src/westmere/type.h b/src/westmere/type.h index b3403e9..ee3bc96 100644 --- a/src/westmere/type.h +++ b/src/westmere/type.h @@ -18,38 +18,38 @@ static const struct { const mnemonic_t *mnemonic; int32_t code; } types_and_classes[256] = { - V(0), V(0), V(0), V(0), V(0), V(0), V(0), T(20), - T(3), V(0), V(0), V(0), V(0), T(261), V(0), V(0), - T(60), V(0), V(0), T(105), V(0), V(0), V(0), T(258), - V(0), V(0), V(0), V(0), T(30), V(0), T(28), V(0), - V(0), T(16), V(0), V(0), T(56), T(14), T(22), V(0), - V(0), T(13), V(0), T(47), T(21), V(0), T(65), T(27), - V(0), V(0), V(0), V(0), V(0), T(1), T(62), V(0), - V(0), C(1), V(0), T(44), V(0), V(0), T(33), V(0), - V(0), V(0), V(0), V(0), T(63), V(0), T(266), V(0), - C(3), T(99), T(37), V(0), V(0), V(0), C(2), T(43), - V(0), T(50), C(4), T(51), V(0), V(0), V(0), T(2), - T(49), T(42), T(19), T(23), V(0), T(6), V(0), V(0), - V(0), V(0), T(29), V(0), T(7), V(0), V(0), V(0), - V(0), T(57), V(0), V(0), V(0), V(0), V(0), T(36), - T(15), V(0), V(0), T(26), T(11), V(0), V(0), V(0), - V(0), V(0), V(0), V(0), T(104), V(0), T(8), V(0), - V(0), V(0), T(38), V(0), T(9), V(0), T(64), V(0), - V(0), V(0), V(0), V(0), V(0), V(0), T(39), T(52), - T(24), V(0), T(5), T(106), V(0), V(0), V(0), V(0), - T(265), V(0), V(0), V(0), V(0), T(25), V(0), T(18), - T(48), V(0), T(53), V(0), V(0), V(0), T(59), V(0), - V(0), V(0), V(0), V(0), T(4), V(0), T(10), V(0), - V(0), V(0), V(0), V(0), V(0), T(55), V(0), V(0), - V(0), V(0), V(0), V(0), V(0), V(0), V(0), V(0), - V(0), V(0), V(0), V(0), V(0), V(0), V(0), V(0), - V(0), V(0), T(61), T(12), V(0), V(0), V(0), V(0), - V(0), T(108), V(0), V(0), T(257), V(0), V(0), V(0), - T(35), V(0), T(263), V(0), V(0), V(0), V(0), T(107), - V(0), V(0), V(0), V(0), T(17), V(0), T(45), V(0), - V(0), V(0), V(0), V(0), V(0), V(0), T(46), V(0), - V(0), T(109), V(0), V(0), V(0), V(0), V(0), V(0), - V(0), V(0), V(0), V(0), T(262), V(0), T(256), V(0) + V(0), V(0), V(0), V(0), V(0), V(0), T(34), V(0), + V(0), V(0), T(30), V(0), V(0), T(57), V(0), T(16), + V(0), V(0), T(56), T(14), T(12), V(0), V(0), T(13), + T(61), V(0), T(105), V(0), V(0), V(0), T(32), T(258), + V(0), T(107), T(47), V(0), V(0), V(0), T(17), V(0), + T(257), V(0), V(0), V(0), V(0), V(0), V(0), V(0), + T(65), V(0), V(0), T(18), V(0), T(1), V(0), T(263), + V(0), V(0), V(0), V(0), T(51), V(0), V(0), T(106), + T(3), V(0), V(0), T(31), V(0), V(0), V(0), V(0), + V(0), T(50), T(44), T(104), T(10), V(0), V(0), V(0), + V(0), V(0), T(55), V(0), T(28), V(0), V(0), V(0), + V(0), V(0), V(0), V(0), V(0), V(0), V(0), T(39), + T(35), V(0), V(0), T(5), T(29), T(262), V(0), V(0), + T(109), V(0), T(264), V(0), V(0), V(0), V(0), V(0), + V(0), T(21), V(0), V(0), V(0), V(0), V(0), V(0), + T(37), C(1), T(58), V(0), V(0), V(0), V(0), V(0), + V(0), V(0), V(0), C(3), V(0), T(52), T(11), T(20), + V(0), T(261), V(0), V(0), V(0), T(48), V(0), V(0), + V(0), T(25), C(2), T(43), V(0), V(0), C(4), T(60), + V(0), V(0), T(7), T(2), V(0), V(0), T(46), T(22), + V(0), V(0), V(0), V(0), V(0), V(0), V(0), T(64), + V(0), T(260), V(0), V(0), V(0), V(0), T(38), V(0), + V(0), T(259), T(59), V(0), V(0), V(0), T(42), T(36), + T(8), T(15), V(0), T(26), T(27), T(6), V(0), T(99), + V(0), V(0), V(0), V(0), V(0), V(0), V(0), T(53), + T(9), T(63), T(33), V(0), T(271), T(270), V(0), T(40), + V(0), V(0), T(24), T(19), V(0), V(0), V(0), V(0), + V(0), V(0), V(0), T(108), V(0), V(0), V(0), T(62), + V(0), V(0), V(0), V(0), V(0), T(66), T(4), V(0), + V(0), V(0), T(256), V(0), T(49), V(0), V(0), V(0), + V(0), V(0), T(45), V(0), V(0), T(23), V(0), V(0), + V(0), V(0), V(0), V(0), V(0), V(0), V(0), V(0) }; #undef V @@ -102,7 +102,7 @@ static really_inline uint8_t hash(uint64_t prefix) { uint32_t value = (uint32_t)((prefix >> 32) ^ prefix); // magic value is generated using hash.c, rerun when adding types - return (uint8_t)((value * 3523548378ull) >> 32); + return (uint8_t)((value * 3537259401ull) >> 32); } nonnull_all diff --git a/src/zone.c b/src/zone.c index 04f85d6..833af7f 100644 --- a/src/zone.c +++ b/src/zone.c @@ -157,12 +157,12 @@ static void close_file( assert(!is_string || file == &parser->first); assert(!is_string || file->handle == NULL); (void)parser; - +#ifndef NDEBUG const bool is_stdin = file->name && file->name != not_a_file && strcmp(file->name, "-") == 0; assert(!is_stdin || (!file->handle || file->handle == stdin)); - +#endif if (file->buffer.data && !is_string) free(file->buffer.data); file->buffer.data = NULL; diff --git a/tests/semantics.c b/tests/semantics.c index 8bd6d57..0d35691 100644 --- a/tests/semantics.c +++ b/tests/semantics.c @@ -177,3 +177,62 @@ void zonemd_digest_lengths(void **state) assert_int_equal(code, tests[i].code); } } + +/*!cmocka */ +void dsync_scheme_types(void **state) +{ + static const char fmt[] = + "example.com. 86400 IN DSYNC %s %d 5359 ( type-scanner.example.net. )"; + static const char hex_fmt[] = + "example.com. 86400 CLASS1 TYPE66 \\# 31 %.4x %.2x 14ef " + "( 0c747970652d7363616e6e6572076578616d706c65036e657400 )"; + + static const struct { + const char* dsync_type_str; + uint16_t dsync_type; + uint8_t dsync_scheme; + int32_t code; + } tests[] = { + // Schema 0: Reserved + { "CDS" , ZONE_TYPE_CDS , 0, ZONE_SUCCESS }, + { "TYPE59" , 59 /* CDS */ , 0, ZONE_SUCCESS }, + { "CSYNC" , ZONE_TYPE_CSYNC , 0, ZONE_SUCCESS }, + { "TYPE62" , 62 /* CSYNC */ , 0, ZONE_SUCCESS }, + { "TXT" , ZONE_TYPE_TXT , 0, ZONE_SUCCESS }, + { "TYPE16" , 16 /* TXT */ , 0, ZONE_SUCCESS }, + // Scheme 1: only CDS and CSYNC + { "CDS" , ZONE_TYPE_CDS , 1, ZONE_SUCCESS }, + { "TYPE59" , 59 /* CDS */ , 1, ZONE_SUCCESS }, + { "CSYNC" , ZONE_TYPE_CSYNC , 1, ZONE_SUCCESS }, + { "TYPE62" , 62 /* CSYNC */ , 1, ZONE_SUCCESS }, + { "TXT" , ZONE_TYPE_TXT , 1, ZONE_SEMANTIC_ERROR }, + { "TYPE16" , 16 /* TXT */ , 1, ZONE_SEMANTIC_ERROR }, + // Other schemes, anything goes + { "CDS" , ZONE_TYPE_CDS , 2, ZONE_SUCCESS }, + { "TYPE59" , 59 /* CDS */ , 2, ZONE_SUCCESS }, + { "CSYNC" , ZONE_TYPE_CSYNC , 2, ZONE_SUCCESS }, + { "TYPE62" , 62 /* CSYNC */ , 2, ZONE_SUCCESS }, + { "TXT" , ZONE_TYPE_TXT , 2, ZONE_SUCCESS }, + { "TYPE16" , 16 /* TXT */ , 2, ZONE_SUCCESS } + }; + + (void)state; + + int32_t code; + + for (size_t i=0, n = sizeof(tests)/sizeof(tests[0]); i < n; i++) { + char buf[512]; + const char *dsync_type_str = tests[i].dsync_type_str; + const uint16_t dsync_type = tests[i].dsync_type; + const uint8_t dsync_scheme = tests[i].dsync_scheme; + + snprintf(buf, sizeof(buf), fmt, dsync_type_str, (int)dsync_scheme); + code = parse_digest(buf); + assert_int_equal(code, tests[i].code); + + /* No need to htobe16(dsync_type), since %.4x is "written" big endian */ + snprintf(buf, sizeof(buf), hex_fmt, (int)dsync_type, (int)dsync_scheme); + code = parse_digest(buf); + assert_int_equal(code, tests[i].code); + } +} diff --git a/tests/types.c b/tests/types.c index e292cc5..1687b48 100644 --- a/tests/types.c +++ b/tests/types.c @@ -313,6 +313,29 @@ static const rdata_t nxt_rdata = RDATA(6, 'm', 'e', 'd', 'i', 'u', 'm', 3, 'f', 'o', 'o', 3, 't', 'l', 'd', 0, 0x40, 0x01, 0x00, 0x82); +static const char eid_text[] = + PAD("venera.invalid. EID 813F 4B7C DAB3 4217"); +static const rdata_t eid_rdata = + RDATA(0x81, 0x3f, 0x4b, 0x7c, 0xda, 0xb3, 0x42, 0x17); + +static const char nimloc_text[] = + PAD("venera.invalid. NIMLOC ( 3227 45\n" + " 0A 01 00 34 )"); +static const rdata_t nimloc_rdata = + RDATA(0x32, 0x27, 0x45, 0x0a, 0x01, 0x00, 0x34); + +static const char atma_text[] = + PAD("foo. ATMA 39.246f.00.0e7c9c.0312.0001.0001.000012345678.00"); +static const rdata_t atma_rdata = + RDATA(0x00, 0x39, 0x24, 0x6f, 0x00, 0x0e, 0x7c, 0x9c, + 0x03, 0x12, 0x00, 0x01, 0x00, 0x01, + 0x00, 0x00, 0x12, 0x34, 0x56, 0x78, 0x00); + +static const char atma2_text[] = + PAD("foo. ATMA +1.908.555.1212"); +static const rdata_t atma2_rdata = + RDATA(0x01, 0x31, 0x39, 0x30, 0x38, 0x35, 0x35, 0x35, 0x31, 0x32, 0x31, 0x32); + static const char naptr_text[] = PAD("foo. NAPTR 100 50 \"s\" \"http+I2L+I2C+I2R\" \"\" _http._tcp.gatech.edu."); static const char naptr_generic_text[] = @@ -364,6 +387,10 @@ static const char dname_generic_text[] = PAD("foo. DNAME \\# 18 04686f7374076578616d706c6503636f6d00"); static const rdata_t dname_rdata = RDATA(HOST_EXAMPLE_COM); +static const char sink_text[] = PAD("foo. SINK 64 1 TkxuZXRMYWJzLm5s"); +static const rdata_t sink_rdata = + RDATA(64, 1, 'N', 'L', 'n', 'e', 't', 'L', 'a', 'b', 's', '.', 'n', 'l'); + static const char apl_text[] = PAD("foo.example. IN APL 1:192.168.32.0/21 !1:192.168.38.0/28"); static const rdata_t apl_rdata = @@ -596,6 +623,12 @@ static const rdata_t hip_rdata = 4, 'r', 'v', 's', '2', 7, 'e', 'x', 'a', 'm', 'p', 'l', 'e', 3, 'c', 'o', 'm', 0, ); +static const char talink_text[] = + PAD("example.com. TALINK h0.example.com. h2.example.com."); +static const rdata_t talink_rdata = + RDATA(2, 'h', '0', 7, 'e', 'x', 'a', 'm', 'p', 'l', 'e', 3, 'c', 'o', 'm', 0, + 2, 'h', '2', 7, 'e', 'x', 'a', 'm', 'p', 'l', 'e', 3, 'c', 'o', 'm', 0); + static const char cds_text[] = PAD("foo. CDS 58470 5 1 ( 3079F1593EBAD6DC121E202A8B766A6A4837206C )"); static const char cds_generic_text[] = @@ -608,6 +641,14 @@ static const rdata_t cds_rdata = 0x12, 0x1e, 0x20, 0x2a, 0x8b, 0x76, 0x6a, 0x6a, 0x48, 0x37, 0x20, 0x6c); +// RFC 8078 Section 4: "Empty keying material is represented by a single 0" +static const char cds2_text[] = + PAD("foo. CDS 0 0 0 0"); +static const char cds2_generic_text[] = + PAD("foo. CDS \\# 4 00000000"); +static const rdata_t cds2_rdata = + RDATA(0, 0, 0, 0); + static const char cdnskey_text[] = PAD("foo. CDNSKEY 256 3 5 ( AQPSKmynfzW4kyBv015MUG2DeIQ3" " Cbl+BBZH4b/0PY1kxkmvHjcZc8no" @@ -662,6 +703,14 @@ static const rdata_t cdnskey_rdata = 0x8d, 0xf5, 0x29, 0xa6, 0x7d, 0x54, 0x68, 0xdb, 0xef, 0xe3); +// RFC 8078 Section 4: "Empty keying material is represented by a single 0" +static const char cdnskey2_text[] = + PAD("foo. CDNSKEY 0 3 0 0"); +static const char cdnskey2_generic_text[] = + PAD("foo. CDNSKEY \\# 4 00000300"); +static const rdata_t cdnskey2_rdata = + RDATA(0, 0, 3, 0); + // generated using https://www.huque.com/bin/openpgpkey with // input from https://www.ietf.org/archive/id/draft-bre-openpgp-samples-01.html static const char openpgpkey_text[] = @@ -790,6 +839,31 @@ static const rdata_t svcb_rdata = 3, 'f', 'o', 'o', 0, 0x00, 0x00, 0x00, 0x02, 0x00, 0x10, 0x00, 0x10, 0x00, 0x00); +static const char dsync_text[] = + PAD("foo. DSYNC CDS 1 5359 cds-scanner.example.net."); +static const char dsync_generic_text[] = + PAD("foo. DSYNC \\# 30 " + /* type */ + "003b" + /* scheme */ + "01" + /* port */ + "14ef" + /* target */ + "0b6364732d7363616e6e6572 076578616d706c65 036e6574 00"); +static const rdata_t dsync_rdata = + RDATA(/* type */ + 0x00, 0x3b, + /* scheme */ + 0x01, + /* port */ + 0x14, 0xef, + /* target */ + 11, 'c', 'd', 's', '-', 's', 'c', 'a', 'n', 'n', 'e', 'r', + 7, 'e', 'x', 'a', 'm', 'p', 'l', 'e', + 3, 'n', 'e', 't', + 0); + static const char spf_text[] = PAD("foo. SPF \"v=spf1 +all\""); static const char spf_generic_text[] = @@ -872,6 +946,96 @@ static const rdata_t avc_rdata = 'G', '|', 'a', 'p', 'p', '-', 'c', 'l', 'a', 's', 's', ':', 'O', 'A', 'M'); +static const char doa_text[] = + PAD("foo. DOA 0 1 2 \"\" bWFpbHRvOmxhYnNAbmxuZXRsYWJzLm5s"); +static const char doa_generic_text[] = + PAD("foo. DOA \\# 34 00000000 00000001 02 00 (\n" + " 6d61696c746f3a6c616273406e6c6e65746c6162732e6e6c )"); +static const rdata_t doa_rdata = + RDATA(/* enterprise */ + 0, 0, 0, 0, + /* type */ + 0, 0, 0, 1, + /* location */ + 2, + /* media type */ + 0, + /* data */ + 'm', 'a', 'i', 'l', 't', 'o', ':', + 'l', 'a', 'b', 's', '@', + 'n', 'l', 'n', 'e', 't', 'l', 'a', 'b', 's', '.', 'n', 'l' + ); + +static const char doa2_text[] = + PAD("foo. DOA 0 100000 200 example/nothing -"); +static const char doa2_generic_text[] = + PAD("foo. DOA \\# 25 00000000 000186a0 c8 0f6578616d706c652f6e6f7468696e67"); +static const rdata_t doa2_rdata = + RDATA(/* enterprise */ + 0, 0, 0, 0, + /* type */ + 0, 1, 134, 160, + /* location */ + 200, + /* media type */ + 15, 'e', 'x', 'a', 'm', 'p', 'l', 'e', '/', + 'n', 'o', 't', 'h', 'i', 'n', 'g' + /* data */ + ); + +static const char amtrelay_text[] = + PAD("foo. AMTRELAY 200 0 0"); +static const char amtrelay_generic_text[] = + PAD("foo. AMTRELAY \\# 2 c8 00"); +static const rdata_t amtrelay_rdata = + RDATA(200, 0); + +static const char amtrelay1_text[] = + PAD("foo. AMTRELAY 10 0 1 203.0.113.15"); +static const char amtrelay1_generic_text[] = + PAD("foo. AMTRELAY \\# 6 0a 01 cb00710f"); +static const rdata_t amtrelay1_rdata = + RDATA(10, 1, 203, 0, 113, 15); + +static const char amtrelay2_text[] = + PAD("foo. AMTRELAY 10 0 2 2001:db8::15"); +static const char amtrelay2_generic_text[] = + PAD("foo. AMTRELAY \\# 18 0a 02 20010db8000000000000000000000015"); +static const rdata_t amtrelay2_rdata = + RDATA(10, 2, 0x20, 0x01, 0x0d, 0xb8 + , 0x00, 0x00, 0x00, 0x00 + , 0x00, 0x00, 0x00, 0x00 + , 0x00, 0x00, 0x00, 0x15); + +static const char amtrelay3_text[] = + PAD("foo. AMTRELAY 128 1 3 amtrelays.example.com."); +static const char amtrelay3_generic_text[] = + PAD("foo. AMTRELAY \\# 25 80 83 09616d7472656c617973076578616d706c6503636f6d00"); +static const rdata_t amtrelay3_rdata = + RDATA( 128, 0x83 + , 9, 'a', 'm', 't', 'r', 'e', 'l', 'a', 'y', 's' + , 7, 'e', 'x', 'a', 'm', 'p', 'l', 'e' + , 3, 'c', 'o', 'm' + , 0); + +static const char ipn_text[] = + PAD("foo. IPN 100"); +static const rdata_t ipn_rdata = + RDATA( 0, 0, 0, 0 + , 0, 0, 0, 100); + +static const char ipn2_text[] = + PAD("foo. IPN 429496729700"); +static const rdata_t ipn2_rdata = + RDATA( 0, 0, 0, 100 + , 0, 0, 0, 100); + +static const char ipn3_text[] = + PAD("foo. IPN 100.100"); +static const rdata_t ipn3_rdata = + RDATA( 0, 0, 0, 100 + , 0, 0, 0, 100); + static const char dlv_text[] = PAD("foo. DLV 58470 5 1 ( 3079F1593EBAD6DC121E202A8B766A6A4837206C )"); static const char dlv_generic_text[] = @@ -943,6 +1107,10 @@ static const test_t tests[] = { { ZONE_TYPE_PX, px_generic_text, &px_rdata }, { ZONE_TYPE_LOC, loc_text, &loc_rdata }, { ZONE_TYPE_NXT, nxt_text, &nxt_rdata }, + { ZONE_TYPE_EID, eid_text, &eid_rdata }, + { ZONE_TYPE_NIMLOC, nimloc_text, &nimloc_rdata }, + { ZONE_TYPE_ATMA, atma_text, &atma_rdata }, + { ZONE_TYPE_ATMA, atma2_text, &atma2_rdata }, { ZONE_TYPE_NAPTR, naptr_text, &naptr_rdata }, { ZONE_TYPE_NAPTR, naptr_generic_text, &naptr_rdata }, { ZONE_TYPE_KX, kx_text, &kx_rdata }, @@ -950,6 +1118,7 @@ static const test_t tests[] = { { ZONE_TYPE_CERT, cert_text, &cert_rdata }, { ZONE_TYPE_DNAME, dname_text, &dname_rdata }, { ZONE_TYPE_DNAME, dname_generic_text, &dname_rdata }, + { ZONE_TYPE_SINK, sink_text, &sink_rdata }, { ZONE_TYPE_APL, apl_text, &apl_rdata }, { ZONE_TYPE_SSHFP, sshfp_text, &sshfp_rdata }, { ZONE_TYPE_SSHFP, sshfp_generic_text, &sshfp_rdata }, @@ -967,16 +1136,23 @@ static const test_t tests[] = { { ZONE_TYPE_SMIMEA, smimea_text, &smimea_rdata }, { ZONE_TYPE_SMIMEA, smimea_generic_text, &smimea_rdata }, { ZONE_TYPE_HIP, hip_text, &hip_rdata }, + { ZONE_TYPE_TALINK, talink_text, &talink_rdata }, { ZONE_TYPE_CDS, cds_text, &cds_rdata }, { ZONE_TYPE_CDS, cds_generic_text, &cds_rdata }, + { ZONE_TYPE_CDS, cds2_text, &cds2_rdata }, + { ZONE_TYPE_CDS, cds2_generic_text, &cds2_rdata }, { ZONE_TYPE_CDNSKEY, cdnskey_text, &cdnskey_rdata }, { ZONE_TYPE_CDNSKEY, cdnskey_generic_text, &cdnskey_rdata }, + { ZONE_TYPE_CDNSKEY, cdnskey2_text, &cdnskey2_rdata }, + { ZONE_TYPE_CDNSKEY, cdnskey2_generic_text, &cdnskey2_rdata }, { ZONE_TYPE_OPENPGPKEY, openpgpkey_text, &openpgpkey_rdata }, { ZONE_TYPE_OPENPGPKEY, openpgpkey_generic_text, &openpgpkey_rdata }, { ZONE_TYPE_CSYNC, csync_text, &csync_rdata }, { ZONE_TYPE_ZONEMD, zonemd_text, &zonemd_rdata }, { ZONE_TYPE_ZONEMD, zonemd_generic_text, &zonemd_rdata }, { ZONE_TYPE_SVCB, svcb_text, &svcb_rdata }, + { ZONE_TYPE_DSYNC, dsync_text, &dsync_rdata }, + { ZONE_TYPE_DSYNC, dsync_generic_text, &dsync_rdata }, { ZONE_TYPE_SPF, spf_text, &spf_rdata }, { ZONE_TYPE_SPF, spf_generic_text, &spf_rdata }, { ZONE_TYPE_NID, nid_text, &nid_rdata }, @@ -997,6 +1173,21 @@ static const test_t tests[] = { { ZONE_TYPE_CAA, caa_generic_text, &caa_rdata }, { ZONE_TYPE_AVC, avc_text, &avc_rdata }, { ZONE_TYPE_AVC, avc_generic_text, &avc_rdata }, + { ZONE_TYPE_DOA, doa_text, &doa_rdata }, + { ZONE_TYPE_DOA, doa_generic_text, &doa_rdata }, + { ZONE_TYPE_DOA, doa2_text, &doa2_rdata }, + { ZONE_TYPE_DOA, doa2_generic_text, &doa2_rdata }, + { ZONE_TYPE_AMTRELAY, amtrelay_text, &amtrelay_rdata }, + { ZONE_TYPE_AMTRELAY, amtrelay_generic_text, &amtrelay_rdata }, + { ZONE_TYPE_AMTRELAY, amtrelay1_text, &amtrelay1_rdata }, + { ZONE_TYPE_AMTRELAY, amtrelay1_generic_text, &amtrelay1_rdata }, + { ZONE_TYPE_AMTRELAY, amtrelay2_text, &amtrelay2_rdata }, + { ZONE_TYPE_AMTRELAY, amtrelay2_generic_text, &amtrelay2_rdata }, + { ZONE_TYPE_AMTRELAY, amtrelay3_text, &amtrelay3_rdata }, + { ZONE_TYPE_AMTRELAY, amtrelay3_generic_text, &amtrelay3_rdata }, + { ZONE_TYPE_IPN, ipn_text, &ipn_rdata }, + { ZONE_TYPE_IPN, ipn2_text, &ipn2_rdata }, + { ZONE_TYPE_IPN, ipn3_text, &ipn3_rdata }, { ZONE_TYPE_DLV, dlv_text, &cds_rdata }, { ZONE_TYPE_DLV, dlv_generic_text, &cds_rdata } };