From 6e1311c624d15e6c4d0184deea3bb670e8a5785d Mon Sep 17 00:00:00 2001 From: Mark Andrews Date: Sat, 26 Jul 2025 06:17:20 +0200 Subject: [PATCH 1/3] Add support for parsing DSYNC scheme mnemonics Adds dns_dsyncscheme_fromtext, dns_dsyncscheme_totext and dns_dsyncscheme_format. Adds type dns_dsyncscheme_t. --- lib/dns/include/dns/dsync.h | 27 +++++++++++++++++++++++++ lib/dns/include/dns/types.h | 1 + lib/dns/rcode.c | 39 +++++++++++++++++++++++++++++++++++++ 3 files changed, 67 insertions(+) create mode 100644 lib/dns/include/dns/dsync.h diff --git a/lib/dns/include/dns/dsync.h b/lib/dns/include/dns/dsync.h new file mode 100644 index 0000000000..9533d4c2e5 --- /dev/null +++ b/lib/dns/include/dns/dsync.h @@ -0,0 +1,27 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, you can obtain one at https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#pragma once + +#define DNS_DSYNCSCHEME_NOTIFY (1) + +#define DNS_DSYNCSCHEMEFORMAT_SIZE (7) + +isc_result_t +dns_dsyncscheme_fromtext(dns_dsyncscheme_t *schemep, isc_textregion_t *source); + +isc_result_t +dns_dsyncscheme_totext(dns_dsyncscheme_t scheme, isc_buffer_t *target); + +void +dns_dsyncscheme_format(dns_dsyncscheme_t scheme, char *cp, unsigned int size); diff --git a/lib/dns/include/dns/types.h b/lib/dns/include/dns/types.h index 7985496351..73d8c40890 100644 --- a/lib/dns/include/dns/types.h +++ b/lib/dns/include/dns/types.h @@ -81,6 +81,7 @@ typedef ISC_LIST(dns_dns64_t) dns_dns64list_t; typedef struct dns_dnsseckey dns_dnsseckey_t; typedef ISC_LIST(dns_dnsseckey_t) dns_dnsseckeylist_t; typedef uint8_t dns_dsdigest_t; +typedef uint8_t dns_dsyncscheme_t; typedef struct dns_dtdata dns_dtdata_t; typedef struct dns_dtenv dns_dtenv_t; typedef struct dns_dtmsg dns_dtmsg_t; diff --git a/lib/dns/rcode.c b/lib/dns/rcode.c index 133f49a99e..c749959a49 100644 --- a/lib/dns/rcode.c +++ b/lib/dns/rcode.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -166,6 +167,8 @@ { DNS_DSDIGEST_GOST2012, "GOST2012", 0 }, \ DSDIGESTPRIVATENAMES SENTINEL +#define DSYNCSCHEMES { DNS_DSYNCSCHEME_NOTIFY, "NOTIFY", 0 }, SENTINEL + struct tbl { unsigned int value; const char *name; @@ -179,6 +182,7 @@ static struct tbl secalgs[] = { SECALGNAMES }; static struct tbl secprotos[] = { SECPROTONAMES }; static struct tbl hashalgs[] = { HASHALGNAMES }; static struct tbl dsdigests[] = { DSDIGESTNAMES }; +static struct tbl dsyncschemes[] = { DSYNCSCHEMES }; static struct tbl privatednss[] = { PRIVATEDNSS SENTINEL }; static struct tbl privateoids[] = { PRIVATEOIDS SENTINEL }; static struct tbl dstalgorithms[] = { PRIVATEDNSS PRIVATEOIDS SECALGNAMES }; @@ -547,6 +551,41 @@ dns_dsdigest_format(dns_dsdigest_t typ, char *cp, unsigned int size) { } } +/* + * DSYNC Scheme + */ + +isc_result_t +dns_dsyncscheme_fromtext(dns_dsyncscheme_t *schemep, isc_textregion_t *source) { + unsigned int value; + + REQUIRE(schemep != NULL); + RETERR(dns_mnemonic_fromtext(&value, source, dsyncschemes, 0xff)); + *schemep = value; + return ISC_R_SUCCESS; +} + +isc_result_t +dns_dsyncscheme_totext(dns_dsyncscheme_t scheme, isc_buffer_t *target) { + return dns_mnemonic_totext(scheme, target, dsyncschemes); +} + +void +dns_dsyncscheme_format(dns_dsyncscheme_t scheme, char *cp, unsigned int size) { + isc_buffer_t b; + isc_region_t r; + isc_result_t result; + + REQUIRE(cp != NULL && size > 0); + isc_buffer_init(&b, cp, size - 1); + result = dns_dsyncscheme_totext(scheme, &b); + isc_buffer_usedregion(&b, &r); + r.base[r.length] = 0; + if (result != ISC_R_SUCCESS) { + r.base[0] = 0; + } +} + /* * This uses lots of hard coded values, but how often do we actually * add classes? From c47615094e0b945cae14a81acc38baed21c6cee6 Mon Sep 17 00:00:00 2001 From: Mark Andrews Date: Sat, 26 Jul 2025 06:21:34 +0200 Subject: [PATCH 2/3] Add support for parsing and displaying DSYNC rdata type --- bin/tests/system/rrchecker/tests_rrchecker.py | 1 + lib/dns/rdata/generic/dsync_66.c | 361 ++++++++++++++++++ lib/dns/rdata/generic/dsync_66.h | 24 ++ 3 files changed, 386 insertions(+) create mode 100644 lib/dns/rdata/generic/dsync_66.c create mode 100644 lib/dns/rdata/generic/dsync_66.h diff --git a/bin/tests/system/rrchecker/tests_rrchecker.py b/bin/tests/system/rrchecker/tests_rrchecker.py index 367450319a..f31e65a2ff 100644 --- a/bin/tests/system/rrchecker/tests_rrchecker.py +++ b/bin/tests/system/rrchecker/tests_rrchecker.py @@ -49,6 +49,7 @@ pytestmark = pytest.mark.extra_artifacts( "DNSKEY", "DOA", "DS", + "DSYNC", "EID", "EUI48", "EUI64", diff --git a/lib/dns/rdata/generic/dsync_66.c b/lib/dns/rdata/generic/dsync_66.c new file mode 100644 index 0000000000..ad2f9cb021 --- /dev/null +++ b/lib/dns/rdata/generic/dsync_66.c @@ -0,0 +1,361 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, you can obtain one at https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#ifndef RDATA_GENERIC_DSYNC_66_C +#define RDATA_GENERIC_DSYNC_66_C + +#include + +#include + +#include +#include + +#define RRTYPE_DSYNC_ATTRIBUTES (0) + +static isc_result_t +fromtext_dsync(ARGS_FROMTEXT) { + isc_token_t token; + isc_result_t result; + dns_fixedname_t fn; + dns_name_t *name = dns_fixedname_initname(&fn); + isc_buffer_t buffer; + dns_rdatatype_t rrtype; + dns_dsyncscheme_t scheme; + bool ok = true; + + REQUIRE(type == dns_rdatatype_dsync); + + UNUSED(type); + UNUSED(rdclass); + UNUSED(callbacks); + + /* + * RRtype + */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, + false)); + result = dns_rdatatype_fromtext(&rrtype, &token.value.as_textregion); + if (result != ISC_R_SUCCESS && result != ISC_R_NOTIMPLEMENTED) { + char *e = NULL; + long i = strtol(DNS_AS_STR(token), &e, 10); + if (i < 0 || i > 65535) { + RETTOK(ISC_R_RANGE); + } + if (*e != 0) { + RETTOK(result); + } + rrtype = (dns_rdatatype_t)i; + } + RETERR(uint16_tobuffer(rrtype, target)); + + /* + * Scheme + */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, + false)); + RETERR(dns_dsyncscheme_fromtext(&scheme, &token.value.as_textregion)); + RETERR(uint8_tobuffer(scheme, target)); + + /* + * Port + */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number, + false)); + if (token.value.as_ulong > 0xffffU) { + RETTOK(ISC_R_RANGE); + } + RETERR(uint16_tobuffer(token.value.as_ulong, target)); + + /* + * Target + */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, + false)); + + buffer_fromregion(&buffer, &token.value.as_region); + if (origin == NULL) { + origin = dns_rootname; + } + RETTOK(dns_name_fromtext(name, &buffer, origin, options)); + RETTOK(dns_name_towire(name, NULL, target)); + if ((options & DNS_RDATA_CHECKNAMES) != 0) { + ok = dns_name_ishostname(name, false); + } + if (!ok && (options & DNS_RDATA_CHECKNAMESFAIL) != 0) { + RETTOK(DNS_R_BADNAME); + } + if (!ok && callbacks != NULL) { + warn_badname(name, lexer, callbacks); + } + return ISC_R_SUCCESS; +} + +static isc_result_t +totext_dsync(ARGS_TOTEXT) { + isc_region_t region; + dns_name_t name; + dns_name_t prefix; + unsigned int opts; + char buf[sizeof("TYPE64000")]; + unsigned short num; + dns_rdatatype_t type; + dns_dsyncscheme_t scheme; + + REQUIRE(rdata->type == dns_rdatatype_dsync); + REQUIRE(rdata->length != 0); + + dns_name_init(&name); + dns_name_init(&prefix); + + dns_rdata_toregion(rdata, ®ion); + + /* + * Type. + */ + type = uint16_fromregion(®ion); + isc_region_consume(®ion, 2); + /* + * XXXAG We should have something like dns_rdatatype_isknown() + * that does the right thing with type 0. + */ + if (dns_rdatatype_isknown(type) && type != 0) { + RETERR(dns_rdatatype_totext(type, target)); + } else { + snprintf(buf, sizeof(buf), "TYPE%u", type); + RETERR(str_totext(buf, target)); + } + RETERR(str_totext(" ", target)); + + /* + * Scheme. + */ + scheme = uint8_fromregion(®ion); + isc_region_consume(®ion, 1); + RETERR(dns_dsyncscheme_totext(scheme, target)); + + RETERR(str_totext(" ", target)); + + /* + * Port + */ + num = uint16_fromregion(®ion); + isc_region_consume(®ion, 2); + snprintf(buf, sizeof(buf), "%u", num); + RETERR(str_totext(buf, target)); + + RETERR(str_totext(" ", target)); + + /* + * Target + */ + dns_name_fromregion(&name, ®ion); + opts = name_prefix(&name, tctx->origin, &prefix) ? DNS_NAME_OMITFINALDOT + : 0; + return dns_name_totext(&prefix, opts, target); +} + +static isc_result_t +fromwire_dsync(ARGS_FROMWIRE) { + dns_name_t name; + isc_region_t sregion; + + REQUIRE(type == dns_rdatatype_dsync); + + UNUSED(type); + UNUSED(rdclass); + + dctx = dns_decompress_setpermitted(dctx, false); + + dns_name_init(&name); + + isc_buffer_activeregion(source, &sregion); + if (sregion.length < 5) { + return ISC_R_UNEXPECTEDEND; + } + RETERR(mem_tobuffer(target, sregion.base, 5)); + isc_buffer_forward(source, 5); + return dns_name_fromwire(&name, source, dctx, target); +} + +static isc_result_t +towire_dsync(ARGS_TOWIRE) { + dns_name_t name; + isc_region_t region; + + REQUIRE(rdata->type == dns_rdatatype_dsync); + REQUIRE(rdata->length != 0); + + dns_compress_setpermitted(cctx, false); + + dns_rdata_toregion(rdata, ®ion); + RETERR(mem_tobuffer(target, region.base, 5)); + isc_region_consume(®ion, 5); + + dns_name_init(&name); + dns_name_fromregion(&name, ®ion); + + return dns_name_towire(&name, cctx, target); +} + +static int +compare_dsync(ARGS_COMPARE) { + isc_region_t region1; + isc_region_t region2; + + REQUIRE(rdata1->type == rdata2->type); + REQUIRE(rdata1->rdclass == rdata2->rdclass); + REQUIRE(rdata1->type == dns_rdatatype_dsync); + REQUIRE(rdata1->length != 0); + REQUIRE(rdata2->length != 0); + + dns_rdata_toregion(rdata1, ®ion1); + dns_rdata_toregion(rdata2, ®ion2); + return isc_region_compare(®ion1, ®ion2); +} + +static isc_result_t +fromstruct_dsync(ARGS_FROMSTRUCT) { + dns_rdata_dsync_t *dsync = source; + isc_region_t region; + + REQUIRE(type == dns_rdatatype_dsync); + REQUIRE(dsync != NULL); + REQUIRE(dsync->common.rdtype == type); + REQUIRE(dsync->common.rdclass == rdclass); + + UNUSED(type); + UNUSED(rdclass); + + RETERR(uint16_tobuffer(dsync->type, target)); + RETERR(uint16_tobuffer(dsync->scheme, target)); + RETERR(uint16_tobuffer(dsync->port, target)); + dns_name_toregion(&dsync->target, ®ion); + return isc_buffer_copyregion(target, ®ion); +} + +static isc_result_t +tostruct_dsync(ARGS_TOSTRUCT) { + isc_region_t region; + dns_rdata_dsync_t *dsync = target; + dns_name_t name; + + REQUIRE(rdata->type == dns_rdatatype_dsync); + REQUIRE(dsync != NULL); + REQUIRE(rdata->length != 0); + + dsync->common.rdclass = rdata->rdclass; + dsync->common.rdtype = rdata->type; + + dns_name_init(&name); + dns_rdata_toregion(rdata, ®ion); + dsync->type = uint16_fromregion(®ion); + isc_region_consume(®ion, 2); + dsync->scheme = uint8_fromregion(®ion); + isc_region_consume(®ion, 1); + dsync->port = uint16_fromregion(®ion); + isc_region_consume(®ion, 2); + dns_name_fromregion(&name, ®ion); + dns_name_init(&dsync->target); + name_duporclone(&name, mctx, &dsync->target); + dsync->mctx = mctx; + return ISC_R_SUCCESS; +} + +static void +freestruct_dsync(ARGS_FREESTRUCT) { + dns_rdata_dsync_t *dsync = source; + + REQUIRE(dsync != NULL); + REQUIRE(dsync->common.rdtype == dns_rdatatype_dsync); + + if (dsync->mctx == NULL) { + return; + } + + dns_name_free(&dsync->target, dsync->mctx); + dsync->mctx = NULL; +} + +static isc_result_t +additionaldata_dsync(ARGS_ADDLDATA) { + dns_name_t name; + isc_region_t region; + + REQUIRE(rdata->type == dns_rdatatype_dsync); + + UNUSED(owner); + + dns_name_init(&name); + dns_rdata_toregion(rdata, ®ion); + isc_region_consume(®ion, 5); + dns_name_fromregion(&name, ®ion); + + if (dns_name_equal(&name, dns_rootname)) { + return ISC_R_SUCCESS; + } + + return (add)(arg, &name, dns_rdatatype_a, NULL DNS__DB_FILELINE); +} + +static isc_result_t +digest_dsync(ARGS_DIGEST) { + isc_region_t r1; + + REQUIRE(rdata->type == dns_rdatatype_dsync); + + dns_rdata_toregion(rdata, &r1); + return (digest)(arg, &r1); +} + +static bool +checkowner_dsync(ARGS_CHECKOWNER) { + REQUIRE(type == dns_rdatatype_dsync); + + UNUSED(name); + UNUSED(rdclass); + UNUSED(type); + UNUSED(wildcard); + + return true; +} + +static bool +checknames_dsync(ARGS_CHECKNAMES) { + isc_region_t region; + dns_name_t name; + + REQUIRE(rdata->type == dns_rdatatype_dsync); + REQUIRE(rdata->length > 5); + + UNUSED(owner); + + dns_rdata_toregion(rdata, ®ion); + isc_region_consume(®ion, 5); + dns_name_init(&name); + dns_name_fromregion(&name, ®ion); + if (!dns_name_ishostname(&name, false)) { + if (bad != NULL) { + dns_name_clone(&name, bad); + } + return false; + } + return true; +} + +static int +casecompare_dsync(ARGS_COMPARE) { + return compare_dsync(rdata1, rdata2); +} + +#endif /* RDATA_GENERIC_DSYNC_66_C */ diff --git a/lib/dns/rdata/generic/dsync_66.h b/lib/dns/rdata/generic/dsync_66.h new file mode 100644 index 0000000000..4ec9eec2ab --- /dev/null +++ b/lib/dns/rdata/generic/dsync_66.h @@ -0,0 +1,24 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, you can obtain one at https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* */ +#pragma once + +typedef struct dns_rdata_dsync { + dns_rdatacommon_t common; + isc_mem_t *mctx; + uint16_t type; + uint8_t scheme; + uint16_t port; + dns_name_t target; +} dns_rdata_dsync_t; From 53c8c5233ae9f7b04837e40e1517b1f0924658e3 Mon Sep 17 00:00:00 2001 From: Mark Andrews Date: Sat, 26 Jul 2025 12:27:33 +0200 Subject: [PATCH 3/3] Add tests for DSYNC --- bin/tests/system/doth/example.axfr.good | 1 + bin/tests/system/doth/example8.axfr.good | 1 + bin/tests/system/genzone.sh | 5 +- bin/tests/system/xfer/dig1.good | 1 + bin/tests/system/xfer/dig2.good | 1 + tests/dns/rdata_test.c | 107 +++++++++++++++++++++++ 6 files changed, 115 insertions(+), 1 deletion(-) diff --git a/bin/tests/system/doth/example.axfr.good b/bin/tests/system/doth/example.axfr.good index a5ec1f2570..4561d59b1e 100644 --- a/bin/tests/system/doth/example.axfr.good +++ b/bin/tests/system/doth/example.axfr.good @@ -2548,6 +2548,7 @@ ds01.example. 3600 IN NS ns42.example. ds01.example. 3600 IN DS 12892 5 2 26584835CA80C81C91999F31CFAF2A0E89D4FF1C8FAFD0DDB31A85C7 19277C13 ds02.example. 3600 IN NS ns43.example. ds02.example. 3600 IN DS 12892 5 1 7AA4A3F416C2F2391FB7AB0D434F762CD62D1390 +dsync01.example. 3600 IN DSYNC CDS NOTIFY 53 . eid01.example. 3600 IN EID 1289AB eui48.example. 3600 IN EUI48 01-23-45-67-89-ab eui64.example. 3600 IN EUI64 01-23-45-67-89-ab-cd-ef diff --git a/bin/tests/system/doth/example8.axfr.good b/bin/tests/system/doth/example8.axfr.good index 39d70e2021..3e20efe43d 100644 --- a/bin/tests/system/doth/example8.axfr.good +++ b/bin/tests/system/doth/example8.axfr.good @@ -2548,6 +2548,7 @@ ds01.example8. 3600 IN DS 12892 5 2 26584835CA80C81C91999F31CFAF2A0E89D4FF1C8FA ds01.example8. 3600 IN NS ns42.example8. ds02.example8. 3600 IN DS 12892 5 1 7AA4A3F416C2F2391FB7AB0D434F762CD62D1390 ds02.example8. 3600 IN NS ns43.example8. +dsync01.example8. 3600 IN DSYNC CDS NOTIFY 53 . eid01.example8. 3600 IN EID 1289AB eui48.example8. 3600 IN EUI48 01-23-45-67-89-ab eui64.example8. 3600 IN EUI64 01-23-45-67-89-ab-cd-ef diff --git a/bin/tests/system/genzone.sh b/bin/tests/system/genzone.sh index 892209230b..4920bc5c91 100644 --- a/bin/tests/system/genzone.sh +++ b/bin/tests/system/genzone.sh @@ -389,7 +389,10 @@ svcb1 SVCB 1 . port=60 https0 HTTPS 0 example.net. https1 HTTPS 1 . port=60 -; type 66 -- 98 (unassigned) +; type 66 +dsync01 DSYNC CDS NOTIFY 53 . + +; type 68 -- 98 (unassigned) ; type 99 spf01 SPF "v=spf1 -all" diff --git a/bin/tests/system/xfer/dig1.good b/bin/tests/system/xfer/dig1.good index d44fcda9d2..4cad0c9f02 100644 --- a/bin/tests/system/xfer/dig1.good +++ b/bin/tests/system/xfer/dig1.good @@ -49,6 +49,7 @@ ds01.example. 3600 IN DS 12892 5 2 26584835CA80C81C91999F31CFAF2A0E89D4FF1C8FAF ds01.example. 3600 IN NS ns42.example. ds02.example. 3600 IN DS 12892 5 1 7AA4A3F416C2F2391FB7AB0D434F762CD62D1390 ds02.example. 3600 IN NS ns43.example. +dsync01.example. 3600 IN DSYNC CDS NOTIFY 53 . eid01.example. 3600 IN EID 1289AB eui48.example. 3600 IN EUI48 01-23-45-67-89-ab eui64.example. 3600 IN EUI64 01-23-45-67-89-ab-cd-ef diff --git a/bin/tests/system/xfer/dig2.good b/bin/tests/system/xfer/dig2.good index 4b090f83fe..795381be59 100644 --- a/bin/tests/system/xfer/dig2.good +++ b/bin/tests/system/xfer/dig2.good @@ -49,6 +49,7 @@ ds01.example. 3600 IN NS ns42.example. ds01.example. 3600 IN DS 12892 5 2 26584835CA80C81C91999F31CFAF2A0E89D4FF1C8FAFD0DDB31A85C7 19277C13 ds02.example. 3600 IN NS ns43.example. ds02.example. 3600 IN DS 12892 5 1 7AA4A3F416C2F2391FB7AB0D434F762CD62D1390 +dsync01.example. 3600 IN DSYNC CDS NOTIFY 53 . eid01.example. 3600 IN EID 1289AB eui48.example. 3600 IN EUI48 01-23-45-67-89-ab eui64.example. 3600 IN EUI64 01-23-45-67-89-ab-cd-ef diff --git a/tests/dns/rdata_test.c b/tests/dns/rdata_test.c index 106e9e9a4b..48090d25b6 100644 --- a/tests/dns/rdata_test.c +++ b/tests/dns/rdata_test.c @@ -1712,6 +1712,113 @@ ISC_RUN_TEST_IMPL(ds) { dns_rdatatype_ds, sizeof(dns_rdata_ds_t)); } +/* + * DSYNC tests. + * + * draft-ietf-dnsop-generalized-notify-09 + * + * 2.1. Wire Format + * + * The DSYNC RDATA wire format is encoded as follows: + * + * 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | RRtype | Scheme | Port + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Target ... / + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-/ + * + * RRtype The type of generalized NOTIFY that this DSYNC RR defines the + * desired target address for (see "Resource Record (RR) TYPEs" IANA + * registry). For now, only CDS and CSYNC are supported values, with + * the former indicating an updated CDS or CDNSKEY record set. + * + * Scheme The mode used for contacting the desired notification + * address. This is an 8-bit unsigned integer. Records with value 0 + * (null scheme) are ignored by consumers. Value 1 is described in + * this document, and values 128-255 are reserved for private use. + * All other values are currently unassigned. + * + * Port The port on the target host of the notification service. This + * is a 16-bit unsigned integer in network byte order. Records with + * value 0 are ignored by consumers. + * + * Target The fully-qualified, uncompressed domain name of the target + * host providing the service of listening for generalized + * notifications of the specified type. This name MUST resolve to + * one or more address records. + * + * 2.2. Presentation Format + * + * The presentation format of the RDATA portion is as follows: + * + * * The RRtype field is represented as a mnemonic from the "Resource + * Record (RR) TYPEs" registry. + * + * * The Scheme field is represented by its mnemonic if assigned (see + * Section 6.2), otherwise as an unsigned decimal integer. + * + * * The Port field is represented as an unsigned decimal integer. + * + * * The Target field is represented as a ([RFC1035], + * Section 5.1). + */ +ISC_RUN_TEST_IMPL(dsync) { + text_ok_t text_ok[] = { + /* + * Invalid, empty record. + */ + TEXT_INVALID(""), + /* + * Known type and known scheme. + */ + TEXT_VALID("CDS NOTIFY 0 example.com"), + /* + * Known type and unknown scheme. + */ + TEXT_VALID("CDS 3 0 example.com"), + /* + * Unknown type and known scheme. + */ + TEXT_VALID("TYPE1000 NOTIFY 0 example.com"), + /* + * Unknown type and unknown scheme. + */ + TEXT_VALID("TYPE1000 3 0 example.com"), + /* + * Unknown type and unknown scheme, max port. + */ + TEXT_VALID("TYPE1000 3 65535 example.com"), + /* + * Unknown type and max scheme, max port. + */ + TEXT_VALID("TYPE64000 255 65535 example.com"), + /* + * Invalid type and max scheme, max port. + */ + TEXT_INVALID("INVALID 255 65536 example.com"), + /* + * Unknown type and too big scheme, max port. + */ + TEXT_INVALID("TYPE1000 256 65536 example.com"), + /* + * Unknown type and unknown scheme, port too big. + */ + TEXT_INVALID("TYPE1000 3 65536 example.com"), + /* + * Unknown type and bad scheme, max port. + */ + TEXT_INVALID("TYPE1000 UNKNOWN 65535 example.com"), + /* + * Sentinel. + */ + TEXT_SENTINEL() + }; + check_rdata(text_ok, NULL, NULL, false, dns_rdataclass_in, + dns_rdatatype_dsync, sizeof(dns_rdata_dsync_t)); +} + /* * EDNS Client Subnet tests. *