diff --git a/bin/tests/system/rrchecker/tests_rrchecker.py b/bin/tests/system/rrchecker/tests_rrchecker.py index bbe578f98b..8cc631a3da 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..52867df1dc --- /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, 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, NULL); + dns_name_init(&prefix, NULL); + + 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); + + dns_decompress_setmethods(dctx, DNS_COMPRESS_NONE); + + dns_name_init(&name, NULL); + + 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, options, 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_setmethods(cctx, DNS_COMPRESS_NONE); + + dns_rdata_toregion(rdata, ®ion); + RETERR(mem_tobuffer(target, region.base, 5)); + isc_region_consume(®ion, 5); + + dns_name_init(&name, NULL); + 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; + ISC_LINK_INIT(&dsync->common, link); + + dns_name_init(&name, NULL); + 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, NULL); + 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, NULL); + 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); +} + +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, NULL); + 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;