From aaa5e2ba41e3721f184307c98c09c3e3b8b2a651 Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Thu, 30 Jan 2025 16:50:57 +0100 Subject: [PATCH] The DSYNC, CLA and IPN RR types --- configure.ac | 26 +++++++++++++++++++- host2str.c | 12 ++++++++++ ldns/host2str.h | 8 +++++++ ldns/rdata.h | 7 ++++-- ldns/rr.h | 9 ++++++- ldns/str2host.h | 10 ++++++++ ldns/util.h.in | 20 ++++++++++++++++ rdata.c | 3 +++ rr.c | 31 ++++++++++++++++++++++-- str2host.c | 63 +++++++++++++++++++++++++++++++++++++++++++++++++ wire2host.c | 2 ++ 11 files changed, 185 insertions(+), 6 deletions(-) diff --git a/configure.ac b/configure.ac index bed73df3..9180dae4 100644 --- a/configure.ac +++ b/configure.ac @@ -668,7 +668,9 @@ case "$enable_dane" in ;; esac +AC_ARG_ENABLE(draft-rrtypes, AS_HELP_STRING([--enable-draft-rrtypes],[Enable all draft RR types.])) AC_ARG_ENABLE(rrtype-ninfo, AS_HELP_STRING([--enable-rrtype-ninfo],[Enable draft RR type ninfo.])) +if test "x$enable_draft_rrtypes" = "xyes"; then enable_rrtype_ninfo="yes"; fi case "$enable_rrtype_ninfo" in yes) AC_DEFINE_UNQUOTED([RRTYPE_NINFO], [], [Define this to enable RR type NINFO.]) @@ -677,6 +679,7 @@ case "$enable_rrtype_ninfo" in ;; esac AC_ARG_ENABLE(rrtype-rkey, AS_HELP_STRING([--enable-rrtype-rkey],[Enable draft RR type rkey.])) +if test "x$enable_draft_rrtypes" = "xyes"; then enable_rrtype_rkey="yes"; fi case "$enable_rrtype_rkey" in yes) AC_DEFINE_UNQUOTED([RRTYPE_RKEY], [], [Define this to enable RR type RKEY.]) @@ -693,6 +696,7 @@ case "$enable_rrtype_openpgpkey" in ;; esac AC_ARG_ENABLE(rrtype-ta, AS_HELP_STRING([--enable-rrtype-ta],[Enable draft RR type ta.])) +if test "x$enable_draft_rrtypes" = "xyes"; then enable_rrtype_ta="yes"; fi case "$enable_rrtype_ta" in yes) AC_DEFINE_UNQUOTED([RRTYPE_TA], [], [Define this to enable RR type TA.]) @@ -701,6 +705,7 @@ case "$enable_rrtype_ta" in ;; esac AC_ARG_ENABLE(rrtype-avc, AS_HELP_STRING([--enable-rrtype-avc],[Enable draft RR type avc.])) +if test "x$enable_draft_rrtypes" = "xyes"; then enable_rrtype_avc="yes"; fi case "$enable_rrtype_avc" in yes) AC_DEFINE_UNQUOTED([RRTYPE_AVC], [], [Define this to enable RR type AVC.]) @@ -709,6 +714,7 @@ case "$enable_rrtype_avc" in ;; esac AC_ARG_ENABLE(rrtype-doa, AS_HELP_STRING([--enable-rrtype-doa],[Enable draft RR type DOA.])) +if test "x$enable_draft_rrtypes" = "xyes"; then enable_rrtype_doa="yes"; fi case "$enable_rrtype_doa" in yes) AC_DEFINE_UNQUOTED([RRTYPE_DOA], [], [Define this to enable RR type DOA.]) @@ -732,7 +738,7 @@ case "$enable_rrtype_svcb_https" in AC_DEFINE_UNQUOTED([RRTYPE_SVCB_HTTPS], [], [Define this to enable RR types SVCB and HTTPS.]) ;; esac -AC_ARG_ENABLE(rrtype-resinfo, AS_HELP_STRING([--enable-rrtype-resinfo],[Disable RR type RESINFO.])) +AC_ARG_ENABLE(rrtype-resinfo, AS_HELP_STRING([--disable-rrtype-resinfo],[Disable RR type RESINFO.])) case "$enable_rrtype_resinfo" in no) ;; @@ -740,6 +746,24 @@ case "$enable_rrtype_resinfo" in AC_DEFINE_UNQUOTED([RRTYPE_RESINFO], [], [Define this to enable RR type RESINFO.]) ;; esac +AC_ARG_ENABLE(rrtype-dsync, AS_HELP_STRING([--enable-rrtype-dsync],[Enable draft RR type DSYNC.])) +if test "x$enable_draft_rrtypes" = "xyes"; then enable_rrtype_dsync="yes"; fi +case "$enable_rrtype_dsync" in + yes) + AC_DEFINE_UNQUOTED([RRTYPE_DSYNC], [], [Define this to enable RR type DSYNC.]) + ;; + no|*) + ;; +esac +AC_ARG_ENABLE(rrtypes-cla-ipn, AS_HELP_STRING([--enable-rrtypes-cla-ipn],[Enable draft RR types CLA and IPN.])) +if test "x$enable_draft_rrtypes" = "xyes"; then enable_rrtypes_cla_ipn="yes"; fi +case "$enable_rrtypes_cla_ipn" in + yes) + AC_DEFINE_UNQUOTED([RRTYPE_CLA_IPN], [], [Define this to enable RR types CLA and IPN.]) + ;; + no|*) + ;; +esac if echo "$tmp_LIBS" | grep "ws2_32" >/dev/null; then diff --git a/host2str.c b/host2str.c index deeeaf63..8348fdb5 100644 --- a/host2str.c +++ b/host2str.c @@ -409,6 +409,14 @@ ldns_rdf2buffer_str_int32(ldns_buffer *output, const ldns_rdf *rdf) return ldns_buffer_status(output); } +ldns_status +ldns_rdf2buffer_str_int64(ldns_buffer *output, const ldns_rdf *rdf) +{ + uint64_t data = ldns_read_uint64(ldns_rdf_data(rdf)); + ldns_buffer_printf(output, "%llu", (unsigned long long) data); + return ldns_buffer_status(output); +} + ldns_status ldns_rdf2buffer_str_time(ldns_buffer *output, const ldns_rdf *rdf) { @@ -1644,6 +1652,10 @@ ldns_rdf2buffer_str_fmt(ldns_buffer *buffer, case LDNS_RDF_TYPE_INT32: res = ldns_rdf2buffer_str_int32(buffer, rdf); break; + case LDNS_RDF_TYPE_INT64: + case LDNS_RDF_TYPE_IPN: + res = ldns_rdf2buffer_str_int64(buffer, rdf); + break; case LDNS_RDF_TYPE_PERIOD: res = ldns_rdf2buffer_str_period(buffer, rdf); break; diff --git a/ldns/host2str.h b/ldns/host2str.h index 79f5561a..23aa8bcf 100644 --- a/ldns/host2str.h +++ b/ldns/host2str.h @@ -581,6 +581,14 @@ ldns_status ldns_rdf2buffer_str_int16(ldns_buffer *output, const ldns_rdf *rdf); */ ldns_status ldns_rdf2buffer_str_int32(ldns_buffer *output, const ldns_rdf *rdf); +/** + * Converts an LDNS_RDF_TYPE_INT64 rdata element to presentation format. + * \param[in] *rdf The rdata to convert + * \param[in] *output The buffer to add the data to + * \return LDNS_STATUS_OK on success, and error status on failure + */ +ldns_status ldns_rdf2buffer_str_int64(ldns_buffer *output, const ldns_rdf *rdf); + /** * Converts an LDNS_RDF_TYPE_TIME rdata element to string format and adds it to the output buffer * \param[in] *rdf The rdata to convert diff --git a/ldns/rdata.h b/ldns/rdata.h index 1e2fd397..617ba0ec 100644 --- a/ldns/rdata.h +++ b/ldns/rdata.h @@ -54,6 +54,8 @@ enum ldns_enum_rdf_type LDNS_RDF_TYPE_INT16, /** 32 bits */ LDNS_RDF_TYPE_INT32, + /** 64 bits */ + LDNS_RDF_TYPE_INT64, /** A record */ LDNS_RDF_TYPE_A, /** AAAA record */ @@ -70,6 +72,7 @@ enum ldns_enum_rdf_type LDNS_RDF_TYPE_HEX, /** nsec type codes */ LDNS_RDF_TYPE_NSEC, + LDNS_RDF_TYPE_BITMAP = LDNS_RDF_TYPE_NSEC, /** a RR type */ LDNS_RDF_TYPE_TYPE, /** a class */ @@ -145,8 +148,8 @@ enum ldns_enum_rdf_type /** draft-ietf-dnsop-svcb-https **/ LDNS_RDF_TYPE_SVCPARAMS, - /* Aliases */ - LDNS_RDF_TYPE_BITMAP = LDNS_RDF_TYPE_NSEC + /** draft-johnson-dns-ipn-cla-07 **/ + LDNS_RDF_TYPE_IPN }; typedef enum ldns_enum_rdf_type ldns_rdf_type; diff --git a/ldns/rr.h b/ldns/rr.h index 314f1597..984bfa34 100644 --- a/ldns/rr.h +++ b/ldns/rr.h @@ -194,6 +194,7 @@ enum ldns_enum_rr_type LDNS_RR_TYPE_ZONEMD = 63, /* RFC 8976 */ LDNS_RR_TYPE_SVCB = 64, /* RFC 9460 */ LDNS_RR_TYPE_HTTPS = 65, /* RFC 9460 */ + LDNS_RR_TYPE_DSYNC = 66, /* draft-ietf-dnsop-generalized-notify */ LDNS_RR_TYPE_SPF = 99, /* RFC 4408 */ @@ -236,6 +237,12 @@ enum ldns_enum_rr_type /** https://iana.org/assignments/dns-parameters/WALLET/wallet-completed-template */ LDNS_RR_TYPE_WALLET = 262, + /** https://www.iana.org/assignments/dns-parameters/CLA/cla-completed-template */ + LDNS_RR_TYPE_CLA = 263, + + /** https://www.iana.org/assignments/dns-parameters/IPN/ipn-completed-template */ + LDNS_RR_TYPE_IPN = 264, + /** DNSSEC Trust Authorities */ LDNS_RR_TYPE_TA = 32768, /* RFC 4431, 5074, DNSSEC Lookaside Validation */ @@ -251,7 +258,7 @@ enum ldns_enum_rr_type typedef enum ldns_enum_rr_type ldns_rr_type; /* The first fields are contiguous and can be referenced instantly */ -#define LDNS_RDATA_FIELD_DESCRIPTORS_COMMON (LDNS_RR_TYPE_WALLET + 1) +#define LDNS_RDATA_FIELD_DESCRIPTORS_COMMON (LDNS_RR_TYPE_IPN + 1) /** * Resource Record diff --git a/ldns/str2host.h b/ldns/str2host.h index 2892db0b..18bd7f6d 100644 --- a/ldns/str2host.h +++ b/ldns/str2host.h @@ -331,6 +331,16 @@ ldns_status ldns_str2rdf_amtrelay(ldns_rdf **rd, const char *str); */ ldns_status ldns_str2rdf_svcparams(ldns_rdf **rd, const char *str); +/** + * Convert either two unsigned 32 bit decimal numbers seperated by a '.', + * or a single unsigned 64 bit decimal number, as described in + * [draft-johnson-dns-ipn-cla-07]. + * \param[out] rd the rdf where to put the data + * \param[in] str the string to be converted + * \return ldns_status + */ +ldns_status ldns_str2rdf_ipn(ldns_rdf **rd, const char *str); + #ifdef __cplusplus } diff --git a/ldns/util.h.in b/ldns/util.h.in index 7115a2b7..c2c9aee4 100644 --- a/ldns/util.h.in +++ b/ldns/util.h.in @@ -91,6 +91,26 @@ ldns_read_uint32(const void *src) #endif } +INLINE uint64_t +ldns_read_uint64(const void *src) +{ +#ifdef ALLOW_UNALIGNED_ACCESSES + const uint32_t *p = (const uint32_t *) src; + return ( ((uint64_t) ntohl(src[0]) << 32) + | (uint64_t) ntohl(src[1])); +#else + const uint8_t *p = (const uint8_t *) src; + return ( ((uint64_t) p[0] << 56) + | ((uint64_t) p[1] << 48) + | ((uint64_t) p[2] << 40) + | ((uint64_t) p[3] << 32) + | ((uint64_t) p[4] << 24) + | ((uint64_t) p[5] << 16) + | ((uint64_t) p[6] << 8) + | (uint64_t) p[7]); +#endif +} + /* * Copy data allowing for unaligned accesses in network byte order * (big endian). diff --git a/rdata.c b/rdata.c index 3f899a21..f2d390d8 100644 --- a/rdata.c +++ b/rdata.c @@ -366,6 +366,9 @@ ldns_rdf_new_frm_str(ldns_rdf_type type, const char *str) case LDNS_RDF_TYPE_SVCPARAMS: status = ldns_str2rdf_svcparams(&rdf, str); break; + case LDNS_RDF_TYPE_IPN: + status = ldns_str2rdf_ipn(&rdf, str); + break; case LDNS_RDF_TYPE_NONE: default: /* default default ??? */ diff --git a/rr.c b/rr.c index 4be63b9e..6374aaf9 100644 --- a/rr.c +++ b/rr.c @@ -1990,6 +1990,15 @@ static const ldns_rdf_type type_svcb_wireformat[] = { LDNS_RDF_TYPE_SVCPARAMS }; #endif +#ifdef RRTYPE_DSYNC +static const ldns_rdf_type type_dsync_wireformat[] = { + LDNS_RDF_TYPE_TYPE, + LDNS_RDF_TYPE_INT8, + LDNS_RDF_TYPE_INT16, + LDNS_RDF_TYPE_DNAME +}; +#endif + /* nsec3 is some vars, followed by same type of data of nsec */ static const ldns_rdf_type type_nsec3_wireformat[] = { /* LDNS_RDF_TYPE_NSEC3_VARS, LDNS_RDF_TYPE_NSEC3_NEXT_OWNER, LDNS_RDF_TYPE_NSEC*/ @@ -2083,6 +2092,12 @@ static const ldns_rdf_type type_amtrelay_wireformat[] = { LDNS_RDF_TYPE_AMTRELAY }; #endif +#ifdef RRTYPE_CLA_IPN +static const ldns_rdf_type type_ipn_wireformat[] = { + LDNS_RDF_TYPE_IPN +}; +#endif + /** \endcond */ @@ -2250,7 +2265,11 @@ static ldns_rr_descriptor rdata_field_descriptors[] = { {LDNS_RR_TYPE_NULL, "TYPE64", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, {LDNS_RR_TYPE_NULL, "TYPE65", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, #endif +#ifdef RRTYPE_DSYNC +{LDNS_RR_TYPE_DSYNC, "DSYNC", 4, 4, type_dsync_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +#else {LDNS_RR_TYPE_NULL, "TYPE66", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +#endif {LDNS_RR_TYPE_NULL, "TYPE67", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, {LDNS_RR_TYPE_NULL, "TYPE68", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, {LDNS_RR_TYPE_NULL, "TYPE69", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, @@ -2501,8 +2520,16 @@ static ldns_rr_descriptor rdata_field_descriptors[] = { {LDNS_RR_TYPE_NULL, "TYPE261", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, #endif /* 262 */ - {LDNS_RR_TYPE_WALLET, "TXT", 1, 0, NULL, LDNS_RDF_TYPE_STR, LDNS_RR_NO_COMPRESS, 0 }, - + {LDNS_RR_TYPE_WALLET, "WALLET", 1, 0, NULL, LDNS_RDF_TYPE_STR, LDNS_RR_NO_COMPRESS, 0 }, +#ifdef RRTYPE_CLA_IPN + /* 263 */ + {LDNS_RR_TYPE_CLA, "CLA", 1, 0, NULL, LDNS_RDF_TYPE_STR, LDNS_RR_NO_COMPRESS, 0 }, + /* 264 */ + {LDNS_RR_TYPE_IPN, "IPN", 1, 1, type_ipn_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +#else +{LDNS_RR_TYPE_NULL, "TYPE263", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE264", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +#endif /* split in array, no longer contiguous */ #ifdef RRTYPE_TA diff --git a/str2host.c b/str2host.c index 5b78e5bc..5095232d 100644 --- a/str2host.c +++ b/str2host.c @@ -224,6 +224,69 @@ ldns_str2rdf_int32(ldns_rdf **rd, const char *longstr) } } +#ifdef __BYTE_ORDER__ +# if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ +# define htonll(x) (x) +# define ntohll(x) (x) +# else +# define htonll(x) (((uint64_t)htonl((x) & 0xFFFFFFFF) << 32) | htonl((x) >> 32)) +# define ntohll(x) (((uint64_t)ntohl((x) & 0xFFFFFFFF) << 32) | ntohl((x) >> 32)) +# endif +#else +# define htonll(x) ((1==htonl(1)) ? (x) : ((uint64_t)htonl((x) & 0xFFFFFFFF) << 32) | htonl((x) >> 32)) +# define ntohll(x) ((1==ntohl(1)) ? (x) : ((uint64_t)ntohl((x) & 0xFFFFFFFF) << 32) | ntohl((x) >> 32)) +#endif + +ldns_status +ldns_str2rdf_ipn(ldns_rdf **rd, const char *ipnstr) +{ + char *end; + uint8_t r[sizeof(uint64_t)]; + char left[21], *right; + + if(strlen(ipnstr) > 21) + return LDNS_STATUS_SYNTAX_INTEGER_OVERFLOW; + errno = 0; /* must set to zero before call, + note race condition on errno */ + if((right = strchr(ipnstr, '.'))) { + uint32_t u32 = strtoul(right + 1, &end, 10); + + if(*end != 0) + return LDNS_STATUS_ERR; + + if(errno == ERANGE) + return LDNS_STATUS_SYNTAX_INTEGER_OVERFLOW; + + u32 = htonl(u32); + memcpy(r + sizeof(uint32_t), &u32, sizeof(uint32_t)); + memcpy(left, ipnstr, right - ipnstr); + left[right - ipnstr] = 0; + + u32 = strtoul(left, &end, 10); + if(*end != 0) + return LDNS_STATUS_ERR; + + if(errno == ERANGE) + return LDNS_STATUS_SYNTAX_INTEGER_OVERFLOW; + + u32 = htonl(u32); + memcpy(r, &u32, sizeof(uint32_t)); + } else { + uint64_t u64 = strtoull(ipnstr, &end, 10); + + if(*end != 0) + return LDNS_STATUS_ERR; + + if(u64 == ULLONG_MAX && errno == ERANGE) + return LDNS_STATUS_SYNTAX_INTEGER_OVERFLOW; + + u64 = htonll(u64); + memcpy(r, &u64, sizeof(uint64_t)); + } + *rd = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_IPN, sizeof(r), r); + return *rd ? LDNS_STATUS_OK : LDNS_STATUS_MEM_ERR; +} + ldns_status ldns_str2rdf_int8(ldns_rdf **rd, const char *bytestr) { diff --git a/wire2host.c b/wire2host.c index 91d3f136..94743864 100644 --- a/wire2host.c +++ b/wire2host.c @@ -223,6 +223,8 @@ ldns_wire2rdf(ldns_rr *rr, const uint8_t *wire, size_t max, size_t *pos) break; case LDNS_RDF_TYPE_ILNP64: case LDNS_RDF_TYPE_EUI64: + case LDNS_RDF_TYPE_IPN: + case LDNS_RDF_TYPE_INT64: cur_rdf_length = LDNS_RDF_SIZE_8BYTES; break; case LDNS_RDF_TYPE_AAAA: -- 2.47.3