summaryrefslogtreecommitdiffstats
path: root/lib/dns/rdata/generic
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--lib/dns/rdata/generic/afsdb_18.c318
-rw-r--r--lib/dns/rdata/generic/afsdb_18.h24
-rw-r--r--lib/dns/rdata/generic/amtrelay_260.c472
-rw-r--r--lib/dns/rdata/generic/amtrelay_260.h27
-rw-r--r--lib/dns/rdata/generic/avc_258.c145
-rw-r--r--lib/dns/rdata/generic/avc_258.h30
-rw-r--r--lib/dns/rdata/generic/caa_257.c628
-rw-r--r--lib/dns/rdata/generic/caa_257.h24
-rw-r--r--lib/dns/rdata/generic/cdnskey_60.c164
-rw-r--r--lib/dns/rdata/generic/cdnskey_60.h17
-rw-r--r--lib/dns/rdata/generic/cds_59.c167
-rw-r--r--lib/dns/rdata/generic/cds_59.h17
-rw-r--r--lib/dns/rdata/generic/cert_37.c285
-rw-r--r--lib/dns/rdata/generic/cert_37.h25
-rw-r--r--lib/dns/rdata/generic/cname_5.c231
-rw-r--r--lib/dns/rdata/generic/cname_5.h20
-rw-r--r--lib/dns/rdata/generic/csync_62.c274
-rw-r--r--lib/dns/rdata/generic/csync_62.h27
-rw-r--r--lib/dns/rdata/generic/dlv_32769.c163
-rw-r--r--lib/dns/rdata/generic/dlv_32769.h17
-rw-r--r--lib/dns/rdata/generic/dname_39.c231
-rw-r--r--lib/dns/rdata/generic/dname_39.h23
-rw-r--r--lib/dns/rdata/generic/dnskey_48.c165
-rw-r--r--lib/dns/rdata/generic/dnskey_48.h20
-rw-r--r--lib/dns/rdata/generic/doa_259.c362
-rw-r--r--lib/dns/rdata/generic/doa_259.h26
-rw-r--r--lib/dns/rdata/generic/ds_43.c386
-rw-r--r--lib/dns/rdata/generic/ds_43.h26
-rw-r--r--lib/dns/rdata/generic/eui48_108.c212
-rw-r--r--lib/dns/rdata/generic/eui48_108.h20
-rw-r--r--lib/dns/rdata/generic/eui64_109.c215
-rw-r--r--lib/dns/rdata/generic/eui64_109.h20
-rw-r--r--lib/dns/rdata/generic/gpos_27.c257
-rw-r--r--lib/dns/rdata/generic/gpos_27.h28
-rw-r--r--lib/dns/rdata/generic/hinfo_13.c218
-rw-r--r--lib/dns/rdata/generic/hinfo_13.h23
-rw-r--r--lib/dns/rdata/generic/hip_55.c523
-rw-r--r--lib/dns/rdata/generic/hip_55.h39
-rw-r--r--lib/dns/rdata/generic/ipseckey_45.c527
-rw-r--r--lib/dns/rdata/generic/ipseckey_45.h27
-rw-r--r--lib/dns/rdata/generic/isdn_20.c248
-rw-r--r--lib/dns/rdata/generic/isdn_20.h26
-rw-r--r--lib/dns/rdata/generic/key_25.c469
-rw-r--r--lib/dns/rdata/generic/key_25.h27
-rw-r--r--lib/dns/rdata/generic/keydata_65533.c463
-rw-r--r--lib/dns/rdata/generic/keydata_65533.h27
-rw-r--r--lib/dns/rdata/generic/l32_105.c231
-rw-r--r--lib/dns/rdata/generic/l32_105.h21
-rw-r--r--lib/dns/rdata/generic/l64_106.c225
-rw-r--r--lib/dns/rdata/generic/l64_106.h21
-rw-r--r--lib/dns/rdata/generic/loc_29.c839
-rw-r--r--lib/dns/rdata/generic/loc_29.h34
-rw-r--r--lib/dns/rdata/generic/lp_107.c278
-rw-r--r--lib/dns/rdata/generic/lp_107.h22
-rw-r--r--lib/dns/rdata/generic/mb_7.c234
-rw-r--r--lib/dns/rdata/generic/mb_7.h21
-rw-r--r--lib/dns/rdata/generic/md_3.c236
-rw-r--r--lib/dns/rdata/generic/md_3.h21
-rw-r--r--lib/dns/rdata/generic/mf_4.c235
-rw-r--r--lib/dns/rdata/generic/mf_4.h21
-rw-r--r--lib/dns/rdata/generic/mg_8.c229
-rw-r--r--lib/dns/rdata/generic/mg_8.h21
-rw-r--r--lib/dns/rdata/generic/minfo_14.c323
-rw-r--r--lib/dns/rdata/generic/minfo_14.h22
-rw-r--r--lib/dns/rdata/generic/mr_9.c230
-rw-r--r--lib/dns/rdata/generic/mr_9.h21
-rw-r--r--lib/dns/rdata/generic/mx_15.c359
-rw-r--r--lib/dns/rdata/generic/mx_15.h22
-rw-r--r--lib/dns/rdata/generic/naptr_35.c738
-rw-r--r--lib/dns/rdata/generic/naptr_35.h31
-rw-r--r--lib/dns/rdata/generic/nid_104.c225
-rw-r--r--lib/dns/rdata/generic/nid_104.h21
-rw-r--r--lib/dns/rdata/generic/ninfo_56.c170
-rw-r--r--lib/dns/rdata/generic/ninfo_56.h33
-rw-r--r--lib/dns/rdata/generic/ns_2.c256
-rw-r--r--lib/dns/rdata/generic/ns_2.h21
-rw-r--r--lib/dns/rdata/generic/nsec3_50.c425
-rw-r--r--lib/dns/rdata/generic/nsec3_50.h109
-rw-r--r--lib/dns/rdata/generic/nsec3param_51.c322
-rw-r--r--lib/dns/rdata/generic/nsec3param_51.h29
-rw-r--r--lib/dns/rdata/generic/nsec_47.c291
-rw-r--r--lib/dns/rdata/generic/nsec_47.h25
-rw-r--r--lib/dns/rdata/generic/null_10.c187
-rw-r--r--lib/dns/rdata/generic/null_10.h22
-rw-r--r--lib/dns/rdata/generic/nxt_30.c351
-rw-r--r--lib/dns/rdata/generic/nxt_30.h25
-rw-r--r--lib/dns/rdata/generic/openpgpkey_61.c250
-rw-r--r--lib/dns/rdata/generic/openpgpkey_61.h21
-rw-r--r--lib/dns/rdata/generic/opt_41.c473
-rw-r--r--lib/dns/rdata/generic/opt_41.h46
-rw-r--r--lib/dns/rdata/generic/proforma.c165
-rw-r--r--lib/dns/rdata/generic/proforma.h22
-rw-r--r--lib/dns/rdata/generic/ptr_12.c279
-rw-r--r--lib/dns/rdata/generic/ptr_12.h21
-rw-r--r--lib/dns/rdata/generic/rkey_57.c161
-rw-r--r--lib/dns/rdata/generic/rkey_57.h16
-rw-r--r--lib/dns/rdata/generic/rp_17.c310
-rw-r--r--lib/dns/rdata/generic/rp_17.h24
-rw-r--r--lib/dns/rdata/generic/rrsig_46.c640
-rw-r--r--lib/dns/rdata/generic/rrsig_46.h31
-rw-r--r--lib/dns/rdata/generic/rt_21.c324
-rw-r--r--lib/dns/rdata/generic/rt_21.h24
-rw-r--r--lib/dns/rdata/generic/sig_24.c591
-rw-r--r--lib/dns/rdata/generic/sig_24.h32
-rw-r--r--lib/dns/rdata/generic/sink_40.c292
-rw-r--r--lib/dns/rdata/generic/sink_40.h24
-rw-r--r--lib/dns/rdata/generic/smimea_53.c153
-rw-r--r--lib/dns/rdata/generic/smimea_53.h16
-rw-r--r--lib/dns/rdata/generic/soa_6.c443
-rw-r--r--lib/dns/rdata/generic/soa_6.h27
-rw-r--r--lib/dns/rdata/generic/spf_99.c146
-rw-r--r--lib/dns/rdata/generic/spf_99.h33
-rw-r--r--lib/dns/rdata/generic/sshfp_44.c297
-rw-r--r--lib/dns/rdata/generic/sshfp_44.h26
-rw-r--r--lib/dns/rdata/generic/ta_32768.c163
-rw-r--r--lib/dns/rdata/generic/ta_32768.h19
-rw-r--r--lib/dns/rdata/generic/talink_58.c258
-rw-r--r--lib/dns/rdata/generic/talink_58.h25
-rw-r--r--lib/dns/rdata/generic/tkey_249.c581
-rw-r--r--lib/dns/rdata/generic/tkey_249.h31
-rw-r--r--lib/dns/rdata/generic/tlsa_52.c340
-rw-r--r--lib/dns/rdata/generic/tlsa_52.h27
-rw-r--r--lib/dns/rdata/generic/txt_16.c360
-rw-r--r--lib/dns/rdata/generic/txt_16.h43
-rw-r--r--lib/dns/rdata/generic/uri_256.c319
-rw-r--r--lib/dns/rdata/generic/uri_256.h23
-rw-r--r--lib/dns/rdata/generic/x25_19.c233
-rw-r--r--lib/dns/rdata/generic/x25_19.h24
-rw-r--r--lib/dns/rdata/generic/zonemd_63.c351
-rw-r--r--lib/dns/rdata/generic/zonemd_63.h31
130 files changed, 22345 insertions, 0 deletions
diff --git a/lib/dns/rdata/generic/afsdb_18.c b/lib/dns/rdata/generic/afsdb_18.c
new file mode 100644
index 0000000..077e0ac
--- /dev/null
+++ b/lib/dns/rdata/generic/afsdb_18.c
@@ -0,0 +1,318 @@
+/*
+ * 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.
+ */
+
+/* RFC1183 */
+
+#ifndef RDATA_GENERIC_AFSDB_18_C
+#define RDATA_GENERIC_AFSDB_18_C
+
+#define RRTYPE_AFSDB_ATTRIBUTES (0)
+
+static isc_result_t
+fromtext_afsdb(ARGS_FROMTEXT) {
+ isc_token_t token;
+ isc_buffer_t buffer;
+ dns_name_t name;
+ bool ok;
+
+ REQUIRE(type == dns_rdatatype_afsdb);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(callbacks);
+
+ /*
+ * Subtype.
+ */
+ 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));
+
+ /*
+ * Hostname.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ false));
+ dns_name_init(&name, NULL);
+ buffer_fromregion(&buffer, &token.value.as_region);
+ if (origin == NULL) {
+ origin = dns_rootname;
+ }
+ RETTOK(dns_name_fromtext(&name, &buffer, origin, options, target));
+ ok = true;
+ 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_afsdb(ARGS_TOTEXT) {
+ dns_name_t name;
+ dns_name_t prefix;
+ isc_region_t region;
+ char buf[sizeof("64000 ")];
+ bool sub;
+ unsigned int num;
+
+ REQUIRE(rdata->type == dns_rdatatype_afsdb);
+ REQUIRE(rdata->length != 0);
+
+ dns_name_init(&name, NULL);
+ dns_name_init(&prefix, NULL);
+
+ dns_rdata_toregion(rdata, &region);
+ num = uint16_fromregion(&region);
+ isc_region_consume(&region, 2);
+ snprintf(buf, sizeof(buf), "%u ", num);
+ RETERR(str_totext(buf, target));
+ dns_name_fromregion(&name, &region);
+ sub = name_prefix(&name, tctx->origin, &prefix);
+ return (dns_name_totext(&prefix, sub, target));
+}
+
+static isc_result_t
+fromwire_afsdb(ARGS_FROMWIRE) {
+ dns_name_t name;
+ isc_region_t sr;
+ isc_region_t tr;
+
+ REQUIRE(type == dns_rdatatype_afsdb);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ dns_decompress_setmethods(dctx, DNS_COMPRESS_NONE);
+
+ dns_name_init(&name, NULL);
+
+ isc_buffer_activeregion(source, &sr);
+ isc_buffer_availableregion(target, &tr);
+ if (tr.length < 2) {
+ return (ISC_R_NOSPACE);
+ }
+ if (sr.length < 2) {
+ return (ISC_R_UNEXPECTEDEND);
+ }
+ memmove(tr.base, sr.base, 2);
+ isc_buffer_forward(source, 2);
+ isc_buffer_add(target, 2);
+ return (dns_name_fromwire(&name, source, dctx, options, target));
+}
+
+static isc_result_t
+towire_afsdb(ARGS_TOWIRE) {
+ isc_region_t tr;
+ isc_region_t sr;
+ dns_name_t name;
+ dns_offsets_t offsets;
+
+ REQUIRE(rdata->type == dns_rdatatype_afsdb);
+ REQUIRE(rdata->length != 0);
+
+ dns_compress_setmethods(cctx, DNS_COMPRESS_NONE);
+ isc_buffer_availableregion(target, &tr);
+ dns_rdata_toregion(rdata, &sr);
+ if (tr.length < 2) {
+ return (ISC_R_NOSPACE);
+ }
+ memmove(tr.base, sr.base, 2);
+ isc_region_consume(&sr, 2);
+ isc_buffer_add(target, 2);
+
+ dns_name_init(&name, offsets);
+ dns_name_fromregion(&name, &sr);
+
+ return (dns_name_towire(&name, cctx, target));
+}
+
+static int
+compare_afsdb(ARGS_COMPARE) {
+ int result;
+ dns_name_t name1;
+ dns_name_t name2;
+ isc_region_t region1;
+ isc_region_t region2;
+
+ REQUIRE(rdata1->type == rdata2->type);
+ REQUIRE(rdata1->rdclass == rdata2->rdclass);
+ REQUIRE(rdata1->type == dns_rdatatype_afsdb);
+ REQUIRE(rdata1->length != 0);
+ REQUIRE(rdata2->length != 0);
+
+ result = memcmp(rdata1->data, rdata2->data, 2);
+ if (result != 0) {
+ return (result < 0 ? -1 : 1);
+ }
+
+ dns_name_init(&name1, NULL);
+ dns_name_init(&name2, NULL);
+
+ dns_rdata_toregion(rdata1, &region1);
+ dns_rdata_toregion(rdata2, &region2);
+
+ isc_region_consume(&region1, 2);
+ isc_region_consume(&region2, 2);
+
+ dns_name_fromregion(&name1, &region1);
+ dns_name_fromregion(&name2, &region2);
+
+ return (dns_name_rdatacompare(&name1, &name2));
+}
+
+static isc_result_t
+fromstruct_afsdb(ARGS_FROMSTRUCT) {
+ dns_rdata_afsdb_t *afsdb = source;
+ isc_region_t region;
+
+ REQUIRE(type == dns_rdatatype_afsdb);
+ REQUIRE(afsdb != NULL);
+ REQUIRE(afsdb->common.rdclass == rdclass);
+ REQUIRE(afsdb->common.rdtype == type);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ RETERR(uint16_tobuffer(afsdb->subtype, target));
+ dns_name_toregion(&afsdb->server, &region);
+ return (isc_buffer_copyregion(target, &region));
+}
+
+static isc_result_t
+tostruct_afsdb(ARGS_TOSTRUCT) {
+ isc_region_t region;
+ dns_rdata_afsdb_t *afsdb = target;
+ dns_name_t name;
+
+ REQUIRE(rdata->type == dns_rdatatype_afsdb);
+ REQUIRE(afsdb != NULL);
+ REQUIRE(rdata->length != 0);
+
+ afsdb->common.rdclass = rdata->rdclass;
+ afsdb->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&afsdb->common, link);
+
+ dns_name_init(&afsdb->server, NULL);
+
+ dns_rdata_toregion(rdata, &region);
+
+ afsdb->subtype = uint16_fromregion(&region);
+ isc_region_consume(&region, 2);
+
+ dns_name_init(&name, NULL);
+ dns_name_fromregion(&name, &region);
+
+ name_duporclone(&name, mctx, &afsdb->server);
+ afsdb->mctx = mctx;
+ return (ISC_R_SUCCESS);
+}
+
+static void
+freestruct_afsdb(ARGS_FREESTRUCT) {
+ dns_rdata_afsdb_t *afsdb = source;
+
+ REQUIRE(afsdb != NULL);
+ REQUIRE(afsdb->common.rdtype == dns_rdatatype_afsdb);
+
+ if (afsdb->mctx == NULL) {
+ return;
+ }
+
+ dns_name_free(&afsdb->server, afsdb->mctx);
+ afsdb->mctx = NULL;
+}
+
+static isc_result_t
+additionaldata_afsdb(ARGS_ADDLDATA) {
+ dns_name_t name;
+ dns_offsets_t offsets;
+ isc_region_t region;
+
+ REQUIRE(rdata->type == dns_rdatatype_afsdb);
+
+ UNUSED(owner);
+
+ dns_name_init(&name, offsets);
+ dns_rdata_toregion(rdata, &region);
+ isc_region_consume(&region, 2);
+ dns_name_fromregion(&name, &region);
+
+ return ((add)(arg, &name, dns_rdatatype_a, NULL));
+}
+
+static isc_result_t
+digest_afsdb(ARGS_DIGEST) {
+ isc_region_t r1, r2;
+ dns_name_t name;
+
+ REQUIRE(rdata->type == dns_rdatatype_afsdb);
+
+ dns_rdata_toregion(rdata, &r1);
+ r2 = r1;
+ isc_region_consume(&r2, 2);
+ r1.length = 2;
+ RETERR((digest)(arg, &r1));
+ dns_name_init(&name, NULL);
+ dns_name_fromregion(&name, &r2);
+
+ return (dns_name_digest(&name, digest, arg));
+}
+
+static bool
+checkowner_afsdb(ARGS_CHECKOWNER) {
+ REQUIRE(type == dns_rdatatype_afsdb);
+
+ UNUSED(name);
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (true);
+}
+
+static bool
+checknames_afsdb(ARGS_CHECKNAMES) {
+ isc_region_t region;
+ dns_name_t name;
+
+ REQUIRE(rdata->type == dns_rdatatype_afsdb);
+
+ UNUSED(owner);
+
+ dns_rdata_toregion(rdata, &region);
+ isc_region_consume(&region, 2);
+ dns_name_init(&name, NULL);
+ dns_name_fromregion(&name, &region);
+ if (!dns_name_ishostname(&name, false)) {
+ if (bad != NULL) {
+ dns_name_clone(&name, bad);
+ }
+ return (false);
+ }
+ return (true);
+}
+
+static int
+casecompare_afsdb(ARGS_COMPARE) {
+ return (compare_afsdb(rdata1, rdata2));
+}
+#endif /* RDATA_GENERIC_AFSDB_18_C */
diff --git a/lib/dns/rdata/generic/afsdb_18.h b/lib/dns/rdata/generic/afsdb_18.h
new file mode 100644
index 0000000..16b390c
--- /dev/null
+++ b/lib/dns/rdata/generic/afsdb_18.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
+
+/*!
+ * \brief Per RFC1183 */
+
+typedef struct dns_rdata_afsdb {
+ dns_rdatacommon_t common;
+ isc_mem_t *mctx;
+ uint16_t subtype;
+ dns_name_t server;
+} dns_rdata_afsdb_t;
diff --git a/lib/dns/rdata/generic/amtrelay_260.c b/lib/dns/rdata/generic/amtrelay_260.c
new file mode 100644
index 0000000..a6d30e1
--- /dev/null
+++ b/lib/dns/rdata/generic/amtrelay_260.c
@@ -0,0 +1,472 @@
+/*
+ * 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_AMTRELAY_260_C
+#define RDATA_GENERIC_AMTRELAY_260_C
+
+#include <string.h>
+
+#include <isc/net.h>
+
+#define RRTYPE_AMTRELAY_ATTRIBUTES (0)
+
+static isc_result_t
+fromtext_amtrelay(ARGS_FROMTEXT) {
+ isc_token_t token;
+ dns_name_t name;
+ isc_buffer_t buffer;
+ unsigned int discovery;
+ unsigned int gateway;
+ struct in_addr addr;
+ unsigned char addr6[16];
+ isc_region_t region;
+
+ REQUIRE(type == dns_rdatatype_amtrelay);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(callbacks);
+
+ /*
+ * Precedence.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
+ false));
+ if (token.value.as_ulong > 0xffU) {
+ RETTOK(ISC_R_RANGE);
+ }
+ RETERR(uint8_tobuffer(token.value.as_ulong, target));
+
+ /*
+ * Discovery.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
+ false));
+ if (token.value.as_ulong > 1U) {
+ RETTOK(ISC_R_RANGE);
+ }
+ discovery = token.value.as_ulong;
+
+ /*
+ * Gateway type.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
+ false));
+ if (token.value.as_ulong > 0x7fU) {
+ RETTOK(ISC_R_RANGE);
+ }
+ RETERR(uint8_tobuffer(token.value.as_ulong | (discovery << 7), target));
+ gateway = token.value.as_ulong;
+
+ if (gateway == 0) {
+ return (ISC_R_SUCCESS);
+ }
+
+ if (gateway > 3) {
+ return (ISC_R_NOTIMPLEMENTED);
+ }
+
+ /*
+ * Gateway.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ false));
+
+ switch (gateway) {
+ case 1:
+ if (inet_pton(AF_INET, DNS_AS_STR(token), &addr) != 1) {
+ RETTOK(DNS_R_BADDOTTEDQUAD);
+ }
+ isc_buffer_availableregion(target, &region);
+ if (region.length < 4) {
+ return (ISC_R_NOSPACE);
+ }
+ memmove(region.base, &addr, 4);
+ isc_buffer_add(target, 4);
+ return (ISC_R_SUCCESS);
+
+ case 2:
+ if (inet_pton(AF_INET6, DNS_AS_STR(token), addr6) != 1) {
+ RETTOK(DNS_R_BADAAAA);
+ }
+ isc_buffer_availableregion(target, &region);
+ if (region.length < 16) {
+ return (ISC_R_NOSPACE);
+ }
+ memmove(region.base, addr6, 16);
+ isc_buffer_add(target, 16);
+ return (ISC_R_SUCCESS);
+
+ case 3:
+ dns_name_init(&name, NULL);
+ buffer_fromregion(&buffer, &token.value.as_region);
+ if (origin == NULL) {
+ origin = dns_rootname;
+ }
+ return (dns_name_fromtext(&name, &buffer, origin, options,
+ target));
+ default:
+ UNREACHABLE();
+ }
+}
+
+static isc_result_t
+totext_amtrelay(ARGS_TOTEXT) {
+ isc_region_t region;
+ dns_name_t name;
+ char buf[sizeof("0 255 ")];
+ unsigned char precedence;
+ unsigned char discovery;
+ unsigned char gateway;
+ const char *space;
+
+ UNUSED(tctx);
+
+ REQUIRE(rdata->type == dns_rdatatype_amtrelay);
+ REQUIRE(rdata->length >= 2);
+
+ if ((rdata->data[1] & 0x7f) > 3U) {
+ return (ISC_R_NOTIMPLEMENTED);
+ }
+
+ /*
+ * Precedence.
+ */
+ dns_rdata_toregion(rdata, &region);
+ precedence = uint8_fromregion(&region);
+ isc_region_consume(&region, 1);
+ snprintf(buf, sizeof(buf), "%u ", precedence);
+ RETERR(str_totext(buf, target));
+
+ /*
+ * Discovery and Gateway type.
+ */
+ gateway = uint8_fromregion(&region);
+ discovery = gateway >> 7;
+ gateway &= 0x7f;
+ space = (gateway != 0U) ? " " : "";
+ isc_region_consume(&region, 1);
+ snprintf(buf, sizeof(buf), "%u %u%s", discovery, gateway, space);
+ RETERR(str_totext(buf, target));
+
+ /*
+ * Gateway.
+ */
+ switch (gateway) {
+ case 0:
+ break;
+ case 1:
+ return (inet_totext(AF_INET, tctx->flags, &region, target));
+
+ case 2:
+ return (inet_totext(AF_INET6, tctx->flags, &region, target));
+
+ case 3:
+ dns_name_init(&name, NULL);
+ dns_name_fromregion(&name, &region);
+ return (dns_name_totext(&name, false, target));
+
+ default:
+ UNREACHABLE();
+ }
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+fromwire_amtrelay(ARGS_FROMWIRE) {
+ dns_name_t name;
+ isc_region_t region;
+
+ REQUIRE(type == dns_rdatatype_amtrelay);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ dns_decompress_setmethods(dctx, DNS_COMPRESS_NONE);
+
+ isc_buffer_activeregion(source, &region);
+ if (region.length < 2) {
+ return (ISC_R_UNEXPECTEDEND);
+ }
+
+ switch (region.base[1] & 0x7f) {
+ case 0:
+ if (region.length != 2) {
+ return (DNS_R_FORMERR);
+ }
+ isc_buffer_forward(source, region.length);
+ return (mem_tobuffer(target, region.base, region.length));
+
+ case 1:
+ if (region.length != 6) {
+ return (DNS_R_FORMERR);
+ }
+ isc_buffer_forward(source, region.length);
+ return (mem_tobuffer(target, region.base, region.length));
+
+ case 2:
+ if (region.length != 18) {
+ return (DNS_R_FORMERR);
+ }
+ isc_buffer_forward(source, region.length);
+ return (mem_tobuffer(target, region.base, region.length));
+
+ case 3:
+ RETERR(mem_tobuffer(target, region.base, 2));
+ isc_buffer_forward(source, 2);
+ dns_name_init(&name, NULL);
+ return (dns_name_fromwire(&name, source, dctx, options,
+ target));
+
+ default:
+ isc_buffer_forward(source, region.length);
+ return (mem_tobuffer(target, region.base, region.length));
+ }
+}
+
+static isc_result_t
+towire_amtrelay(ARGS_TOWIRE) {
+ isc_region_t region;
+
+ REQUIRE(rdata->type == dns_rdatatype_amtrelay);
+ REQUIRE(rdata->length != 0);
+
+ UNUSED(cctx);
+
+ dns_rdata_toregion(rdata, &region);
+ return (mem_tobuffer(target, region.base, region.length));
+}
+
+static int
+compare_amtrelay(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_amtrelay);
+ REQUIRE(rdata1->length >= 2);
+ REQUIRE(rdata2->length >= 2);
+
+ dns_rdata_toregion(rdata1, &region1);
+ dns_rdata_toregion(rdata2, &region2);
+
+ return (isc_region_compare(&region1, &region2));
+}
+
+static isc_result_t
+fromstruct_amtrelay(ARGS_FROMSTRUCT) {
+ dns_rdata_amtrelay_t *amtrelay = source;
+ isc_region_t region;
+ uint32_t n;
+
+ REQUIRE(type == dns_rdatatype_amtrelay);
+ REQUIRE(amtrelay != NULL);
+ REQUIRE(amtrelay->common.rdtype == type);
+ REQUIRE(amtrelay->common.rdclass == rdclass);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ RETERR(uint8_tobuffer(amtrelay->precedence, target));
+ n = (amtrelay->discovery ? 0x80 : 0) | amtrelay->gateway_type;
+ RETERR(uint8_tobuffer(n, target));
+
+ switch (amtrelay->gateway_type) {
+ case 0:
+ return (ISC_R_SUCCESS);
+
+ case 1:
+ n = ntohl(amtrelay->in_addr.s_addr);
+ return (uint32_tobuffer(n, target));
+
+ case 2:
+ return (mem_tobuffer(target, amtrelay->in6_addr.s6_addr, 16));
+ break;
+
+ case 3:
+ dns_name_toregion(&amtrelay->gateway, &region);
+ return (isc_buffer_copyregion(target, &region));
+ break;
+
+ default:
+ return (mem_tobuffer(target, amtrelay->data, amtrelay->length));
+ }
+}
+
+static isc_result_t
+tostruct_amtrelay(ARGS_TOSTRUCT) {
+ isc_region_t region;
+ dns_rdata_amtrelay_t *amtrelay = target;
+ dns_name_t name;
+ uint32_t n;
+
+ REQUIRE(rdata->type == dns_rdatatype_amtrelay);
+ REQUIRE(amtrelay != NULL);
+ REQUIRE(rdata->length >= 2);
+
+ amtrelay->common.rdclass = rdata->rdclass;
+ amtrelay->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&amtrelay->common, link);
+
+ dns_name_init(&amtrelay->gateway, NULL);
+ amtrelay->data = NULL;
+
+ dns_name_init(&name, NULL);
+ dns_rdata_toregion(rdata, &region);
+
+ amtrelay->precedence = uint8_fromregion(&region);
+ isc_region_consume(&region, 1);
+
+ amtrelay->gateway_type = uint8_fromregion(&region);
+ amtrelay->discovery = (amtrelay->gateway_type & 0x80) != 0;
+ amtrelay->gateway_type &= 0x7f;
+ isc_region_consume(&region, 1);
+
+ switch (amtrelay->gateway_type) {
+ case 0:
+ break;
+
+ case 1:
+ n = uint32_fromregion(&region);
+ amtrelay->in_addr.s_addr = htonl(n);
+ isc_region_consume(&region, 4);
+ break;
+
+ case 2:
+ memmove(amtrelay->in6_addr.s6_addr, region.base, 16);
+ isc_region_consume(&region, 16);
+ break;
+
+ case 3:
+ dns_name_fromregion(&name, &region);
+ name_duporclone(&name, mctx, &amtrelay->gateway);
+ isc_region_consume(&region, name_length(&name));
+ break;
+
+ default:
+ if (region.length != 0) {
+ amtrelay->data = mem_maybedup(mctx, region.base,
+ region.length);
+ if (amtrelay->data == NULL) {
+ return (ISC_R_NOMEMORY);
+ }
+ }
+ amtrelay->length = region.length;
+ }
+ amtrelay->mctx = mctx;
+ return (ISC_R_SUCCESS);
+}
+
+static void
+freestruct_amtrelay(ARGS_FREESTRUCT) {
+ dns_rdata_amtrelay_t *amtrelay = source;
+
+ REQUIRE(amtrelay != NULL);
+ REQUIRE(amtrelay->common.rdtype == dns_rdatatype_amtrelay);
+
+ if (amtrelay->mctx == NULL) {
+ return;
+ }
+
+ if (amtrelay->gateway_type == 3) {
+ dns_name_free(&amtrelay->gateway, amtrelay->mctx);
+ }
+
+ if (amtrelay->data != NULL) {
+ isc_mem_free(amtrelay->mctx, amtrelay->data);
+ }
+
+ amtrelay->mctx = NULL;
+}
+
+static isc_result_t
+additionaldata_amtrelay(ARGS_ADDLDATA) {
+ REQUIRE(rdata->type == dns_rdatatype_amtrelay);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(add);
+ UNUSED(arg);
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+digest_amtrelay(ARGS_DIGEST) {
+ isc_region_t region;
+
+ REQUIRE(rdata->type == dns_rdatatype_amtrelay);
+
+ dns_rdata_toregion(rdata, &region);
+ return ((digest)(arg, &region));
+}
+
+static bool
+checkowner_amtrelay(ARGS_CHECKOWNER) {
+ REQUIRE(type == dns_rdatatype_amtrelay);
+
+ UNUSED(name);
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (true);
+}
+
+static bool
+checknames_amtrelay(ARGS_CHECKNAMES) {
+ REQUIRE(rdata->type == dns_rdatatype_amtrelay);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(bad);
+
+ return (true);
+}
+
+static int
+casecompare_amtrelay(ARGS_COMPARE) {
+ isc_region_t region1;
+ isc_region_t region2;
+ dns_name_t name1;
+ dns_name_t name2;
+
+ REQUIRE(rdata1->type == rdata2->type);
+ REQUIRE(rdata1->rdclass == rdata2->rdclass);
+ REQUIRE(rdata1->type == dns_rdatatype_amtrelay);
+ REQUIRE(rdata1->length >= 2);
+ REQUIRE(rdata2->length >= 2);
+
+ dns_rdata_toregion(rdata1, &region1);
+ dns_rdata_toregion(rdata2, &region2);
+
+ if (memcmp(region1.base, region2.base, 2) != 0 ||
+ (region1.base[1] & 0x7f) != 3)
+ {
+ return (isc_region_compare(&region1, &region2));
+ }
+
+ dns_name_init(&name1, NULL);
+ dns_name_init(&name2, NULL);
+
+ isc_region_consume(&region1, 2);
+ isc_region_consume(&region2, 2);
+
+ dns_name_fromregion(&name1, &region1);
+ dns_name_fromregion(&name2, &region2);
+
+ return (dns_name_rdatacompare(&name1, &name2));
+}
+
+#endif /* RDATA_GENERIC_AMTRELAY_260_C */
diff --git a/lib/dns/rdata/generic/amtrelay_260.h b/lib/dns/rdata/generic/amtrelay_260.h
new file mode 100644
index 0000000..8680c35
--- /dev/null
+++ b/lib/dns/rdata/generic/amtrelay_260.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
+
+typedef struct dns_rdata_amtrelay {
+ dns_rdatacommon_t common;
+ isc_mem_t *mctx;
+ uint8_t precedence;
+ bool discovery;
+ uint8_t gateway_type;
+ struct in_addr in_addr; /* gateway type 1 */
+ struct in6_addr in6_addr; /* gateway type 2 */
+ dns_name_t gateway; /* gateway type 3 */
+ unsigned char *data; /* gateway type > 3 */
+ uint16_t length;
+} dns_rdata_amtrelay_t;
diff --git a/lib/dns/rdata/generic/avc_258.c b/lib/dns/rdata/generic/avc_258.c
new file mode 100644
index 0000000..8c7c8d0
--- /dev/null
+++ b/lib/dns/rdata/generic/avc_258.c
@@ -0,0 +1,145 @@
+/*
+ * 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_AVC_258_C
+#define RDATA_GENERIC_AVC_258_C
+
+#define RRTYPE_AVC_ATTRIBUTES (0)
+
+static isc_result_t
+fromtext_avc(ARGS_FROMTEXT) {
+ REQUIRE(type == dns_rdatatype_avc);
+
+ return (generic_fromtext_txt(CALL_FROMTEXT));
+}
+
+static isc_result_t
+totext_avc(ARGS_TOTEXT) {
+ REQUIRE(rdata != NULL);
+ REQUIRE(rdata->type == dns_rdatatype_avc);
+
+ return (generic_totext_txt(CALL_TOTEXT));
+}
+
+static isc_result_t
+fromwire_avc(ARGS_FROMWIRE) {
+ REQUIRE(type == dns_rdatatype_avc);
+
+ return (generic_fromwire_txt(CALL_FROMWIRE));
+}
+
+static isc_result_t
+towire_avc(ARGS_TOWIRE) {
+ REQUIRE(rdata->type == dns_rdatatype_avc);
+
+ UNUSED(cctx);
+
+ return (mem_tobuffer(target, rdata->data, rdata->length));
+}
+
+static int
+compare_avc(ARGS_COMPARE) {
+ isc_region_t r1;
+ isc_region_t r2;
+
+ REQUIRE(rdata1->type == rdata2->type);
+ REQUIRE(rdata1->rdclass == rdata2->rdclass);
+ REQUIRE(rdata1->type == dns_rdatatype_avc);
+
+ dns_rdata_toregion(rdata1, &r1);
+ dns_rdata_toregion(rdata2, &r2);
+ return (isc_region_compare(&r1, &r2));
+}
+
+static isc_result_t
+fromstruct_avc(ARGS_FROMSTRUCT) {
+ REQUIRE(type == dns_rdatatype_avc);
+
+ return (generic_fromstruct_txt(CALL_FROMSTRUCT));
+}
+
+static isc_result_t
+tostruct_avc(ARGS_TOSTRUCT) {
+ dns_rdata_avc_t *avc = target;
+
+ REQUIRE(rdata->type == dns_rdatatype_avc);
+ REQUIRE(avc != NULL);
+
+ avc->common.rdclass = rdata->rdclass;
+ avc->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&avc->common, link);
+
+ return (generic_tostruct_txt(CALL_TOSTRUCT));
+}
+
+static void
+freestruct_avc(ARGS_FREESTRUCT) {
+ dns_rdata_avc_t *avc = source;
+
+ REQUIRE(avc != NULL);
+ REQUIRE(avc->common.rdtype == dns_rdatatype_avc);
+
+ generic_freestruct_txt(source);
+}
+
+static isc_result_t
+additionaldata_avc(ARGS_ADDLDATA) {
+ REQUIRE(rdata->type == dns_rdatatype_avc);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(add);
+ UNUSED(arg);
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+digest_avc(ARGS_DIGEST) {
+ isc_region_t r;
+
+ REQUIRE(rdata->type == dns_rdatatype_avc);
+
+ dns_rdata_toregion(rdata, &r);
+
+ return ((digest)(arg, &r));
+}
+
+static bool
+checkowner_avc(ARGS_CHECKOWNER) {
+ REQUIRE(type == dns_rdatatype_avc);
+
+ UNUSED(name);
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (true);
+}
+
+static bool
+checknames_avc(ARGS_CHECKNAMES) {
+ REQUIRE(rdata->type == dns_rdatatype_avc);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(bad);
+
+ return (true);
+}
+
+static int
+casecompare_avc(ARGS_COMPARE) {
+ return (compare_avc(rdata1, rdata2));
+}
+#endif /* RDATA_GENERIC_AVC_258_C */
diff --git a/lib/dns/rdata/generic/avc_258.h b/lib/dns/rdata/generic/avc_258.h
new file mode 100644
index 0000000..828d7f0
--- /dev/null
+++ b/lib/dns/rdata/generic/avc_258.h
@@ -0,0 +1,30 @@
+/*
+ * 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 dns_rdata_txt_string_t dns_rdata_avc_string_t;
+
+typedef struct dns_rdata_avc {
+ dns_rdatacommon_t common;
+ isc_mem_t *mctx;
+ unsigned char *data;
+ uint16_t length;
+ /* private */
+ uint16_t offset;
+} dns_rdata_avc_t;
+
+/*
+ * ISC_LANG_BEGINDECLS and ISC_LANG_ENDDECLS are already done
+ * via rdatastructpre.h and rdatastructsuf.h.
+ */
diff --git a/lib/dns/rdata/generic/caa_257.c b/lib/dns/rdata/generic/caa_257.c
new file mode 100644
index 0000000..70bf9f2
--- /dev/null
+++ b/lib/dns/rdata/generic/caa_257.c
@@ -0,0 +1,628 @@
+/*
+ * 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 GENERIC_CAA_257_C
+#define GENERIC_CAA_257_C 1
+
+#define RRTYPE_CAA_ATTRIBUTES (0)
+
+static unsigned char const alphanumeric[256] = {
+ /* 0x00-0x0f */ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ /* 0x10-0x1f */ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ /* 0x20-0x2f */ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ /* 0x30-0x3f */ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ /* 0x40-0x4f */ 0,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ /* 0x50-0x5f */ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ /* 0x60-0x6f */ 0,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ /* 0x70-0x7f */ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ /* 0x80-0x8f */ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ /* 0x90-0x9f */ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ /* 0xa0-0xaf */ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ /* 0xb0-0xbf */ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ /* 0xc0-0xcf */ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ /* 0xd0-0xdf */ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ /* 0xe0-0xef */ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ /* 0xf0-0xff */ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+};
+
+static isc_result_t
+fromtext_caa(ARGS_FROMTEXT) {
+ isc_token_t token;
+ isc_textregion_t tr;
+ uint8_t flags;
+ unsigned int i;
+
+ REQUIRE(type == dns_rdatatype_caa);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(origin);
+ UNUSED(options);
+ UNUSED(callbacks);
+
+ /* Flags. */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
+ false));
+ if (token.value.as_ulong > 255U) {
+ RETTOK(ISC_R_RANGE);
+ }
+ flags = (uint8_t)(token.value.as_ulong & 255U);
+ RETERR(uint8_tobuffer(flags, target));
+
+ /*
+ * Tag
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ false));
+ tr = token.value.as_textregion;
+ for (i = 0; i < tr.length; i++) {
+ if (!alphanumeric[(unsigned char)tr.base[i]]) {
+ RETTOK(DNS_R_SYNTAX);
+ }
+ }
+ RETERR(uint8_tobuffer(tr.length, target));
+ RETERR(mem_tobuffer(target, tr.base, tr.length));
+
+ /*
+ * Value
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_qstring,
+ false));
+ if (token.type != isc_tokentype_qstring &&
+ token.type != isc_tokentype_string)
+ {
+ RETERR(DNS_R_SYNTAX);
+ }
+ RETERR(multitxt_fromtext(&token.value.as_textregion, target));
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+totext_caa(ARGS_TOTEXT) {
+ isc_region_t region;
+ uint8_t flags;
+ char buf[256];
+
+ UNUSED(tctx);
+
+ REQUIRE(rdata->type == dns_rdatatype_caa);
+ REQUIRE(rdata->length >= 3U);
+ REQUIRE(rdata->data != NULL);
+
+ dns_rdata_toregion(rdata, &region);
+
+ /*
+ * Flags
+ */
+ flags = uint8_consume_fromregion(&region);
+ snprintf(buf, sizeof(buf), "%u ", flags);
+ RETERR(str_totext(buf, target));
+
+ /*
+ * Tag
+ */
+ RETERR(txt_totext(&region, false, target));
+ RETERR(str_totext(" ", target));
+
+ /*
+ * Value
+ */
+ RETERR(multitxt_totext(&region, target));
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+fromwire_caa(ARGS_FROMWIRE) {
+ isc_region_t sr;
+ unsigned int len, i;
+
+ REQUIRE(type == dns_rdatatype_caa);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(dctx);
+ UNUSED(options);
+
+ /*
+ * Flags
+ */
+ isc_buffer_activeregion(source, &sr);
+ if (sr.length < 2) {
+ return (ISC_R_UNEXPECTEDEND);
+ }
+
+ /*
+ * Flags, tag length
+ */
+ RETERR(mem_tobuffer(target, sr.base, 2));
+ len = sr.base[1];
+ isc_region_consume(&sr, 2);
+ isc_buffer_forward(source, 2);
+
+ /*
+ * Zero length tag fields are illegal.
+ */
+ if (sr.length < len || len == 0) {
+ RETERR(DNS_R_FORMERR);
+ }
+
+ /* Check the Tag's value */
+ for (i = 0; i < len; i++) {
+ if (!alphanumeric[sr.base[i]]) {
+ RETERR(DNS_R_FORMERR);
+ /*
+ * Tag + Value
+ */
+ }
+ }
+ /*
+ * Tag + Value
+ */
+ isc_buffer_forward(source, sr.length);
+ return (mem_tobuffer(target, sr.base, sr.length));
+}
+
+static isc_result_t
+towire_caa(ARGS_TOWIRE) {
+ isc_region_t region;
+
+ REQUIRE(rdata->type == dns_rdatatype_caa);
+ REQUIRE(rdata->length >= 3U);
+ REQUIRE(rdata->data != NULL);
+
+ UNUSED(cctx);
+
+ dns_rdata_toregion(rdata, &region);
+ return (mem_tobuffer(target, region.base, region.length));
+}
+
+static int
+compare_caa(ARGS_COMPARE) {
+ isc_region_t r1, r2;
+
+ REQUIRE(rdata1->type == rdata2->type);
+ REQUIRE(rdata1->rdclass == rdata2->rdclass);
+ REQUIRE(rdata1->type == dns_rdatatype_caa);
+ REQUIRE(rdata1->length >= 3U);
+ REQUIRE(rdata2->length >= 3U);
+ REQUIRE(rdata1->data != NULL);
+ REQUIRE(rdata2->data != NULL);
+
+ dns_rdata_toregion(rdata1, &r1);
+ dns_rdata_toregion(rdata2, &r2);
+ return (isc_region_compare(&r1, &r2));
+}
+
+static isc_result_t
+fromstruct_caa(ARGS_FROMSTRUCT) {
+ dns_rdata_caa_t *caa = source;
+ isc_region_t region;
+ unsigned int i;
+
+ REQUIRE(type == dns_rdatatype_caa);
+ REQUIRE(caa != NULL);
+ REQUIRE(caa->common.rdtype == type);
+ REQUIRE(caa->common.rdclass == rdclass);
+ REQUIRE(caa->tag != NULL && caa->tag_len != 0);
+ REQUIRE(caa->value != NULL);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ /*
+ * Flags
+ */
+ RETERR(uint8_tobuffer(caa->flags, target));
+
+ /*
+ * Tag length
+ */
+ RETERR(uint8_tobuffer(caa->tag_len, target));
+
+ /*
+ * Tag
+ */
+ region.base = caa->tag;
+ region.length = caa->tag_len;
+ for (i = 0; i < region.length; i++) {
+ if (!alphanumeric[region.base[i]]) {
+ RETERR(DNS_R_SYNTAX);
+ }
+ }
+ RETERR(isc_buffer_copyregion(target, &region));
+
+ /*
+ * Value
+ */
+ region.base = caa->value;
+ region.length = caa->value_len;
+ return (isc_buffer_copyregion(target, &region));
+}
+
+static isc_result_t
+tostruct_caa(ARGS_TOSTRUCT) {
+ dns_rdata_caa_t *caa = target;
+ isc_region_t sr;
+
+ REQUIRE(rdata->type == dns_rdatatype_caa);
+ REQUIRE(caa != NULL);
+ REQUIRE(rdata->length >= 3U);
+ REQUIRE(rdata->data != NULL);
+
+ caa->common.rdclass = rdata->rdclass;
+ caa->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&caa->common, link);
+
+ dns_rdata_toregion(rdata, &sr);
+
+ /*
+ * Flags
+ */
+ if (sr.length < 1) {
+ return (ISC_R_UNEXPECTEDEND);
+ }
+ caa->flags = uint8_fromregion(&sr);
+ isc_region_consume(&sr, 1);
+
+ /*
+ * Tag length
+ */
+ if (sr.length < 1) {
+ return (ISC_R_UNEXPECTEDEND);
+ }
+ caa->tag_len = uint8_fromregion(&sr);
+ isc_region_consume(&sr, 1);
+
+ /*
+ * Tag
+ */
+ if (sr.length < caa->tag_len) {
+ return (ISC_R_UNEXPECTEDEND);
+ }
+ caa->tag = mem_maybedup(mctx, sr.base, caa->tag_len);
+ if (caa->tag == NULL) {
+ return (ISC_R_NOMEMORY);
+ }
+ isc_region_consume(&sr, caa->tag_len);
+
+ /*
+ * Value
+ */
+ caa->value_len = sr.length;
+ caa->value = mem_maybedup(mctx, sr.base, sr.length);
+ if (caa->value == NULL) {
+ return (ISC_R_NOMEMORY);
+ }
+
+ caa->mctx = mctx;
+ return (ISC_R_SUCCESS);
+}
+
+static void
+freestruct_caa(ARGS_FREESTRUCT) {
+ dns_rdata_caa_t *caa = (dns_rdata_caa_t *)source;
+
+ REQUIRE(caa != NULL);
+ REQUIRE(caa->common.rdtype == dns_rdatatype_caa);
+
+ if (caa->mctx == NULL) {
+ return;
+ }
+
+ if (caa->tag != NULL) {
+ isc_mem_free(caa->mctx, caa->tag);
+ }
+ if (caa->value != NULL) {
+ isc_mem_free(caa->mctx, caa->value);
+ }
+ caa->mctx = NULL;
+}
+
+static isc_result_t
+additionaldata_caa(ARGS_ADDLDATA) {
+ REQUIRE(rdata->type == dns_rdatatype_caa);
+ REQUIRE(rdata->data != NULL);
+ REQUIRE(rdata->length >= 3U);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(add);
+ UNUSED(arg);
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+digest_caa(ARGS_DIGEST) {
+ isc_region_t r;
+
+ REQUIRE(rdata->type == dns_rdatatype_caa);
+ REQUIRE(rdata->data != NULL);
+ REQUIRE(rdata->length >= 3U);
+
+ dns_rdata_toregion(rdata, &r);
+
+ return ((digest)(arg, &r));
+}
+
+static bool
+checkowner_caa(ARGS_CHECKOWNER) {
+ REQUIRE(type == dns_rdatatype_caa);
+
+ UNUSED(name);
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (true);
+}
+
+static bool
+checknames_caa(ARGS_CHECKNAMES) {
+ REQUIRE(rdata->type == dns_rdatatype_caa);
+ REQUIRE(rdata->data != NULL);
+ REQUIRE(rdata->length >= 3U);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(bad);
+
+ return (true);
+}
+
+static int
+casecompare_caa(ARGS_COMPARE) {
+ return (compare_caa(rdata1, rdata2));
+}
+
+#endif /* GENERIC_CAA_257_C */
diff --git a/lib/dns/rdata/generic/caa_257.h b/lib/dns/rdata/generic/caa_257.h
new file mode 100644
index 0000000..f5f348d
--- /dev/null
+++ b/lib/dns/rdata/generic/caa_257.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_caa {
+ dns_rdatacommon_t common;
+ isc_mem_t *mctx;
+ uint8_t flags;
+ unsigned char *tag;
+ uint8_t tag_len;
+ unsigned char *value;
+ uint16_t value_len;
+} dns_rdata_caa_t;
diff --git a/lib/dns/rdata/generic/cdnskey_60.c b/lib/dns/rdata/generic/cdnskey_60.c
new file mode 100644
index 0000000..3da66d6
--- /dev/null
+++ b/lib/dns/rdata/generic/cdnskey_60.c
@@ -0,0 +1,164 @@
+/*
+ * 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.
+ */
+
+/* draft-ietf-dnsop-delegation-trust-maintainance-14 */
+
+#ifndef RDATA_GENERIC_CDNSKEY_60_C
+#define RDATA_GENERIC_CDNSKEY_60_C
+
+#include <dst/dst.h>
+
+#define RRTYPE_CDNSKEY_ATTRIBUTES 0
+
+static isc_result_t
+fromtext_cdnskey(ARGS_FROMTEXT) {
+ REQUIRE(type == dns_rdatatype_cdnskey);
+
+ return (generic_fromtext_key(CALL_FROMTEXT));
+}
+
+static isc_result_t
+totext_cdnskey(ARGS_TOTEXT) {
+ REQUIRE(rdata != NULL);
+ REQUIRE(rdata->type == dns_rdatatype_cdnskey);
+
+ return (generic_totext_key(CALL_TOTEXT));
+}
+
+static isc_result_t
+fromwire_cdnskey(ARGS_FROMWIRE) {
+ REQUIRE(type == dns_rdatatype_cdnskey);
+
+ return (generic_fromwire_key(CALL_FROMWIRE));
+}
+
+static isc_result_t
+towire_cdnskey(ARGS_TOWIRE) {
+ isc_region_t sr;
+
+ REQUIRE(rdata->type == dns_rdatatype_cdnskey);
+ REQUIRE(rdata->length != 0);
+
+ UNUSED(cctx);
+
+ dns_rdata_toregion(rdata, &sr);
+ return (mem_tobuffer(target, sr.base, sr.length));
+}
+
+static int
+compare_cdnskey(ARGS_COMPARE) {
+ isc_region_t r1;
+ isc_region_t r2;
+
+ REQUIRE(rdata1 != NULL);
+ REQUIRE(rdata2 != NULL);
+ REQUIRE(rdata1->type == rdata2->type);
+ REQUIRE(rdata1->rdclass == rdata2->rdclass);
+ REQUIRE(rdata1->type == dns_rdatatype_cdnskey);
+ REQUIRE(rdata1->length != 0);
+ REQUIRE(rdata2->length != 0);
+
+ dns_rdata_toregion(rdata1, &r1);
+ dns_rdata_toregion(rdata2, &r2);
+ return (isc_region_compare(&r1, &r2));
+}
+
+static isc_result_t
+fromstruct_cdnskey(ARGS_FROMSTRUCT) {
+ REQUIRE(type == dns_rdatatype_cdnskey);
+
+ return (generic_fromstruct_key(CALL_FROMSTRUCT));
+}
+
+static isc_result_t
+tostruct_cdnskey(ARGS_TOSTRUCT) {
+ dns_rdata_cdnskey_t *dnskey = target;
+
+ REQUIRE(dnskey != NULL);
+ REQUIRE(rdata != NULL);
+ REQUIRE(rdata->type == dns_rdatatype_cdnskey);
+
+ dnskey->common.rdclass = rdata->rdclass;
+ dnskey->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&dnskey->common, link);
+
+ return (generic_tostruct_key(CALL_TOSTRUCT));
+}
+
+static void
+freestruct_cdnskey(ARGS_FREESTRUCT) {
+ dns_rdata_cdnskey_t *dnskey = (dns_rdata_cdnskey_t *)source;
+
+ REQUIRE(dnskey != NULL);
+ REQUIRE(dnskey->common.rdtype == dns_rdatatype_cdnskey);
+
+ generic_freestruct_key(source);
+}
+
+static isc_result_t
+additionaldata_cdnskey(ARGS_ADDLDATA) {
+ REQUIRE(rdata->type == dns_rdatatype_cdnskey);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(add);
+ UNUSED(arg);
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+digest_cdnskey(ARGS_DIGEST) {
+ isc_region_t r;
+
+ REQUIRE(rdata != NULL);
+ REQUIRE(rdata->type == dns_rdatatype_cdnskey);
+
+ dns_rdata_toregion(rdata, &r);
+
+ return ((digest)(arg, &r));
+}
+
+static bool
+checkowner_cdnskey(ARGS_CHECKOWNER) {
+ REQUIRE(type == dns_rdatatype_cdnskey);
+
+ UNUSED(name);
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (true);
+}
+
+static bool
+checknames_cdnskey(ARGS_CHECKNAMES) {
+ REQUIRE(rdata != NULL);
+ REQUIRE(rdata->type == dns_rdatatype_cdnskey);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(bad);
+
+ return (true);
+}
+
+static int
+casecompare_cdnskey(ARGS_COMPARE) {
+ /*
+ * Treat ALG 253 (private DNS) subtype name case sensitively.
+ */
+ return (compare_cdnskey(rdata1, rdata2));
+}
+
+#endif /* RDATA_GENERIC_CDNSKEY_60_C */
diff --git a/lib/dns/rdata/generic/cdnskey_60.h b/lib/dns/rdata/generic/cdnskey_60.h
new file mode 100644
index 0000000..b2c8771
--- /dev/null
+++ b/lib/dns/rdata/generic/cdnskey_60.h
@@ -0,0 +1,17 @@
+/*
+ * 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
+
+/* CDNSKEY records have the same RDATA fields as DNSKEY records. */
+typedef struct dns_rdata_key dns_rdata_cdnskey_t;
diff --git a/lib/dns/rdata/generic/cds_59.c b/lib/dns/rdata/generic/cds_59.c
new file mode 100644
index 0000000..7c64158
--- /dev/null
+++ b/lib/dns/rdata/generic/cds_59.c
@@ -0,0 +1,167 @@
+/*
+ * 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.
+ */
+
+/* draft-ietf-dnsop-delegation-trust-maintainance-14 */
+
+#ifndef RDATA_GENERIC_CDS_59_C
+#define RDATA_GENERIC_CDS_59_C
+
+#define RRTYPE_CDS_ATTRIBUTES 0
+
+#include <dns/ds.h>
+
+static isc_result_t
+fromtext_cds(ARGS_FROMTEXT) {
+ REQUIRE(type == dns_rdatatype_cds);
+
+ return (generic_fromtext_ds(CALL_FROMTEXT));
+}
+
+static isc_result_t
+totext_cds(ARGS_TOTEXT) {
+ REQUIRE(rdata != NULL);
+ REQUIRE(rdata->type == dns_rdatatype_cds);
+
+ return (generic_totext_ds(CALL_TOTEXT));
+}
+
+static isc_result_t
+fromwire_cds(ARGS_FROMWIRE) {
+ REQUIRE(type == dns_rdatatype_cds);
+
+ return (generic_fromwire_ds(CALL_FROMWIRE));
+}
+
+static isc_result_t
+towire_cds(ARGS_TOWIRE) {
+ isc_region_t sr;
+
+ REQUIRE(rdata->type == dns_rdatatype_cds);
+ REQUIRE(rdata->length != 0);
+
+ UNUSED(cctx);
+
+ dns_rdata_toregion(rdata, &sr);
+ return (mem_tobuffer(target, sr.base, sr.length));
+}
+
+static int
+compare_cds(ARGS_COMPARE) {
+ isc_region_t r1;
+ isc_region_t r2;
+
+ REQUIRE(rdata1->type == rdata2->type);
+ REQUIRE(rdata1->rdclass == rdata2->rdclass);
+ REQUIRE(rdata1->type == dns_rdatatype_cds);
+ REQUIRE(rdata1->length != 0);
+ REQUIRE(rdata2->length != 0);
+
+ dns_rdata_toregion(rdata1, &r1);
+ dns_rdata_toregion(rdata2, &r2);
+ return (isc_region_compare(&r1, &r2));
+}
+
+static isc_result_t
+fromstruct_cds(ARGS_FROMSTRUCT) {
+ REQUIRE(type == dns_rdatatype_cds);
+
+ return (generic_fromstruct_ds(CALL_FROMSTRUCT));
+}
+
+static isc_result_t
+tostruct_cds(ARGS_TOSTRUCT) {
+ dns_rdata_cds_t *cds = target;
+
+ REQUIRE(rdata->type == dns_rdatatype_cds);
+ REQUIRE(cds != NULL);
+ REQUIRE(rdata->length != 0);
+
+ /*
+ * Checked by generic_tostruct_ds().
+ */
+ cds->common.rdclass = rdata->rdclass;
+ cds->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&cds->common, link);
+
+ return (generic_tostruct_ds(CALL_TOSTRUCT));
+}
+
+static void
+freestruct_cds(ARGS_FREESTRUCT) {
+ dns_rdata_cds_t *cds = source;
+
+ REQUIRE(cds != NULL);
+ REQUIRE(cds->common.rdtype == dns_rdatatype_cds);
+
+ if (cds->mctx == NULL) {
+ return;
+ }
+
+ if (cds->digest != NULL) {
+ isc_mem_free(cds->mctx, cds->digest);
+ }
+ cds->mctx = NULL;
+}
+
+static isc_result_t
+additionaldata_cds(ARGS_ADDLDATA) {
+ REQUIRE(rdata->type == dns_rdatatype_cds);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(add);
+ UNUSED(arg);
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+digest_cds(ARGS_DIGEST) {
+ isc_region_t r;
+
+ REQUIRE(rdata->type == dns_rdatatype_cds);
+
+ dns_rdata_toregion(rdata, &r);
+
+ return ((digest)(arg, &r));
+}
+
+static bool
+checkowner_cds(ARGS_CHECKOWNER) {
+ REQUIRE(type == dns_rdatatype_cds);
+
+ UNUSED(name);
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (true);
+}
+
+static bool
+checknames_cds(ARGS_CHECKNAMES) {
+ REQUIRE(rdata->type == dns_rdatatype_cds);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(bad);
+
+ return (true);
+}
+
+static int
+casecompare_cds(ARGS_COMPARE) {
+ return (compare_cds(rdata1, rdata2));
+}
+
+#endif /* RDATA_GENERIC_CDS_59_C */
diff --git a/lib/dns/rdata/generic/cds_59.h b/lib/dns/rdata/generic/cds_59.h
new file mode 100644
index 0000000..b5b409a
--- /dev/null
+++ b/lib/dns/rdata/generic/cds_59.h
@@ -0,0 +1,17 @@
+/*
+ * 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
+
+/* CDS records have the same RDATA fields as DS records. */
+typedef struct dns_rdata_ds dns_rdata_cds_t;
diff --git a/lib/dns/rdata/generic/cert_37.c b/lib/dns/rdata/generic/cert_37.c
new file mode 100644
index 0000000..eb307a7
--- /dev/null
+++ b/lib/dns/rdata/generic/cert_37.c
@@ -0,0 +1,285 @@
+/*
+ * 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.
+ */
+
+/* RFC2538 */
+
+#ifndef RDATA_GENERIC_CERT_37_C
+#define RDATA_GENERIC_CERT_37_C
+
+#define RRTYPE_CERT_ATTRIBUTES (0)
+
+static isc_result_t
+fromtext_cert(ARGS_FROMTEXT) {
+ isc_token_t token;
+ dns_secalg_t secalg;
+ dns_cert_t cert;
+
+ REQUIRE(type == dns_rdatatype_cert);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(origin);
+ UNUSED(options);
+ UNUSED(callbacks);
+
+ /*
+ * Cert type.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ false));
+ RETTOK(dns_cert_fromtext(&cert, &token.value.as_textregion));
+ RETERR(uint16_tobuffer(cert, target));
+
+ /*
+ * Key tag.
+ */
+ 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));
+
+ /*
+ * Algorithm.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ false));
+ RETTOK(dns_secalg_fromtext(&secalg, &token.value.as_textregion));
+ RETERR(mem_tobuffer(target, &secalg, 1));
+
+ return (isc_base64_tobuffer(lexer, target, -2));
+}
+
+static isc_result_t
+totext_cert(ARGS_TOTEXT) {
+ isc_region_t sr;
+ char buf[sizeof("64000 ")];
+ unsigned int n;
+
+ REQUIRE(rdata->type == dns_rdatatype_cert);
+ REQUIRE(rdata->length != 0);
+
+ UNUSED(tctx);
+
+ dns_rdata_toregion(rdata, &sr);
+
+ /*
+ * Type.
+ */
+ n = uint16_fromregion(&sr);
+ isc_region_consume(&sr, 2);
+ RETERR(dns_cert_totext((dns_cert_t)n, target));
+ RETERR(str_totext(" ", target));
+
+ /*
+ * Key tag.
+ */
+ n = uint16_fromregion(&sr);
+ isc_region_consume(&sr, 2);
+ snprintf(buf, sizeof(buf), "%u ", n);
+ RETERR(str_totext(buf, target));
+
+ /*
+ * Algorithm.
+ */
+ RETERR(dns_secalg_totext(sr.base[0], target));
+ isc_region_consume(&sr, 1);
+
+ /*
+ * Cert.
+ */
+ if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) {
+ RETERR(str_totext(" (", target));
+ }
+ RETERR(str_totext(tctx->linebreak, target));
+ if (tctx->width == 0) { /* No splitting */
+ RETERR(isc_base64_totext(&sr, 60, "", target));
+ } else {
+ RETERR(isc_base64_totext(&sr, tctx->width - 2, tctx->linebreak,
+ target));
+ }
+ if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) {
+ RETERR(str_totext(" )", target));
+ }
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+fromwire_cert(ARGS_FROMWIRE) {
+ isc_region_t sr;
+
+ REQUIRE(type == dns_rdatatype_cert);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(dctx);
+ UNUSED(options);
+
+ isc_buffer_activeregion(source, &sr);
+ if (sr.length < 6) {
+ return (ISC_R_UNEXPECTEDEND);
+ }
+
+ isc_buffer_forward(source, sr.length);
+ return (mem_tobuffer(target, sr.base, sr.length));
+}
+
+static isc_result_t
+towire_cert(ARGS_TOWIRE) {
+ isc_region_t sr;
+
+ REQUIRE(rdata->type == dns_rdatatype_cert);
+ REQUIRE(rdata->length != 0);
+
+ UNUSED(cctx);
+
+ dns_rdata_toregion(rdata, &sr);
+ return (mem_tobuffer(target, sr.base, sr.length));
+}
+
+static int
+compare_cert(ARGS_COMPARE) {
+ isc_region_t r1;
+ isc_region_t r2;
+
+ REQUIRE(rdata1->type == rdata2->type);
+ REQUIRE(rdata1->rdclass == rdata2->rdclass);
+ REQUIRE(rdata1->type == dns_rdatatype_cert);
+ REQUIRE(rdata1->length != 0);
+ REQUIRE(rdata2->length != 0);
+
+ dns_rdata_toregion(rdata1, &r1);
+ dns_rdata_toregion(rdata2, &r2);
+ return (isc_region_compare(&r1, &r2));
+}
+
+static isc_result_t
+fromstruct_cert(ARGS_FROMSTRUCT) {
+ dns_rdata_cert_t *cert = source;
+
+ REQUIRE(type == dns_rdatatype_cert);
+ REQUIRE(cert != NULL);
+ REQUIRE(cert->common.rdtype == type);
+ REQUIRE(cert->common.rdclass == rdclass);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ RETERR(uint16_tobuffer(cert->type, target));
+ RETERR(uint16_tobuffer(cert->key_tag, target));
+ RETERR(uint8_tobuffer(cert->algorithm, target));
+
+ return (mem_tobuffer(target, cert->certificate, cert->length));
+}
+
+static isc_result_t
+tostruct_cert(ARGS_TOSTRUCT) {
+ dns_rdata_cert_t *cert = target;
+ isc_region_t region;
+
+ REQUIRE(rdata->type == dns_rdatatype_cert);
+ REQUIRE(cert != NULL);
+ REQUIRE(rdata->length != 0);
+
+ cert->common.rdclass = rdata->rdclass;
+ cert->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&cert->common, link);
+
+ dns_rdata_toregion(rdata, &region);
+
+ cert->type = uint16_fromregion(&region);
+ isc_region_consume(&region, 2);
+ cert->key_tag = uint16_fromregion(&region);
+ isc_region_consume(&region, 2);
+ cert->algorithm = uint8_fromregion(&region);
+ isc_region_consume(&region, 1);
+ cert->length = region.length;
+
+ cert->certificate = mem_maybedup(mctx, region.base, region.length);
+ if (cert->certificate == NULL) {
+ return (ISC_R_NOMEMORY);
+ }
+
+ cert->mctx = mctx;
+ return (ISC_R_SUCCESS);
+}
+
+static void
+freestruct_cert(ARGS_FREESTRUCT) {
+ dns_rdata_cert_t *cert = source;
+
+ REQUIRE(cert != NULL);
+ REQUIRE(cert->common.rdtype == dns_rdatatype_cert);
+
+ if (cert->mctx == NULL) {
+ return;
+ }
+
+ if (cert->certificate != NULL) {
+ isc_mem_free(cert->mctx, cert->certificate);
+ }
+ cert->mctx = NULL;
+}
+
+static isc_result_t
+additionaldata_cert(ARGS_ADDLDATA) {
+ REQUIRE(rdata->type == dns_rdatatype_cert);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(add);
+ UNUSED(arg);
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+digest_cert(ARGS_DIGEST) {
+ isc_region_t r;
+
+ REQUIRE(rdata->type == dns_rdatatype_cert);
+
+ dns_rdata_toregion(rdata, &r);
+
+ return ((digest)(arg, &r));
+}
+
+static bool
+checkowner_cert(ARGS_CHECKOWNER) {
+ REQUIRE(type == dns_rdatatype_cert);
+
+ UNUSED(name);
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (true);
+}
+
+static bool
+checknames_cert(ARGS_CHECKNAMES) {
+ REQUIRE(rdata->type == dns_rdatatype_cert);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(bad);
+
+ return (true);
+}
+
+static int
+casecompare_cert(ARGS_COMPARE) {
+ return (compare_cert(rdata1, rdata2));
+}
+#endif /* RDATA_GENERIC_CERT_37_C */
diff --git a/lib/dns/rdata/generic/cert_37.h b/lib/dns/rdata/generic/cert_37.h
new file mode 100644
index 0000000..a905a2b
--- /dev/null
+++ b/lib/dns/rdata/generic/cert_37.h
@@ -0,0 +1,25 @@
+/*
+ * 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
+
+/*% RFC2538 */
+typedef struct dns_rdata_cert {
+ dns_rdatacommon_t common;
+ isc_mem_t *mctx;
+ uint16_t type;
+ uint16_t key_tag;
+ uint8_t algorithm;
+ uint16_t length;
+ unsigned char *certificate;
+} dns_rdata_cert_t;
diff --git a/lib/dns/rdata/generic/cname_5.c b/lib/dns/rdata/generic/cname_5.c
new file mode 100644
index 0000000..f3f9378
--- /dev/null
+++ b/lib/dns/rdata/generic/cname_5.c
@@ -0,0 +1,231 @@
+/*
+ * 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_CNAME_5_C
+#define RDATA_GENERIC_CNAME_5_C
+
+#define RRTYPE_CNAME_ATTRIBUTES \
+ (DNS_RDATATYPEATTR_EXCLUSIVE | DNS_RDATATYPEATTR_SINGLETON)
+
+static isc_result_t
+fromtext_cname(ARGS_FROMTEXT) {
+ isc_token_t token;
+ dns_name_t name;
+ isc_buffer_t buffer;
+
+ REQUIRE(type == dns_rdatatype_cname);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(callbacks);
+
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ false));
+
+ dns_name_init(&name, NULL);
+ buffer_fromregion(&buffer, &token.value.as_region);
+ if (origin == NULL) {
+ origin = dns_rootname;
+ }
+ RETTOK(dns_name_fromtext(&name, &buffer, origin, options, target));
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+totext_cname(ARGS_TOTEXT) {
+ isc_region_t region;
+ dns_name_t name;
+ dns_name_t prefix;
+ bool sub;
+
+ REQUIRE(rdata->type == dns_rdatatype_cname);
+ REQUIRE(rdata->length != 0);
+
+ dns_name_init(&name, NULL);
+ dns_name_init(&prefix, NULL);
+
+ dns_rdata_toregion(rdata, &region);
+ dns_name_fromregion(&name, &region);
+
+ sub = name_prefix(&name, tctx->origin, &prefix);
+
+ return (dns_name_totext(&prefix, sub, target));
+}
+
+static isc_result_t
+fromwire_cname(ARGS_FROMWIRE) {
+ dns_name_t name;
+
+ REQUIRE(type == dns_rdatatype_cname);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ dns_decompress_setmethods(dctx, DNS_COMPRESS_GLOBAL14);
+
+ dns_name_init(&name, NULL);
+ return (dns_name_fromwire(&name, source, dctx, options, target));
+}
+
+static isc_result_t
+towire_cname(ARGS_TOWIRE) {
+ dns_name_t name;
+ dns_offsets_t offsets;
+ isc_region_t region;
+
+ REQUIRE(rdata->type == dns_rdatatype_cname);
+ REQUIRE(rdata->length != 0);
+
+ dns_compress_setmethods(cctx, DNS_COMPRESS_GLOBAL14);
+
+ dns_name_init(&name, offsets);
+ dns_rdata_toregion(rdata, &region);
+ dns_name_fromregion(&name, &region);
+
+ return (dns_name_towire(&name, cctx, target));
+}
+
+static int
+compare_cname(ARGS_COMPARE) {
+ dns_name_t name1;
+ dns_name_t name2;
+ isc_region_t region1;
+ isc_region_t region2;
+
+ REQUIRE(rdata1->type == rdata2->type);
+ REQUIRE(rdata1->rdclass == rdata2->rdclass);
+ REQUIRE(rdata1->type == dns_rdatatype_cname);
+ REQUIRE(rdata1->length != 0);
+ REQUIRE(rdata2->length != 0);
+
+ dns_name_init(&name1, NULL);
+ dns_name_init(&name2, NULL);
+
+ dns_rdata_toregion(rdata1, &region1);
+ dns_rdata_toregion(rdata2, &region2);
+
+ dns_name_fromregion(&name1, &region1);
+ dns_name_fromregion(&name2, &region2);
+
+ return (dns_name_rdatacompare(&name1, &name2));
+}
+
+static isc_result_t
+fromstruct_cname(ARGS_FROMSTRUCT) {
+ dns_rdata_cname_t *cname = source;
+ isc_region_t region;
+
+ REQUIRE(type == dns_rdatatype_cname);
+ REQUIRE(cname != NULL);
+ REQUIRE(cname->common.rdtype == type);
+ REQUIRE(cname->common.rdclass == rdclass);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ dns_name_toregion(&cname->cname, &region);
+ return (isc_buffer_copyregion(target, &region));
+}
+
+static isc_result_t
+tostruct_cname(ARGS_TOSTRUCT) {
+ isc_region_t region;
+ dns_rdata_cname_t *cname = target;
+ dns_name_t name;
+
+ REQUIRE(rdata->type == dns_rdatatype_cname);
+ REQUIRE(cname != NULL);
+ REQUIRE(rdata->length != 0);
+
+ cname->common.rdclass = rdata->rdclass;
+ cname->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&cname->common, link);
+
+ dns_name_init(&name, NULL);
+ dns_rdata_toregion(rdata, &region);
+ dns_name_fromregion(&name, &region);
+ dns_name_init(&cname->cname, NULL);
+ name_duporclone(&name, mctx, &cname->cname);
+ cname->mctx = mctx;
+ return (ISC_R_SUCCESS);
+}
+
+static void
+freestruct_cname(ARGS_FREESTRUCT) {
+ dns_rdata_cname_t *cname = source;
+
+ REQUIRE(cname != NULL);
+
+ if (cname->mctx == NULL) {
+ return;
+ }
+
+ dns_name_free(&cname->cname, cname->mctx);
+ cname->mctx = NULL;
+}
+
+static isc_result_t
+additionaldata_cname(ARGS_ADDLDATA) {
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(add);
+ UNUSED(arg);
+
+ REQUIRE(rdata->type == dns_rdatatype_cname);
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+digest_cname(ARGS_DIGEST) {
+ isc_region_t r;
+ dns_name_t name;
+
+ REQUIRE(rdata->type == dns_rdatatype_cname);
+
+ dns_rdata_toregion(rdata, &r);
+ dns_name_init(&name, NULL);
+ dns_name_fromregion(&name, &r);
+
+ return (dns_name_digest(&name, digest, arg));
+}
+
+static bool
+checkowner_cname(ARGS_CHECKOWNER) {
+ REQUIRE(type == dns_rdatatype_cname);
+
+ UNUSED(name);
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (true);
+}
+
+static bool
+checknames_cname(ARGS_CHECKNAMES) {
+ REQUIRE(rdata->type == dns_rdatatype_cname);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(bad);
+
+ return (true);
+}
+
+static int
+casecompare_cname(ARGS_COMPARE) {
+ return (compare_cname(rdata1, rdata2));
+}
+
+#endif /* RDATA_GENERIC_CNAME_5_C */
diff --git a/lib/dns/rdata/generic/cname_5.h b/lib/dns/rdata/generic/cname_5.h
new file mode 100644
index 0000000..1525fa0
--- /dev/null
+++ b/lib/dns/rdata/generic/cname_5.h
@@ -0,0 +1,20 @@
+/*
+ * 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_cname {
+ dns_rdatacommon_t common;
+ isc_mem_t *mctx;
+ dns_name_t cname;
+} dns_rdata_cname_t;
diff --git a/lib/dns/rdata/generic/csync_62.c b/lib/dns/rdata/generic/csync_62.c
new file mode 100644
index 0000000..285f22b
--- /dev/null
+++ b/lib/dns/rdata/generic/csync_62.c
@@ -0,0 +1,274 @@
+/*
+ * 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.
+ */
+
+/* RFC 7477 */
+
+#ifndef RDATA_GENERIC_CSYNC_62_C
+#define RDATA_GENERIC_CSYNC_62_C
+
+#define RRTYPE_CSYNC_ATTRIBUTES 0
+
+static isc_result_t
+fromtext_csync(ARGS_FROMTEXT) {
+ isc_token_t token;
+
+ REQUIRE(type == dns_rdatatype_csync);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(origin);
+ UNUSED(options);
+ UNUSED(callbacks);
+
+ /* Serial. */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
+ false));
+ RETERR(uint32_tobuffer(token.value.as_ulong, target));
+
+ /* Flags. */
+ 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));
+
+ /* Type Map */
+ return (typemap_fromtext(lexer, target, true));
+}
+
+static isc_result_t
+totext_csync(ARGS_TOTEXT) {
+ unsigned long num;
+ char buf[sizeof("0123456789")]; /* Also TYPE65535 */
+ isc_region_t sr;
+
+ REQUIRE(rdata->type == dns_rdatatype_csync);
+ REQUIRE(rdata->length >= 6);
+
+ UNUSED(tctx);
+
+ dns_rdata_toregion(rdata, &sr);
+
+ num = uint32_fromregion(&sr);
+ isc_region_consume(&sr, 4);
+ snprintf(buf, sizeof(buf), "%lu", num);
+ RETERR(str_totext(buf, target));
+
+ RETERR(str_totext(" ", target));
+
+ num = uint16_fromregion(&sr);
+ isc_region_consume(&sr, 2);
+ snprintf(buf, sizeof(buf), "%lu", num);
+ RETERR(str_totext(buf, target));
+
+ /*
+ * Don't leave a trailing space when there's no typemap present.
+ */
+ if (sr.length > 0) {
+ RETERR(str_totext(" ", target));
+ }
+ return (typemap_totext(&sr, NULL, target));
+}
+
+static isc_result_t
+fromwire_csync(ARGS_FROMWIRE) {
+ isc_region_t sr;
+
+ REQUIRE(type == dns_rdatatype_csync);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(options);
+ UNUSED(dctx);
+
+ /*
+ * Serial + Flags
+ */
+ isc_buffer_activeregion(source, &sr);
+ if (sr.length < 6) {
+ return (ISC_R_UNEXPECTEDEND);
+ }
+
+ RETERR(mem_tobuffer(target, sr.base, 6));
+ isc_buffer_forward(source, 6);
+ isc_region_consume(&sr, 6);
+
+ RETERR(typemap_test(&sr, true));
+
+ RETERR(mem_tobuffer(target, sr.base, sr.length));
+ isc_buffer_forward(source, sr.length);
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+towire_csync(ARGS_TOWIRE) {
+ REQUIRE(rdata->type == dns_rdatatype_csync);
+ REQUIRE(rdata->length >= 6);
+
+ UNUSED(cctx);
+
+ return (mem_tobuffer(target, rdata->data, rdata->length));
+}
+
+static int
+compare_csync(ARGS_COMPARE) {
+ isc_region_t r1;
+ isc_region_t r2;
+
+ REQUIRE(rdata1->type == rdata2->type);
+ REQUIRE(rdata1->rdclass == rdata2->rdclass);
+ REQUIRE(rdata1->type == dns_rdatatype_csync);
+ REQUIRE(rdata1->length >= 6);
+ REQUIRE(rdata2->length >= 6);
+
+ dns_rdata_toregion(rdata1, &r1);
+ dns_rdata_toregion(rdata2, &r2);
+ return (isc_region_compare(&r1, &r2));
+}
+
+static isc_result_t
+fromstruct_csync(ARGS_FROMSTRUCT) {
+ dns_rdata_csync_t *csync = source;
+ isc_region_t region;
+
+ REQUIRE(type == dns_rdatatype_csync);
+ REQUIRE(csync != NULL);
+ REQUIRE(csync->common.rdtype == type);
+ REQUIRE(csync->common.rdclass == rdclass);
+ REQUIRE(csync->typebits != NULL || csync->len == 0);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ RETERR(uint32_tobuffer(csync->serial, target));
+ RETERR(uint16_tobuffer(csync->flags, target));
+
+ region.base = csync->typebits;
+ region.length = csync->len;
+ RETERR(typemap_test(&region, true));
+ return (mem_tobuffer(target, csync->typebits, csync->len));
+}
+
+static isc_result_t
+tostruct_csync(ARGS_TOSTRUCT) {
+ isc_region_t region;
+ dns_rdata_csync_t *csync = target;
+
+ REQUIRE(rdata->type == dns_rdatatype_csync);
+ REQUIRE(csync != NULL);
+ REQUIRE(rdata->length != 0);
+
+ csync->common.rdclass = rdata->rdclass;
+ csync->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&csync->common, link);
+
+ dns_rdata_toregion(rdata, &region);
+
+ csync->serial = uint32_fromregion(&region);
+ isc_region_consume(&region, 4);
+
+ csync->flags = uint16_fromregion(&region);
+ isc_region_consume(&region, 2);
+
+ csync->len = region.length;
+ csync->typebits = mem_maybedup(mctx, region.base, region.length);
+ if (csync->typebits == NULL) {
+ goto cleanup;
+ }
+
+ csync->mctx = mctx;
+ return (ISC_R_SUCCESS);
+
+cleanup:
+ return (ISC_R_NOMEMORY);
+}
+
+static void
+freestruct_csync(ARGS_FREESTRUCT) {
+ dns_rdata_csync_t *csync = source;
+
+ REQUIRE(csync != NULL);
+ REQUIRE(csync->common.rdtype == dns_rdatatype_csync);
+
+ if (csync->mctx == NULL) {
+ return;
+ }
+
+ if (csync->typebits != NULL) {
+ isc_mem_free(csync->mctx, csync->typebits);
+ }
+ csync->mctx = NULL;
+}
+
+static isc_result_t
+additionaldata_csync(ARGS_ADDLDATA) {
+ REQUIRE(rdata->type == dns_rdatatype_csync);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(add);
+ UNUSED(arg);
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+digest_csync(ARGS_DIGEST) {
+ isc_region_t r;
+
+ REQUIRE(rdata->type == dns_rdatatype_csync);
+
+ dns_rdata_toregion(rdata, &r);
+ return ((digest)(arg, &r));
+}
+
+static bool
+checkowner_csync(ARGS_CHECKOWNER) {
+ REQUIRE(type == dns_rdatatype_csync);
+
+ UNUSED(name);
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (true);
+}
+
+static bool
+checknames_csync(ARGS_CHECKNAMES) {
+ REQUIRE(rdata->type == dns_rdatatype_csync);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(bad);
+
+ return (true);
+}
+
+static int
+casecompare_csync(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_csync);
+ REQUIRE(rdata1->length >= 6);
+ REQUIRE(rdata2->length >= 6);
+
+ dns_rdata_toregion(rdata1, &region1);
+ dns_rdata_toregion(rdata2, &region2);
+ return (isc_region_compare(&region1, &region2));
+}
+#endif /* RDATA_GENERIC_CSYNC_62_C */
diff --git a/lib/dns/rdata/generic/csync_62.h b/lib/dns/rdata/generic/csync_62.h
new file mode 100644
index 0000000..a7b3c1e
--- /dev/null
+++ b/lib/dns/rdata/generic/csync_62.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
+
+/*!
+ * \brief Per RFC 7477
+ */
+
+typedef struct dns_rdata_csync {
+ dns_rdatacommon_t common;
+ isc_mem_t *mctx;
+ uint32_t serial;
+ uint16_t flags;
+ unsigned char *typebits;
+ uint16_t len;
+} dns_rdata_csync_t;
diff --git a/lib/dns/rdata/generic/dlv_32769.c b/lib/dns/rdata/generic/dlv_32769.c
new file mode 100644
index 0000000..faf9500
--- /dev/null
+++ b/lib/dns/rdata/generic/dlv_32769.c
@@ -0,0 +1,163 @@
+/*
+ * 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.
+ */
+
+/* RFC3658 */
+
+#ifndef RDATA_GENERIC_DLV_32769_C
+#define RDATA_GENERIC_DLV_32769_C
+
+#define RRTYPE_DLV_ATTRIBUTES 0
+
+#include <dns/ds.h>
+
+static isc_result_t
+fromtext_dlv(ARGS_FROMTEXT) {
+ REQUIRE(type == dns_rdatatype_dlv);
+
+ return (generic_fromtext_ds(CALL_FROMTEXT));
+}
+
+static isc_result_t
+totext_dlv(ARGS_TOTEXT) {
+ REQUIRE(rdata != NULL);
+ REQUIRE(rdata->type == dns_rdatatype_dlv);
+
+ return (generic_totext_ds(CALL_TOTEXT));
+}
+
+static isc_result_t
+fromwire_dlv(ARGS_FROMWIRE) {
+ REQUIRE(type == dns_rdatatype_dlv);
+
+ return (generic_fromwire_ds(CALL_FROMWIRE));
+}
+
+static isc_result_t
+towire_dlv(ARGS_TOWIRE) {
+ isc_region_t sr;
+
+ REQUIRE(rdata->type == dns_rdatatype_dlv);
+ REQUIRE(rdata->length != 0);
+
+ UNUSED(cctx);
+
+ dns_rdata_toregion(rdata, &sr);
+ return (mem_tobuffer(target, sr.base, sr.length));
+}
+
+static int
+compare_dlv(ARGS_COMPARE) {
+ isc_region_t r1;
+ isc_region_t r2;
+
+ REQUIRE(rdata1->type == rdata2->type);
+ REQUIRE(rdata1->rdclass == rdata2->rdclass);
+ REQUIRE(rdata1->type == dns_rdatatype_dlv);
+ REQUIRE(rdata1->length != 0);
+ REQUIRE(rdata2->length != 0);
+
+ dns_rdata_toregion(rdata1, &r1);
+ dns_rdata_toregion(rdata2, &r2);
+ return (isc_region_compare(&r1, &r2));
+}
+
+static isc_result_t
+fromstruct_dlv(ARGS_FROMSTRUCT) {
+ REQUIRE(type == dns_rdatatype_dlv);
+
+ return (generic_fromstruct_ds(CALL_FROMSTRUCT));
+}
+
+static isc_result_t
+tostruct_dlv(ARGS_TOSTRUCT) {
+ dns_rdata_dlv_t *dlv = target;
+
+ REQUIRE(rdata->type == dns_rdatatype_dlv);
+ REQUIRE(dlv != NULL);
+
+ dlv->common.rdclass = rdata->rdclass;
+ dlv->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&dlv->common, link);
+
+ return (generic_tostruct_ds(CALL_TOSTRUCT));
+}
+
+static void
+freestruct_dlv(ARGS_FREESTRUCT) {
+ dns_rdata_dlv_t *dlv = source;
+
+ REQUIRE(dlv != NULL);
+ REQUIRE(dlv->common.rdtype == dns_rdatatype_dlv);
+
+ if (dlv->mctx == NULL) {
+ return;
+ }
+
+ if (dlv->digest != NULL) {
+ isc_mem_free(dlv->mctx, dlv->digest);
+ }
+ dlv->mctx = NULL;
+}
+
+static isc_result_t
+additionaldata_dlv(ARGS_ADDLDATA) {
+ REQUIRE(rdata->type == dns_rdatatype_dlv);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(add);
+ UNUSED(arg);
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+digest_dlv(ARGS_DIGEST) {
+ isc_region_t r;
+
+ REQUIRE(rdata->type == dns_rdatatype_dlv);
+
+ dns_rdata_toregion(rdata, &r);
+
+ return ((digest)(arg, &r));
+}
+
+static bool
+checkowner_dlv(ARGS_CHECKOWNER) {
+ REQUIRE(type == dns_rdatatype_dlv);
+
+ UNUSED(name);
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (true);
+}
+
+static bool
+checknames_dlv(ARGS_CHECKNAMES) {
+ REQUIRE(rdata->type == dns_rdatatype_dlv);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(bad);
+
+ return (true);
+}
+
+static int
+casecompare_dlv(ARGS_COMPARE) {
+ return (compare_dlv(rdata1, rdata2));
+}
+
+#endif /* RDATA_GENERIC_DLV_32769_C */
diff --git a/lib/dns/rdata/generic/dlv_32769.h b/lib/dns/rdata/generic/dlv_32769.h
new file mode 100644
index 0000000..ec3709f
--- /dev/null
+++ b/lib/dns/rdata/generic/dlv_32769.h
@@ -0,0 +1,17 @@
+/*
+ * 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.
+ */
+
+/* draft-ietf-dnsext-delegation-signer-05.txt */
+#pragma once
+
+typedef struct dns_rdata_ds dns_rdata_dlv_t;
diff --git a/lib/dns/rdata/generic/dname_39.c b/lib/dns/rdata/generic/dname_39.c
new file mode 100644
index 0000000..2eb1dc8
--- /dev/null
+++ b/lib/dns/rdata/generic/dname_39.c
@@ -0,0 +1,231 @@
+/*
+ * 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.
+ */
+
+/* RFC2672 */
+
+#ifndef RDATA_GENERIC_DNAME_39_C
+#define RDATA_GENERIC_DNAME_39_C
+
+#define RRTYPE_DNAME_ATTRIBUTES (DNS_RDATATYPEATTR_SINGLETON)
+
+static isc_result_t
+fromtext_dname(ARGS_FROMTEXT) {
+ isc_token_t token;
+ dns_name_t name;
+ isc_buffer_t buffer;
+
+ REQUIRE(type == dns_rdatatype_dname);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(callbacks);
+
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ false));
+
+ dns_name_init(&name, NULL);
+ buffer_fromregion(&buffer, &token.value.as_region);
+ if (origin == NULL) {
+ origin = dns_rootname;
+ }
+ RETTOK(dns_name_fromtext(&name, &buffer, origin, options, target));
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+totext_dname(ARGS_TOTEXT) {
+ isc_region_t region;
+ dns_name_t name;
+ dns_name_t prefix;
+ bool sub;
+
+ REQUIRE(rdata->type == dns_rdatatype_dname);
+ REQUIRE(rdata->length != 0);
+
+ dns_name_init(&name, NULL);
+ dns_name_init(&prefix, NULL);
+
+ dns_rdata_toregion(rdata, &region);
+ dns_name_fromregion(&name, &region);
+
+ sub = name_prefix(&name, tctx->origin, &prefix);
+
+ return (dns_name_totext(&prefix, sub, target));
+}
+
+static isc_result_t
+fromwire_dname(ARGS_FROMWIRE) {
+ dns_name_t name;
+
+ REQUIRE(type == dns_rdatatype_dname);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ dns_decompress_setmethods(dctx, DNS_COMPRESS_NONE);
+
+ dns_name_init(&name, NULL);
+ return (dns_name_fromwire(&name, source, dctx, options, target));
+}
+
+static isc_result_t
+towire_dname(ARGS_TOWIRE) {
+ dns_name_t name;
+ dns_offsets_t offsets;
+ isc_region_t region;
+
+ REQUIRE(rdata->type == dns_rdatatype_dname);
+ REQUIRE(rdata->length != 0);
+
+ dns_compress_setmethods(cctx, DNS_COMPRESS_NONE);
+ dns_name_init(&name, offsets);
+ dns_rdata_toregion(rdata, &region);
+ dns_name_fromregion(&name, &region);
+
+ return (dns_name_towire(&name, cctx, target));
+}
+
+static int
+compare_dname(ARGS_COMPARE) {
+ dns_name_t name1;
+ dns_name_t name2;
+ isc_region_t region1;
+ isc_region_t region2;
+
+ REQUIRE(rdata1->type == rdata2->type);
+ REQUIRE(rdata1->rdclass == rdata2->rdclass);
+ REQUIRE(rdata1->type == dns_rdatatype_dname);
+ REQUIRE(rdata1->length != 0);
+ REQUIRE(rdata2->length != 0);
+
+ dns_name_init(&name1, NULL);
+ dns_name_init(&name2, NULL);
+
+ dns_rdata_toregion(rdata1, &region1);
+ dns_rdata_toregion(rdata2, &region2);
+
+ dns_name_fromregion(&name1, &region1);
+ dns_name_fromregion(&name2, &region2);
+
+ return (dns_name_rdatacompare(&name1, &name2));
+}
+
+static isc_result_t
+fromstruct_dname(ARGS_FROMSTRUCT) {
+ dns_rdata_dname_t *dname = source;
+ isc_region_t region;
+
+ REQUIRE(type == dns_rdatatype_dname);
+ REQUIRE(dname != NULL);
+ REQUIRE(dname->common.rdtype == type);
+ REQUIRE(dname->common.rdclass == rdclass);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ dns_name_toregion(&dname->dname, &region);
+ return (isc_buffer_copyregion(target, &region));
+}
+
+static isc_result_t
+tostruct_dname(ARGS_TOSTRUCT) {
+ isc_region_t region;
+ dns_rdata_dname_t *dname = target;
+ dns_name_t name;
+
+ REQUIRE(rdata->type == dns_rdatatype_dname);
+ REQUIRE(dname != NULL);
+ REQUIRE(rdata->length != 0);
+
+ dname->common.rdclass = rdata->rdclass;
+ dname->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&dname->common, link);
+
+ dns_name_init(&name, NULL);
+ dns_rdata_toregion(rdata, &region);
+ dns_name_fromregion(&name, &region);
+ dns_name_init(&dname->dname, NULL);
+ name_duporclone(&name, mctx, &dname->dname);
+ dname->mctx = mctx;
+ return (ISC_R_SUCCESS);
+}
+
+static void
+freestruct_dname(ARGS_FREESTRUCT) {
+ dns_rdata_dname_t *dname = source;
+
+ REQUIRE(dname != NULL);
+ REQUIRE(dname->common.rdtype == dns_rdatatype_dname);
+
+ if (dname->mctx == NULL) {
+ return;
+ }
+
+ dns_name_free(&dname->dname, dname->mctx);
+ dname->mctx = NULL;
+}
+
+static isc_result_t
+additionaldata_dname(ARGS_ADDLDATA) {
+ REQUIRE(rdata->type == dns_rdatatype_dname);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(add);
+ UNUSED(arg);
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+digest_dname(ARGS_DIGEST) {
+ isc_region_t r;
+ dns_name_t name;
+
+ REQUIRE(rdata->type == dns_rdatatype_dname);
+
+ dns_rdata_toregion(rdata, &r);
+ dns_name_init(&name, NULL);
+ dns_name_fromregion(&name, &r);
+
+ return (dns_name_digest(&name, digest, arg));
+}
+
+static bool
+checkowner_dname(ARGS_CHECKOWNER) {
+ REQUIRE(type == dns_rdatatype_dname);
+
+ UNUSED(name);
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (true);
+}
+
+static bool
+checknames_dname(ARGS_CHECKNAMES) {
+ REQUIRE(rdata->type == dns_rdatatype_dname);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(bad);
+
+ return (true);
+}
+
+static int
+casecompare_dname(ARGS_COMPARE) {
+ return (compare_dname(rdata1, rdata2));
+}
+#endif /* RDATA_GENERIC_DNAME_39_C */
diff --git a/lib/dns/rdata/generic/dname_39.h b/lib/dns/rdata/generic/dname_39.h
new file mode 100644
index 0000000..14c71fb
--- /dev/null
+++ b/lib/dns/rdata/generic/dname_39.h
@@ -0,0 +1,23 @@
+/*
+ * 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
+
+/*!
+ * \brief per RFC2672 */
+
+typedef struct dns_rdata_dname {
+ dns_rdatacommon_t common;
+ isc_mem_t *mctx;
+ dns_name_t dname;
+} dns_rdata_dname_t;
diff --git a/lib/dns/rdata/generic/dnskey_48.c b/lib/dns/rdata/generic/dnskey_48.c
new file mode 100644
index 0000000..2df1e77
--- /dev/null
+++ b/lib/dns/rdata/generic/dnskey_48.c
@@ -0,0 +1,165 @@
+/*
+ * 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.
+ */
+
+/* RFC2535 */
+
+#ifndef RDATA_GENERIC_DNSKEY_48_C
+#define RDATA_GENERIC_DNSKEY_48_C
+
+#include <dst/dst.h>
+
+#define RRTYPE_DNSKEY_ATTRIBUTES (DNS_RDATATYPEATTR_DNSSEC)
+
+static isc_result_t
+fromtext_dnskey(ARGS_FROMTEXT) {
+ REQUIRE(type == dns_rdatatype_dnskey);
+
+ return (generic_fromtext_key(CALL_FROMTEXT));
+}
+
+static isc_result_t
+totext_dnskey(ARGS_TOTEXT) {
+ REQUIRE(rdata != NULL);
+ REQUIRE(rdata->type == dns_rdatatype_dnskey);
+
+ return (generic_totext_key(CALL_TOTEXT));
+}
+
+static isc_result_t
+fromwire_dnskey(ARGS_FROMWIRE) {
+ REQUIRE(type == dns_rdatatype_dnskey);
+
+ return (generic_fromwire_key(CALL_FROMWIRE));
+}
+
+static isc_result_t
+towire_dnskey(ARGS_TOWIRE) {
+ isc_region_t sr;
+
+ REQUIRE(rdata != NULL);
+ REQUIRE(rdata->type == dns_rdatatype_dnskey);
+ REQUIRE(rdata->length != 0);
+
+ UNUSED(cctx);
+
+ dns_rdata_toregion(rdata, &sr);
+ return (mem_tobuffer(target, sr.base, sr.length));
+}
+
+static int
+compare_dnskey(ARGS_COMPARE) {
+ isc_region_t r1;
+ isc_region_t r2;
+
+ REQUIRE(rdata1 != NULL);
+ REQUIRE(rdata2 != NULL);
+ REQUIRE(rdata1->type == rdata2->type);
+ REQUIRE(rdata1->rdclass == rdata2->rdclass);
+ REQUIRE(rdata1->type == dns_rdatatype_dnskey);
+ REQUIRE(rdata1->length != 0);
+ REQUIRE(rdata2->length != 0);
+
+ dns_rdata_toregion(rdata1, &r1);
+ dns_rdata_toregion(rdata2, &r2);
+ return (isc_region_compare(&r1, &r2));
+}
+
+static isc_result_t
+fromstruct_dnskey(ARGS_FROMSTRUCT) {
+ REQUIRE(type == dns_rdatatype_dnskey);
+
+ return (generic_fromstruct_key(CALL_FROMSTRUCT));
+}
+
+static isc_result_t
+tostruct_dnskey(ARGS_TOSTRUCT) {
+ dns_rdata_dnskey_t *dnskey = target;
+
+ REQUIRE(dnskey != NULL);
+ REQUIRE(rdata != NULL);
+ REQUIRE(rdata->type == dns_rdatatype_dnskey);
+
+ dnskey->common.rdclass = rdata->rdclass;
+ dnskey->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&dnskey->common, link);
+
+ return (generic_tostruct_key(CALL_TOSTRUCT));
+}
+
+static void
+freestruct_dnskey(ARGS_FREESTRUCT) {
+ dns_rdata_dnskey_t *dnskey = (dns_rdata_dnskey_t *)source;
+
+ REQUIRE(dnskey != NULL);
+ REQUIRE(dnskey->common.rdtype == dns_rdatatype_dnskey);
+
+ generic_freestruct_key(source);
+}
+
+static isc_result_t
+additionaldata_dnskey(ARGS_ADDLDATA) {
+ REQUIRE(rdata->type == dns_rdatatype_dnskey);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(add);
+ UNUSED(arg);
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+digest_dnskey(ARGS_DIGEST) {
+ isc_region_t r;
+
+ REQUIRE(rdata != NULL);
+ REQUIRE(rdata->type == dns_rdatatype_dnskey);
+
+ dns_rdata_toregion(rdata, &r);
+
+ return ((digest)(arg, &r));
+}
+
+static bool
+checkowner_dnskey(ARGS_CHECKOWNER) {
+ REQUIRE(type == dns_rdatatype_dnskey);
+
+ UNUSED(name);
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (true);
+}
+
+static bool
+checknames_dnskey(ARGS_CHECKNAMES) {
+ REQUIRE(rdata != NULL);
+ REQUIRE(rdata->type == dns_rdatatype_dnskey);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(bad);
+
+ return (true);
+}
+
+static int
+casecompare_dnskey(ARGS_COMPARE) {
+ /*
+ * Treat ALG 253 (private DNS) subtype name case sensitively.
+ */
+ return (compare_dnskey(rdata1, rdata2));
+}
+
+#endif /* RDATA_GENERIC_DNSKEY_48_C */
diff --git a/lib/dns/rdata/generic/dnskey_48.h b/lib/dns/rdata/generic/dnskey_48.h
new file mode 100644
index 0000000..7a0bc6f
--- /dev/null
+++ b/lib/dns/rdata/generic/dnskey_48.h
@@ -0,0 +1,20 @@
+/*
+ * 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
+
+/*!
+ * \brief per RFC2535
+ */
+
+typedef struct dns_rdata_key dns_rdata_dnskey_t;
diff --git a/lib/dns/rdata/generic/doa_259.c b/lib/dns/rdata/generic/doa_259.c
new file mode 100644
index 0000000..45f2439
--- /dev/null
+++ b/lib/dns/rdata/generic/doa_259.c
@@ -0,0 +1,362 @@
+/*
+ * 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_DOA_259_C
+#define RDATA_GENERIC_DOA_259_C
+
+#define RRTYPE_DOA_ATTRIBUTES (0)
+
+static isc_result_t
+fromtext_doa(ARGS_FROMTEXT) {
+ isc_token_t token;
+
+ REQUIRE(type == dns_rdatatype_doa);
+
+ UNUSED(rdclass);
+ UNUSED(origin);
+ UNUSED(options);
+ UNUSED(callbacks);
+
+ /*
+ * DOA-ENTERPRISE
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
+ false));
+ RETERR(uint32_tobuffer(token.value.as_ulong, target));
+
+ /*
+ * DOA-TYPE
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
+ false));
+ RETERR(uint32_tobuffer(token.value.as_ulong, target));
+
+ /*
+ * DOA-LOCATION
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
+ false));
+ if (token.value.as_ulong > 0xffU) {
+ RETTOK(ISC_R_RANGE);
+ }
+ RETERR(uint8_tobuffer(token.value.as_ulong, target));
+
+ /*
+ * DOA-MEDIA-TYPE
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_qstring,
+ false));
+ RETTOK(txt_fromtext(&token.value.as_textregion, target));
+
+ /*
+ * DOA-DATA
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ false));
+ if (strcmp(DNS_AS_STR(token), "-") == 0) {
+ return (ISC_R_SUCCESS);
+ } else {
+ isc_lex_ungettoken(lexer, &token);
+ return (isc_base64_tobuffer(lexer, target, -1));
+ }
+}
+
+static isc_result_t
+totext_doa(ARGS_TOTEXT) {
+ char buf[sizeof("4294967295 ")];
+ isc_region_t region;
+ uint32_t n;
+
+ REQUIRE(rdata != NULL);
+ REQUIRE(rdata->type == dns_rdatatype_doa);
+ REQUIRE(rdata->length != 0);
+
+ UNUSED(tctx);
+
+ dns_rdata_toregion(rdata, &region);
+
+ /*
+ * DOA-ENTERPRISE
+ */
+ n = uint32_fromregion(&region);
+ isc_region_consume(&region, 4);
+ snprintf(buf, sizeof(buf), "%u ", n);
+ RETERR(str_totext(buf, target));
+
+ /*
+ * DOA-TYPE
+ */
+ n = uint32_fromregion(&region);
+ isc_region_consume(&region, 4);
+ snprintf(buf, sizeof(buf), "%u ", n);
+ RETERR(str_totext(buf, target));
+
+ /*
+ * DOA-LOCATION
+ */
+ n = uint8_fromregion(&region);
+ isc_region_consume(&region, 1);
+ snprintf(buf, sizeof(buf), "%u ", n);
+ RETERR(str_totext(buf, target));
+
+ /*
+ * DOA-MEDIA-TYPE
+ */
+ RETERR(txt_totext(&region, true, target));
+ RETERR(str_totext(" ", target));
+
+ /*
+ * DOA-DATA
+ */
+ if (region.length == 0) {
+ return (str_totext("-", target));
+ } else {
+ return (isc_base64_totext(&region, 60, "", target));
+ }
+}
+
+static isc_result_t
+fromwire_doa(ARGS_FROMWIRE) {
+ isc_region_t region;
+
+ UNUSED(rdclass);
+ UNUSED(dctx);
+ UNUSED(options);
+
+ REQUIRE(type == dns_rdatatype_doa);
+
+ isc_buffer_activeregion(source, &region);
+ /*
+ * DOA-MEDIA-TYPE may be an empty <character-string> (i.e.,
+ * comprising of just the length octet) and DOA-DATA can have
+ * zero length.
+ */
+ if (region.length < 4 + 4 + 1 + 1) {
+ return (ISC_R_UNEXPECTEDEND);
+ }
+
+ /*
+ * Check whether DOA-MEDIA-TYPE length is not malformed.
+ */
+ if (region.base[9] > region.length - 10) {
+ return (ISC_R_UNEXPECTEDEND);
+ }
+
+ isc_buffer_forward(source, region.length);
+ return (mem_tobuffer(target, region.base, region.length));
+}
+
+static isc_result_t
+towire_doa(ARGS_TOWIRE) {
+ isc_region_t region;
+
+ UNUSED(cctx);
+
+ REQUIRE(rdata != NULL);
+ REQUIRE(rdata->type == dns_rdatatype_doa);
+ REQUIRE(rdata->length != 0);
+
+ dns_rdata_toregion(rdata, &region);
+ return (mem_tobuffer(target, region.base, region.length));
+}
+
+static int
+compare_doa(ARGS_COMPARE) {
+ isc_region_t r1;
+ isc_region_t r2;
+
+ REQUIRE(rdata1 != NULL);
+ REQUIRE(rdata2 != NULL);
+ REQUIRE(rdata1->type == rdata2->type);
+ REQUIRE(rdata1->type == dns_rdatatype_doa);
+ REQUIRE(rdata1->rdclass == rdata2->rdclass);
+ REQUIRE(rdata1->length != 0);
+ REQUIRE(rdata2->length != 0);
+
+ dns_rdata_toregion(rdata1, &r1);
+ dns_rdata_toregion(rdata2, &r2);
+ return (isc_region_compare(&r1, &r2));
+}
+
+static isc_result_t
+fromstruct_doa(ARGS_FROMSTRUCT) {
+ dns_rdata_doa_t *doa = source;
+
+ REQUIRE(type == dns_rdatatype_doa);
+ REQUIRE(doa != NULL);
+ REQUIRE(doa->common.rdtype == dns_rdatatype_doa);
+ REQUIRE(doa->common.rdclass == rdclass);
+
+ RETERR(uint32_tobuffer(doa->enterprise, target));
+ RETERR(uint32_tobuffer(doa->type, target));
+ RETERR(uint8_tobuffer(doa->location, target));
+ RETERR(uint8_tobuffer(doa->mediatype_len, target));
+ RETERR(mem_tobuffer(target, doa->mediatype, doa->mediatype_len));
+ return (mem_tobuffer(target, doa->data, doa->data_len));
+}
+
+static isc_result_t
+tostruct_doa(ARGS_TOSTRUCT) {
+ dns_rdata_doa_t *doa = target;
+ isc_region_t region;
+
+ REQUIRE(rdata != NULL);
+ REQUIRE(rdata->type == dns_rdatatype_doa);
+ REQUIRE(doa != NULL);
+ REQUIRE(rdata->length != 0);
+
+ doa->common.rdclass = rdata->rdclass;
+ doa->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&doa->common, link);
+
+ dns_rdata_toregion(rdata, &region);
+
+ /*
+ * DOA-ENTERPRISE
+ */
+ if (region.length < 4) {
+ return (ISC_R_UNEXPECTEDEND);
+ }
+ doa->enterprise = uint32_fromregion(&region);
+ isc_region_consume(&region, 4);
+
+ /*
+ * DOA-TYPE
+ */
+ if (region.length < 4) {
+ return (ISC_R_UNEXPECTEDEND);
+ }
+ doa->type = uint32_fromregion(&region);
+ isc_region_consume(&region, 4);
+
+ /*
+ * DOA-LOCATION
+ */
+ if (region.length < 1) {
+ return (ISC_R_UNEXPECTEDEND);
+ }
+ doa->location = uint8_fromregion(&region);
+ isc_region_consume(&region, 1);
+
+ /*
+ * DOA-MEDIA-TYPE
+ */
+ if (region.length < 1) {
+ return (ISC_R_UNEXPECTEDEND);
+ }
+ doa->mediatype_len = uint8_fromregion(&region);
+ isc_region_consume(&region, 1);
+ INSIST(doa->mediatype_len <= region.length);
+ doa->mediatype = mem_maybedup(mctx, region.base, doa->mediatype_len);
+ if (doa->mediatype == NULL) {
+ goto cleanup;
+ }
+ isc_region_consume(&region, doa->mediatype_len);
+
+ /*
+ * DOA-DATA
+ */
+ doa->data_len = region.length;
+ doa->data = NULL;
+ if (doa->data_len > 0) {
+ doa->data = mem_maybedup(mctx, region.base, doa->data_len);
+ if (doa->data == NULL) {
+ goto cleanup;
+ }
+ isc_region_consume(&region, doa->data_len);
+ }
+
+ doa->mctx = mctx;
+
+ return (ISC_R_SUCCESS);
+
+cleanup:
+ if (mctx != NULL && doa->mediatype != NULL) {
+ isc_mem_free(mctx, doa->mediatype);
+ }
+ return (ISC_R_NOMEMORY);
+}
+
+static void
+freestruct_doa(ARGS_FREESTRUCT) {
+ dns_rdata_doa_t *doa = source;
+
+ REQUIRE(doa != NULL);
+ REQUIRE(doa->common.rdtype == dns_rdatatype_doa);
+
+ if (doa->mctx == NULL) {
+ return;
+ }
+
+ if (doa->mediatype != NULL) {
+ isc_mem_free(doa->mctx, doa->mediatype);
+ }
+ if (doa->data != NULL) {
+ isc_mem_free(doa->mctx, doa->data);
+ }
+
+ doa->mctx = NULL;
+}
+
+static isc_result_t
+additionaldata_doa(ARGS_ADDLDATA) {
+ REQUIRE(rdata->type == dns_rdatatype_doa);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(add);
+ UNUSED(arg);
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+digest_doa(ARGS_DIGEST) {
+ isc_region_t r;
+
+ REQUIRE(rdata->type == dns_rdatatype_doa);
+
+ dns_rdata_toregion(rdata, &r);
+
+ return ((digest)(arg, &r));
+}
+
+static bool
+checkowner_doa(ARGS_CHECKOWNER) {
+ UNUSED(name);
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ REQUIRE(type == dns_rdatatype_doa);
+
+ return (true);
+}
+
+static bool
+checknames_doa(ARGS_CHECKNAMES) {
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(bad);
+
+ REQUIRE(rdata->type == dns_rdatatype_doa);
+
+ return (true);
+}
+
+static int
+casecompare_doa(ARGS_COMPARE) {
+ return (compare_doa(rdata1, rdata2));
+}
+
+#endif /* RDATA_GENERIC_DOA_259_C */
diff --git a/lib/dns/rdata/generic/doa_259.h b/lib/dns/rdata/generic/doa_259.h
new file mode 100644
index 0000000..320bd7a
--- /dev/null
+++ b/lib/dns/rdata/generic/doa_259.h
@@ -0,0 +1,26 @@
+/*
+ * 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_doa {
+ dns_rdatacommon_t common;
+ isc_mem_t *mctx;
+ unsigned char *mediatype;
+ unsigned char *data;
+ uint32_t enterprise;
+ uint32_t type;
+ uint16_t data_len;
+ uint8_t location;
+ uint8_t mediatype_len;
+} dns_rdata_doa_t;
diff --git a/lib/dns/rdata/generic/ds_43.c b/lib/dns/rdata/generic/ds_43.c
new file mode 100644
index 0000000..482f32b
--- /dev/null
+++ b/lib/dns/rdata/generic/ds_43.c
@@ -0,0 +1,386 @@
+/*
+ * 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.
+ */
+
+/* RFC3658 */
+
+#ifndef RDATA_GENERIC_DS_43_C
+#define RDATA_GENERIC_DS_43_C
+
+#define RRTYPE_DS_ATTRIBUTES \
+ (DNS_RDATATYPEATTR_DNSSEC | DNS_RDATATYPEATTR_ZONECUTAUTH | \
+ DNS_RDATATYPEATTR_ATPARENT)
+
+#include <isc/md.h>
+
+#include <dns/ds.h>
+
+static isc_result_t
+generic_fromtext_ds(ARGS_FROMTEXT) {
+ isc_token_t token;
+ unsigned char c;
+ int length;
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(origin);
+ UNUSED(options);
+ UNUSED(callbacks);
+
+ /*
+ * Key tag.
+ */
+ 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));
+
+ /*
+ * Algorithm.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ false));
+ RETTOK(dns_secalg_fromtext(&c, &token.value.as_textregion));
+ RETERR(mem_tobuffer(target, &c, 1));
+
+ /*
+ * Digest type.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ false));
+ RETTOK(dns_dsdigest_fromtext(&c, &token.value.as_textregion));
+ RETERR(mem_tobuffer(target, &c, 1));
+
+ /*
+ * Digest.
+ */
+ switch (c) {
+ case DNS_DSDIGEST_SHA1:
+ length = ISC_SHA1_DIGESTLENGTH;
+ break;
+ case DNS_DSDIGEST_SHA256:
+ length = ISC_SHA256_DIGESTLENGTH;
+ break;
+ case DNS_DSDIGEST_SHA384:
+ length = ISC_SHA384_DIGESTLENGTH;
+ break;
+ default:
+ length = -2;
+ break;
+ }
+ return (isc_hex_tobuffer(lexer, target, length));
+}
+
+static isc_result_t
+fromtext_ds(ARGS_FROMTEXT) {
+ REQUIRE(type == dns_rdatatype_ds);
+
+ return (generic_fromtext_ds(CALL_FROMTEXT));
+}
+
+static isc_result_t
+generic_totext_ds(ARGS_TOTEXT) {
+ isc_region_t sr;
+ char buf[sizeof("64000 ")];
+ unsigned int n;
+
+ REQUIRE(rdata->length != 0);
+
+ UNUSED(tctx);
+
+ dns_rdata_toregion(rdata, &sr);
+
+ /*
+ * Key tag.
+ */
+ n = uint16_fromregion(&sr);
+ isc_region_consume(&sr, 2);
+ snprintf(buf, sizeof(buf), "%u ", n);
+ RETERR(str_totext(buf, target));
+
+ /*
+ * Algorithm.
+ */
+ n = uint8_fromregion(&sr);
+ isc_region_consume(&sr, 1);
+ snprintf(buf, sizeof(buf), "%u ", n);
+ RETERR(str_totext(buf, target));
+
+ /*
+ * Digest type.
+ */
+ n = uint8_fromregion(&sr);
+ isc_region_consume(&sr, 1);
+ snprintf(buf, sizeof(buf), "%u", n);
+ RETERR(str_totext(buf, target));
+
+ /*
+ * Digest.
+ */
+ if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) {
+ RETERR(str_totext(" (", target));
+ }
+ RETERR(str_totext(tctx->linebreak, target));
+ if ((tctx->flags & DNS_STYLEFLAG_NOCRYPTO) == 0) {
+ if (tctx->width == 0) { /* No splitting */
+ RETERR(isc_hex_totext(&sr, 0, "", target));
+ } else {
+ RETERR(isc_hex_totext(&sr, tctx->width - 2,
+ tctx->linebreak, target));
+ }
+ } else {
+ RETERR(str_totext("[omitted]", target));
+ }
+ if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) {
+ RETERR(str_totext(" )", target));
+ }
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+totext_ds(ARGS_TOTEXT) {
+ REQUIRE(rdata != NULL);
+ REQUIRE(rdata->type == dns_rdatatype_ds);
+
+ return (generic_totext_ds(CALL_TOTEXT));
+}
+
+static isc_result_t
+generic_fromwire_ds(ARGS_FROMWIRE) {
+ isc_region_t sr;
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(dctx);
+ UNUSED(options);
+
+ isc_buffer_activeregion(source, &sr);
+
+ /*
+ * Check digest lengths if we know them.
+ */
+ if (sr.length < 5 ||
+ (sr.base[3] == DNS_DSDIGEST_SHA1 &&
+ sr.length < 4 + ISC_SHA1_DIGESTLENGTH) ||
+ (sr.base[3] == DNS_DSDIGEST_SHA256 &&
+ sr.length < 4 + ISC_SHA256_DIGESTLENGTH) ||
+ (sr.base[3] == DNS_DSDIGEST_SHA384 &&
+ sr.length < 4 + ISC_SHA384_DIGESTLENGTH))
+ {
+ return (ISC_R_UNEXPECTEDEND);
+ }
+
+ /*
+ * Only copy digest lengths if we know them.
+ * If there is extra data dns_rdata_fromwire() will
+ * detect that.
+ */
+ if (sr.base[3] == DNS_DSDIGEST_SHA1) {
+ sr.length = 4 + ISC_SHA1_DIGESTLENGTH;
+ } else if (sr.base[3] == DNS_DSDIGEST_SHA256) {
+ sr.length = 4 + ISC_SHA256_DIGESTLENGTH;
+ } else if (sr.base[3] == DNS_DSDIGEST_SHA384) {
+ sr.length = 4 + ISC_SHA384_DIGESTLENGTH;
+ }
+
+ isc_buffer_forward(source, sr.length);
+ return (mem_tobuffer(target, sr.base, sr.length));
+}
+
+static isc_result_t
+fromwire_ds(ARGS_FROMWIRE) {
+ REQUIRE(type == dns_rdatatype_ds);
+
+ return (generic_fromwire_ds(CALL_FROMWIRE));
+}
+
+static isc_result_t
+towire_ds(ARGS_TOWIRE) {
+ isc_region_t sr;
+
+ REQUIRE(rdata->type == dns_rdatatype_ds);
+ REQUIRE(rdata->length != 0);
+
+ UNUSED(cctx);
+
+ dns_rdata_toregion(rdata, &sr);
+ return (mem_tobuffer(target, sr.base, sr.length));
+}
+
+static int
+compare_ds(ARGS_COMPARE) {
+ isc_region_t r1;
+ isc_region_t r2;
+
+ REQUIRE(rdata1->type == rdata2->type);
+ REQUIRE(rdata1->rdclass == rdata2->rdclass);
+ REQUIRE(rdata1->type == dns_rdatatype_ds);
+ REQUIRE(rdata1->length != 0);
+ REQUIRE(rdata2->length != 0);
+
+ dns_rdata_toregion(rdata1, &r1);
+ dns_rdata_toregion(rdata2, &r2);
+ return (isc_region_compare(&r1, &r2));
+}
+
+static isc_result_t
+generic_fromstruct_ds(ARGS_FROMSTRUCT) {
+ dns_rdata_ds_t *ds = source;
+
+ REQUIRE(ds != NULL);
+ REQUIRE(ds->common.rdtype == type);
+ REQUIRE(ds->common.rdclass == rdclass);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ switch (ds->digest_type) {
+ case DNS_DSDIGEST_SHA1:
+ REQUIRE(ds->length == ISC_SHA1_DIGESTLENGTH);
+ break;
+ case DNS_DSDIGEST_SHA256:
+ REQUIRE(ds->length == ISC_SHA256_DIGESTLENGTH);
+ break;
+ case DNS_DSDIGEST_SHA384:
+ REQUIRE(ds->length == ISC_SHA384_DIGESTLENGTH);
+ break;
+ }
+
+ RETERR(uint16_tobuffer(ds->key_tag, target));
+ RETERR(uint8_tobuffer(ds->algorithm, target));
+ RETERR(uint8_tobuffer(ds->digest_type, target));
+
+ return (mem_tobuffer(target, ds->digest, ds->length));
+}
+
+static isc_result_t
+fromstruct_ds(ARGS_FROMSTRUCT) {
+ REQUIRE(type == dns_rdatatype_ds);
+
+ return (generic_fromstruct_ds(CALL_FROMSTRUCT));
+}
+
+static isc_result_t
+generic_tostruct_ds(ARGS_TOSTRUCT) {
+ dns_rdata_ds_t *ds = target;
+ isc_region_t region;
+
+ REQUIRE(ds != NULL);
+ REQUIRE(rdata->length != 0);
+ REQUIRE(ds->common.rdtype == rdata->type);
+ REQUIRE(ds->common.rdclass == rdata->rdclass);
+ REQUIRE(!ISC_LINK_LINKED(&ds->common, link));
+
+ dns_rdata_toregion(rdata, &region);
+
+ ds->key_tag = uint16_fromregion(&region);
+ isc_region_consume(&region, 2);
+ ds->algorithm = uint8_fromregion(&region);
+ isc_region_consume(&region, 1);
+ ds->digest_type = uint8_fromregion(&region);
+ isc_region_consume(&region, 1);
+ ds->length = region.length;
+
+ ds->digest = mem_maybedup(mctx, region.base, region.length);
+ if (ds->digest == NULL) {
+ return (ISC_R_NOMEMORY);
+ }
+
+ ds->mctx = mctx;
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+tostruct_ds(ARGS_TOSTRUCT) {
+ dns_rdata_ds_t *ds = target;
+
+ REQUIRE(rdata->type == dns_rdatatype_ds);
+ REQUIRE(ds != NULL);
+
+ ds->common.rdclass = rdata->rdclass;
+ ds->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&ds->common, link);
+
+ return (generic_tostruct_ds(CALL_TOSTRUCT));
+}
+
+static void
+freestruct_ds(ARGS_FREESTRUCT) {
+ dns_rdata_ds_t *ds = source;
+
+ REQUIRE(ds != NULL);
+ REQUIRE(ds->common.rdtype == dns_rdatatype_ds);
+
+ if (ds->mctx == NULL) {
+ return;
+ }
+
+ if (ds->digest != NULL) {
+ isc_mem_free(ds->mctx, ds->digest);
+ }
+ ds->mctx = NULL;
+}
+
+static isc_result_t
+additionaldata_ds(ARGS_ADDLDATA) {
+ REQUIRE(rdata->type == dns_rdatatype_ds);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(add);
+ UNUSED(arg);
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+digest_ds(ARGS_DIGEST) {
+ isc_region_t r;
+
+ REQUIRE(rdata->type == dns_rdatatype_ds);
+
+ dns_rdata_toregion(rdata, &r);
+
+ return ((digest)(arg, &r));
+}
+
+static bool
+checkowner_ds(ARGS_CHECKOWNER) {
+ REQUIRE(type == dns_rdatatype_ds);
+
+ UNUSED(name);
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (true);
+}
+
+static bool
+checknames_ds(ARGS_CHECKNAMES) {
+ REQUIRE(rdata->type == dns_rdatatype_ds);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(bad);
+
+ return (true);
+}
+
+static int
+casecompare_ds(ARGS_COMPARE) {
+ return (compare_ds(rdata1, rdata2));
+}
+
+#endif /* RDATA_GENERIC_DS_43_C */
diff --git a/lib/dns/rdata/generic/ds_43.h b/lib/dns/rdata/generic/ds_43.h
new file mode 100644
index 0000000..57e8494
--- /dev/null
+++ b/lib/dns/rdata/generic/ds_43.h
@@ -0,0 +1,26 @@
+/*
+ * 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
+
+/*!
+ * \brief per draft-ietf-dnsext-delegation-signer-05.txt */
+typedef struct dns_rdata_ds {
+ dns_rdatacommon_t common;
+ isc_mem_t *mctx;
+ uint16_t key_tag;
+ dns_secalg_t algorithm;
+ dns_dsdigest_t digest_type;
+ uint16_t length;
+ unsigned char *digest;
+} dns_rdata_ds_t;
diff --git a/lib/dns/rdata/generic/eui48_108.c b/lib/dns/rdata/generic/eui48_108.c
new file mode 100644
index 0000000..25603b2
--- /dev/null
+++ b/lib/dns/rdata/generic/eui48_108.c
@@ -0,0 +1,212 @@
+/*
+ * 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_EUI48_108_C
+#define RDATA_GENERIC_EUI48_108_C
+
+#include <string.h>
+
+#define RRTYPE_EUI48_ATTRIBUTES (0)
+
+static isc_result_t
+fromtext_eui48(ARGS_FROMTEXT) {
+ isc_token_t token;
+ unsigned char eui48[6];
+ unsigned int l0, l1, l2, l3, l4, l5;
+ int n;
+
+ REQUIRE(type == dns_rdatatype_eui48);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(origin);
+ UNUSED(options);
+ UNUSED(callbacks);
+
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ false));
+ n = sscanf(DNS_AS_STR(token), "%2x-%2x-%2x-%2x-%2x-%2x", &l0, &l1, &l2,
+ &l3, &l4, &l5);
+ if (n != 6 || l0 > 255U || l1 > 255U || l2 > 255U || l3 > 255U ||
+ l4 > 255U || l5 > 255U)
+ {
+ return (DNS_R_BADEUI);
+ }
+
+ eui48[0] = l0;
+ eui48[1] = l1;
+ eui48[2] = l2;
+ eui48[3] = l3;
+ eui48[4] = l4;
+ eui48[5] = l5;
+ return (mem_tobuffer(target, eui48, sizeof(eui48)));
+}
+
+static isc_result_t
+totext_eui48(ARGS_TOTEXT) {
+ char buf[sizeof("xx-xx-xx-xx-xx-xx")];
+
+ REQUIRE(rdata->type == dns_rdatatype_eui48);
+ REQUIRE(rdata->length == 6);
+
+ UNUSED(tctx);
+
+ (void)snprintf(buf, sizeof(buf), "%02x-%02x-%02x-%02x-%02x-%02x",
+ rdata->data[0], rdata->data[1], rdata->data[2],
+ rdata->data[3], rdata->data[4], rdata->data[5]);
+ return (str_totext(buf, target));
+}
+
+static isc_result_t
+fromwire_eui48(ARGS_FROMWIRE) {
+ isc_region_t sregion;
+
+ REQUIRE(type == dns_rdatatype_eui48);
+
+ UNUSED(type);
+ UNUSED(options);
+ UNUSED(rdclass);
+ UNUSED(dctx);
+
+ isc_buffer_activeregion(source, &sregion);
+ if (sregion.length != 6) {
+ return (DNS_R_FORMERR);
+ }
+ isc_buffer_forward(source, sregion.length);
+ return (mem_tobuffer(target, sregion.base, sregion.length));
+}
+
+static isc_result_t
+towire_eui48(ARGS_TOWIRE) {
+ REQUIRE(rdata->type == dns_rdatatype_eui48);
+ REQUIRE(rdata->length == 6);
+
+ UNUSED(cctx);
+
+ return (mem_tobuffer(target, rdata->data, rdata->length));
+}
+
+static int
+compare_eui48(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_eui48);
+ REQUIRE(rdata1->length == 6);
+ REQUIRE(rdata2->length == 6);
+
+ dns_rdata_toregion(rdata1, &region1);
+ dns_rdata_toregion(rdata2, &region2);
+ return (isc_region_compare(&region1, &region2));
+}
+
+static isc_result_t
+fromstruct_eui48(ARGS_FROMSTRUCT) {
+ dns_rdata_eui48_t *eui48 = source;
+
+ REQUIRE(type == dns_rdatatype_eui48);
+ REQUIRE(eui48 != NULL);
+ REQUIRE(eui48->common.rdtype == type);
+ REQUIRE(eui48->common.rdclass == rdclass);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ return (mem_tobuffer(target, eui48->eui48, sizeof(eui48->eui48)));
+}
+
+static isc_result_t
+tostruct_eui48(ARGS_TOSTRUCT) {
+ dns_rdata_eui48_t *eui48 = target;
+
+ REQUIRE(rdata->type == dns_rdatatype_eui48);
+ REQUIRE(eui48 != NULL);
+ REQUIRE(rdata->length == 6);
+
+ UNUSED(mctx);
+
+ eui48->common.rdclass = rdata->rdclass;
+ eui48->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&eui48->common, link);
+
+ memmove(eui48->eui48, rdata->data, rdata->length);
+ return (ISC_R_SUCCESS);
+}
+
+static void
+freestruct_eui48(ARGS_FREESTRUCT) {
+ dns_rdata_eui48_t *eui48 = source;
+
+ REQUIRE(eui48 != NULL);
+ REQUIRE(eui48->common.rdtype == dns_rdatatype_eui48);
+
+ return;
+}
+
+static isc_result_t
+additionaldata_eui48(ARGS_ADDLDATA) {
+ REQUIRE(rdata->type == dns_rdatatype_eui48);
+ REQUIRE(rdata->length == 6);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(add);
+ UNUSED(arg);
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+digest_eui48(ARGS_DIGEST) {
+ isc_region_t r;
+
+ REQUIRE(rdata->type == dns_rdatatype_eui48);
+ REQUIRE(rdata->length == 6);
+
+ dns_rdata_toregion(rdata, &r);
+
+ return ((digest)(arg, &r));
+}
+
+static bool
+checkowner_eui48(ARGS_CHECKOWNER) {
+ REQUIRE(type == dns_rdatatype_eui48);
+
+ UNUSED(name);
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (true);
+}
+
+static bool
+checknames_eui48(ARGS_CHECKNAMES) {
+ REQUIRE(rdata->type == dns_rdatatype_eui48);
+ REQUIRE(rdata->length == 6);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(bad);
+
+ return (true);
+}
+
+static int
+casecompare_eui48(ARGS_COMPARE) {
+ return (compare_eui48(rdata1, rdata2));
+}
+
+#endif /* RDATA_GENERIC_EUI48_108_C */
diff --git a/lib/dns/rdata/generic/eui48_108.h b/lib/dns/rdata/generic/eui48_108.h
new file mode 100644
index 0000000..fb3cebd
--- /dev/null
+++ b/lib/dns/rdata/generic/eui48_108.h
@@ -0,0 +1,20 @@
+/*
+ * 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_eui48 {
+ dns_rdatacommon_t common;
+ unsigned char eui48[6];
+} dns_rdata_eui48_t;
diff --git a/lib/dns/rdata/generic/eui64_109.c b/lib/dns/rdata/generic/eui64_109.c
new file mode 100644
index 0000000..93978d2
--- /dev/null
+++ b/lib/dns/rdata/generic/eui64_109.c
@@ -0,0 +1,215 @@
+/*
+ * 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_EUI64_109_C
+#define RDATA_GENERIC_EUI64_109_C
+
+#include <string.h>
+
+#define RRTYPE_EUI64_ATTRIBUTES (0)
+
+static isc_result_t
+fromtext_eui64(ARGS_FROMTEXT) {
+ isc_token_t token;
+ unsigned char eui64[8];
+ unsigned int l0, l1, l2, l3, l4, l5, l6, l7;
+ int n;
+
+ REQUIRE(type == dns_rdatatype_eui64);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(origin);
+ UNUSED(options);
+ UNUSED(callbacks);
+
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ false));
+ n = sscanf(DNS_AS_STR(token), "%2x-%2x-%2x-%2x-%2x-%2x-%2x-%2x", &l0,
+ &l1, &l2, &l3, &l4, &l5, &l6, &l7);
+ if (n != 8 || l0 > 255U || l1 > 255U || l2 > 255U || l3 > 255U ||
+ l4 > 255U || l5 > 255U || l6 > 255U || l7 > 255U)
+ {
+ return (DNS_R_BADEUI);
+ }
+
+ eui64[0] = l0;
+ eui64[1] = l1;
+ eui64[2] = l2;
+ eui64[3] = l3;
+ eui64[4] = l4;
+ eui64[5] = l5;
+ eui64[6] = l6;
+ eui64[7] = l7;
+ return (mem_tobuffer(target, eui64, sizeof(eui64)));
+}
+
+static isc_result_t
+totext_eui64(ARGS_TOTEXT) {
+ char buf[sizeof("xx-xx-xx-xx-xx-xx-xx-xx")];
+
+ REQUIRE(rdata->type == dns_rdatatype_eui64);
+ REQUIRE(rdata->length == 8);
+
+ UNUSED(tctx);
+
+ (void)snprintf(
+ buf, sizeof(buf), "%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x",
+ rdata->data[0], rdata->data[1], rdata->data[2], rdata->data[3],
+ rdata->data[4], rdata->data[5], rdata->data[6], rdata->data[7]);
+ return (str_totext(buf, target));
+}
+
+static isc_result_t
+fromwire_eui64(ARGS_FROMWIRE) {
+ isc_region_t sregion;
+
+ REQUIRE(type == dns_rdatatype_eui64);
+
+ UNUSED(type);
+ UNUSED(options);
+ UNUSED(rdclass);
+ UNUSED(dctx);
+
+ isc_buffer_activeregion(source, &sregion);
+ if (sregion.length != 8) {
+ return (DNS_R_FORMERR);
+ }
+ isc_buffer_forward(source, sregion.length);
+ return (mem_tobuffer(target, sregion.base, sregion.length));
+}
+
+static isc_result_t
+towire_eui64(ARGS_TOWIRE) {
+ REQUIRE(rdata->type == dns_rdatatype_eui64);
+ REQUIRE(rdata->length == 8);
+
+ UNUSED(cctx);
+
+ return (mem_tobuffer(target, rdata->data, rdata->length));
+}
+
+static int
+compare_eui64(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_eui64);
+ REQUIRE(rdata1->length == 8);
+ REQUIRE(rdata2->length == 8);
+
+ dns_rdata_toregion(rdata1, &region1);
+ dns_rdata_toregion(rdata2, &region2);
+ return (isc_region_compare(&region1, &region2));
+}
+
+static isc_result_t
+fromstruct_eui64(ARGS_FROMSTRUCT) {
+ dns_rdata_eui64_t *eui64 = source;
+
+ REQUIRE(type == dns_rdatatype_eui64);
+ REQUIRE(eui64 != NULL);
+ REQUIRE(eui64->common.rdtype == type);
+ REQUIRE(eui64->common.rdclass == rdclass);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ return (mem_tobuffer(target, eui64->eui64, sizeof(eui64->eui64)));
+}
+
+static isc_result_t
+tostruct_eui64(ARGS_TOSTRUCT) {
+ dns_rdata_eui64_t *eui64 = target;
+
+ REQUIRE(rdata->type == dns_rdatatype_eui64);
+ REQUIRE(eui64 != NULL);
+ REQUIRE(rdata->length == 8);
+
+ UNUSED(mctx);
+
+ eui64->common.rdclass = rdata->rdclass;
+ eui64->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&eui64->common, link);
+
+ memmove(eui64->eui64, rdata->data, rdata->length);
+ return (ISC_R_SUCCESS);
+}
+
+static void
+freestruct_eui64(ARGS_FREESTRUCT) {
+ dns_rdata_eui64_t *eui64 = source;
+
+ REQUIRE(eui64 != NULL);
+ REQUIRE(eui64->common.rdtype == dns_rdatatype_eui64);
+
+ return;
+}
+
+static isc_result_t
+additionaldata_eui64(ARGS_ADDLDATA) {
+ REQUIRE(rdata->type == dns_rdatatype_eui64);
+ REQUIRE(rdata->length == 8);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(add);
+ UNUSED(arg);
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+digest_eui64(ARGS_DIGEST) {
+ isc_region_t r;
+
+ REQUIRE(rdata->type == dns_rdatatype_eui64);
+ REQUIRE(rdata->length == 8);
+
+ dns_rdata_toregion(rdata, &r);
+
+ return ((digest)(arg, &r));
+}
+
+static bool
+checkowner_eui64(ARGS_CHECKOWNER) {
+ REQUIRE(type == dns_rdatatype_eui64);
+
+ UNUSED(name);
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (true);
+}
+
+static bool
+checknames_eui64(ARGS_CHECKNAMES) {
+ REQUIRE(rdata->type == dns_rdatatype_eui64);
+ REQUIRE(rdata->length == 8);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(bad);
+
+ return (true);
+}
+
+static int
+casecompare_eui64(ARGS_COMPARE) {
+ return (compare_eui64(rdata1, rdata2));
+}
+
+#endif /* RDATA_GENERIC_EUI64_109_C */
diff --git a/lib/dns/rdata/generic/eui64_109.h b/lib/dns/rdata/generic/eui64_109.h
new file mode 100644
index 0000000..c5f6d89
--- /dev/null
+++ b/lib/dns/rdata/generic/eui64_109.h
@@ -0,0 +1,20 @@
+/*
+ * 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_eui64 {
+ dns_rdatacommon_t common;
+ unsigned char eui64[8];
+} dns_rdata_eui64_t;
diff --git a/lib/dns/rdata/generic/gpos_27.c b/lib/dns/rdata/generic/gpos_27.c
new file mode 100644
index 0000000..4f2f3fd
--- /dev/null
+++ b/lib/dns/rdata/generic/gpos_27.c
@@ -0,0 +1,257 @@
+/*
+ * 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.
+ */
+
+/* RFC1712 */
+
+#ifndef RDATA_GENERIC_GPOS_27_C
+#define RDATA_GENERIC_GPOS_27_C
+
+#define RRTYPE_GPOS_ATTRIBUTES (0)
+
+static isc_result_t
+fromtext_gpos(ARGS_FROMTEXT) {
+ isc_token_t token;
+ int i;
+
+ REQUIRE(type == dns_rdatatype_gpos);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(origin);
+ UNUSED(options);
+ UNUSED(callbacks);
+
+ for (i = 0; i < 3; i++) {
+ RETERR(isc_lex_getmastertoken(lexer, &token,
+ isc_tokentype_qstring, false));
+ RETTOK(txt_fromtext(&token.value.as_textregion, target));
+ }
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+totext_gpos(ARGS_TOTEXT) {
+ isc_region_t region;
+ int i;
+
+ REQUIRE(rdata->type == dns_rdatatype_gpos);
+ REQUIRE(rdata->length != 0);
+
+ UNUSED(tctx);
+
+ dns_rdata_toregion(rdata, &region);
+
+ for (i = 0; i < 3; i++) {
+ RETERR(txt_totext(&region, true, target));
+ if (i != 2) {
+ RETERR(str_totext(" ", target));
+ }
+ }
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+fromwire_gpos(ARGS_FROMWIRE) {
+ int i;
+
+ REQUIRE(type == dns_rdatatype_gpos);
+
+ UNUSED(type);
+ UNUSED(dctx);
+ UNUSED(rdclass);
+ UNUSED(options);
+
+ for (i = 0; i < 3; i++) {
+ RETERR(txt_fromwire(source, target));
+ }
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+towire_gpos(ARGS_TOWIRE) {
+ REQUIRE(rdata->type == dns_rdatatype_gpos);
+ REQUIRE(rdata->length != 0);
+
+ UNUSED(cctx);
+
+ return (mem_tobuffer(target, rdata->data, rdata->length));
+}
+
+static int
+compare_gpos(ARGS_COMPARE) {
+ isc_region_t r1;
+ isc_region_t r2;
+
+ REQUIRE(rdata1->type == rdata2->type);
+ REQUIRE(rdata1->rdclass == rdata2->rdclass);
+ REQUIRE(rdata1->type == dns_rdatatype_gpos);
+ REQUIRE(rdata1->length != 0);
+ REQUIRE(rdata2->length != 0);
+
+ dns_rdata_toregion(rdata1, &r1);
+ dns_rdata_toregion(rdata2, &r2);
+ return (isc_region_compare(&r1, &r2));
+}
+
+static isc_result_t
+fromstruct_gpos(ARGS_FROMSTRUCT) {
+ dns_rdata_gpos_t *gpos = source;
+
+ REQUIRE(type == dns_rdatatype_gpos);
+ REQUIRE(gpos != NULL);
+ REQUIRE(gpos->common.rdtype == type);
+ REQUIRE(gpos->common.rdclass == rdclass);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ RETERR(uint8_tobuffer(gpos->long_len, target));
+ RETERR(mem_tobuffer(target, gpos->longitude, gpos->long_len));
+ RETERR(uint8_tobuffer(gpos->lat_len, target));
+ RETERR(mem_tobuffer(target, gpos->latitude, gpos->lat_len));
+ RETERR(uint8_tobuffer(gpos->alt_len, target));
+ return (mem_tobuffer(target, gpos->altitude, gpos->alt_len));
+}
+
+static isc_result_t
+tostruct_gpos(ARGS_TOSTRUCT) {
+ dns_rdata_gpos_t *gpos = target;
+ isc_region_t region;
+
+ REQUIRE(rdata->type == dns_rdatatype_gpos);
+ REQUIRE(gpos != NULL);
+ REQUIRE(rdata->length != 0);
+
+ gpos->common.rdclass = rdata->rdclass;
+ gpos->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&gpos->common, link);
+
+ dns_rdata_toregion(rdata, &region);
+ gpos->long_len = uint8_fromregion(&region);
+ isc_region_consume(&region, 1);
+ gpos->longitude = mem_maybedup(mctx, region.base, gpos->long_len);
+ if (gpos->longitude == NULL) {
+ return (ISC_R_NOMEMORY);
+ }
+ isc_region_consume(&region, gpos->long_len);
+
+ gpos->lat_len = uint8_fromregion(&region);
+ isc_region_consume(&region, 1);
+ gpos->latitude = mem_maybedup(mctx, region.base, gpos->lat_len);
+ if (gpos->latitude == NULL) {
+ goto cleanup_longitude;
+ }
+ isc_region_consume(&region, gpos->lat_len);
+
+ gpos->alt_len = uint8_fromregion(&region);
+ isc_region_consume(&region, 1);
+ if (gpos->lat_len > 0) {
+ gpos->altitude = mem_maybedup(mctx, region.base, gpos->alt_len);
+ if (gpos->altitude == NULL) {
+ goto cleanup_latitude;
+ }
+ } else {
+ gpos->altitude = NULL;
+ }
+
+ gpos->mctx = mctx;
+ return (ISC_R_SUCCESS);
+
+cleanup_latitude:
+ if (mctx != NULL && gpos->longitude != NULL) {
+ isc_mem_free(mctx, gpos->longitude);
+ }
+
+cleanup_longitude:
+ if (mctx != NULL && gpos->latitude != NULL) {
+ isc_mem_free(mctx, gpos->latitude);
+ }
+ return (ISC_R_NOMEMORY);
+}
+
+static void
+freestruct_gpos(ARGS_FREESTRUCT) {
+ dns_rdata_gpos_t *gpos = source;
+
+ REQUIRE(gpos != NULL);
+ REQUIRE(gpos->common.rdtype == dns_rdatatype_gpos);
+
+ if (gpos->mctx == NULL) {
+ return;
+ }
+
+ if (gpos->longitude != NULL) {
+ isc_mem_free(gpos->mctx, gpos->longitude);
+ }
+ if (gpos->latitude != NULL) {
+ isc_mem_free(gpos->mctx, gpos->latitude);
+ }
+ if (gpos->altitude != NULL) {
+ isc_mem_free(gpos->mctx, gpos->altitude);
+ }
+ gpos->mctx = NULL;
+}
+
+static isc_result_t
+additionaldata_gpos(ARGS_ADDLDATA) {
+ REQUIRE(rdata->type == dns_rdatatype_gpos);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(add);
+ UNUSED(arg);
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+digest_gpos(ARGS_DIGEST) {
+ isc_region_t r;
+
+ REQUIRE(rdata->type == dns_rdatatype_gpos);
+
+ dns_rdata_toregion(rdata, &r);
+
+ return ((digest)(arg, &r));
+}
+
+static bool
+checkowner_gpos(ARGS_CHECKOWNER) {
+ REQUIRE(type == dns_rdatatype_gpos);
+
+ UNUSED(name);
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (true);
+}
+
+static bool
+checknames_gpos(ARGS_CHECKNAMES) {
+ REQUIRE(rdata->type == dns_rdatatype_gpos);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(bad);
+
+ return (true);
+}
+
+static int
+casecompare_gpos(ARGS_COMPARE) {
+ return (compare_gpos(rdata1, rdata2));
+}
+
+#endif /* RDATA_GENERIC_GPOS_27_C */
diff --git a/lib/dns/rdata/generic/gpos_27.h b/lib/dns/rdata/generic/gpos_27.h
new file mode 100644
index 0000000..b09a69f
--- /dev/null
+++ b/lib/dns/rdata/generic/gpos_27.h
@@ -0,0 +1,28 @@
+/*
+ * 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
+
+/*!
+ * \brief per RFC1712 */
+
+typedef struct dns_rdata_gpos {
+ dns_rdatacommon_t common;
+ isc_mem_t *mctx;
+ char *longitude;
+ char *latitude;
+ char *altitude;
+ uint8_t long_len;
+ uint8_t lat_len;
+ uint8_t alt_len;
+} dns_rdata_gpos_t;
diff --git a/lib/dns/rdata/generic/hinfo_13.c b/lib/dns/rdata/generic/hinfo_13.c
new file mode 100644
index 0000000..d3978ed
--- /dev/null
+++ b/lib/dns/rdata/generic/hinfo_13.c
@@ -0,0 +1,218 @@
+/*
+ * 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 RRTYPE_HINFO_ATTRIBUTES (0)
+
+static isc_result_t
+fromtext_hinfo(ARGS_FROMTEXT) {
+ isc_token_t token;
+ int i;
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(origin);
+ UNUSED(options);
+ UNUSED(callbacks);
+
+ REQUIRE(type == dns_rdatatype_hinfo);
+
+ for (i = 0; i < 2; i++) {
+ RETERR(isc_lex_getmastertoken(lexer, &token,
+ isc_tokentype_qstring, false));
+ RETTOK(txt_fromtext(&token.value.as_textregion, target));
+ }
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+totext_hinfo(ARGS_TOTEXT) {
+ isc_region_t region;
+
+ UNUSED(tctx);
+
+ REQUIRE(rdata->type == dns_rdatatype_hinfo);
+ REQUIRE(rdata->length != 0);
+
+ dns_rdata_toregion(rdata, &region);
+ RETERR(txt_totext(&region, true, target));
+ RETERR(str_totext(" ", target));
+ return (txt_totext(&region, true, target));
+}
+
+static isc_result_t
+fromwire_hinfo(ARGS_FROMWIRE) {
+ REQUIRE(type == dns_rdatatype_hinfo);
+
+ UNUSED(type);
+ UNUSED(dctx);
+ UNUSED(rdclass);
+ UNUSED(options);
+
+ RETERR(txt_fromwire(source, target));
+ return (txt_fromwire(source, target));
+}
+
+static isc_result_t
+towire_hinfo(ARGS_TOWIRE) {
+ UNUSED(cctx);
+
+ REQUIRE(rdata->type == dns_rdatatype_hinfo);
+ REQUIRE(rdata->length != 0);
+
+ return (mem_tobuffer(target, rdata->data, rdata->length));
+}
+
+static int
+compare_hinfo(ARGS_COMPARE) {
+ isc_region_t r1;
+ isc_region_t r2;
+
+ REQUIRE(rdata1->type == rdata2->type);
+ REQUIRE(rdata1->rdclass == rdata2->rdclass);
+ REQUIRE(rdata1->type == dns_rdatatype_hinfo);
+ REQUIRE(rdata1->length != 0);
+ REQUIRE(rdata2->length != 0);
+
+ dns_rdata_toregion(rdata1, &r1);
+ dns_rdata_toregion(rdata2, &r2);
+ return (isc_region_compare(&r1, &r2));
+}
+
+static isc_result_t
+fromstruct_hinfo(ARGS_FROMSTRUCT) {
+ dns_rdata_hinfo_t *hinfo = source;
+
+ REQUIRE(type == dns_rdatatype_hinfo);
+ REQUIRE(hinfo != NULL);
+ REQUIRE(hinfo->common.rdtype == type);
+ REQUIRE(hinfo->common.rdclass == rdclass);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ RETERR(uint8_tobuffer(hinfo->cpu_len, target));
+ RETERR(mem_tobuffer(target, hinfo->cpu, hinfo->cpu_len));
+ RETERR(uint8_tobuffer(hinfo->os_len, target));
+ return (mem_tobuffer(target, hinfo->os, hinfo->os_len));
+}
+
+static isc_result_t
+tostruct_hinfo(ARGS_TOSTRUCT) {
+ dns_rdata_hinfo_t *hinfo = target;
+ isc_region_t region;
+
+ REQUIRE(rdata->type == dns_rdatatype_hinfo);
+ REQUIRE(hinfo != NULL);
+ REQUIRE(rdata->length != 0);
+
+ hinfo->common.rdclass = rdata->rdclass;
+ hinfo->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&hinfo->common, link);
+
+ dns_rdata_toregion(rdata, &region);
+ hinfo->cpu_len = uint8_fromregion(&region);
+ isc_region_consume(&region, 1);
+ hinfo->cpu = mem_maybedup(mctx, region.base, hinfo->cpu_len);
+ if (hinfo->cpu == NULL) {
+ return (ISC_R_NOMEMORY);
+ }
+ isc_region_consume(&region, hinfo->cpu_len);
+
+ hinfo->os_len = uint8_fromregion(&region);
+ isc_region_consume(&region, 1);
+ hinfo->os = mem_maybedup(mctx, region.base, hinfo->os_len);
+ if (hinfo->os == NULL) {
+ goto cleanup;
+ }
+
+ hinfo->mctx = mctx;
+ return (ISC_R_SUCCESS);
+
+cleanup:
+ if (mctx != NULL && hinfo->cpu != NULL) {
+ isc_mem_free(mctx, hinfo->cpu);
+ }
+ return (ISC_R_NOMEMORY);
+}
+
+static void
+freestruct_hinfo(ARGS_FREESTRUCT) {
+ dns_rdata_hinfo_t *hinfo = source;
+
+ REQUIRE(hinfo != NULL);
+
+ if (hinfo->mctx == NULL) {
+ return;
+ }
+
+ if (hinfo->cpu != NULL) {
+ isc_mem_free(hinfo->mctx, hinfo->cpu);
+ }
+ if (hinfo->os != NULL) {
+ isc_mem_free(hinfo->mctx, hinfo->os);
+ }
+ hinfo->mctx = NULL;
+}
+
+static isc_result_t
+additionaldata_hinfo(ARGS_ADDLDATA) {
+ REQUIRE(rdata->type == dns_rdatatype_hinfo);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(add);
+ UNUSED(arg);
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+digest_hinfo(ARGS_DIGEST) {
+ isc_region_t r;
+
+ REQUIRE(rdata->type == dns_rdatatype_hinfo);
+
+ dns_rdata_toregion(rdata, &r);
+
+ return ((digest)(arg, &r));
+}
+
+static bool
+checkowner_hinfo(ARGS_CHECKOWNER) {
+ REQUIRE(type == dns_rdatatype_hinfo);
+
+ UNUSED(name);
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (true);
+}
+
+static bool
+checknames_hinfo(ARGS_CHECKNAMES) {
+ REQUIRE(rdata->type == dns_rdatatype_hinfo);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(bad);
+
+ return (true);
+}
+
+static int
+casecompare_hinfo(ARGS_COMPARE) {
+ return (compare_hinfo(rdata1, rdata2));
+}
diff --git a/lib/dns/rdata/generic/hinfo_13.h b/lib/dns/rdata/generic/hinfo_13.h
new file mode 100644
index 0000000..a477d47
--- /dev/null
+++ b/lib/dns/rdata/generic/hinfo_13.h
@@ -0,0 +1,23 @@
+/*
+ * 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_hinfo {
+ dns_rdatacommon_t common;
+ isc_mem_t *mctx;
+ char *cpu;
+ char *os;
+ uint8_t cpu_len;
+ uint8_t os_len;
+} dns_rdata_hinfo_t;
diff --git a/lib/dns/rdata/generic/hip_55.c b/lib/dns/rdata/generic/hip_55.c
new file mode 100644
index 0000000..e67df0e
--- /dev/null
+++ b/lib/dns/rdata/generic/hip_55.c
@@ -0,0 +1,523 @@
+/*
+ * 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.
+ */
+
+/* RFC 5205 */
+
+#pragma once
+
+#define RRTYPE_HIP_ATTRIBUTES (0)
+
+static isc_result_t
+fromtext_hip(ARGS_FROMTEXT) {
+ isc_token_t token;
+ dns_name_t name;
+ isc_buffer_t buffer;
+ isc_buffer_t hit_len;
+ isc_buffer_t key_len;
+ unsigned char *start;
+ size_t len;
+
+ REQUIRE(type == dns_rdatatype_hip);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(callbacks);
+
+ /*
+ * Dummy HIT len.
+ */
+ hit_len = *target;
+ RETERR(uint8_tobuffer(0, target));
+
+ /*
+ * Algorithm.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
+ false));
+ if (token.value.as_ulong > 0xffU) {
+ RETTOK(ISC_R_RANGE);
+ }
+ RETERR(uint8_tobuffer(token.value.as_ulong, target));
+
+ /*
+ * Dummy KEY len.
+ */
+ key_len = *target;
+ RETERR(uint16_tobuffer(0, target));
+
+ /*
+ * HIT (base16).
+ */
+ start = isc_buffer_used(target);
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ false));
+ RETTOK(isc_hex_decodestring(DNS_AS_STR(token), target));
+
+ /*
+ * Fill in HIT len.
+ */
+ len = (unsigned char *)isc_buffer_used(target) - start;
+ if (len > 0xffU) {
+ RETTOK(ISC_R_RANGE);
+ }
+ RETERR(uint8_tobuffer((uint32_t)len, &hit_len));
+
+ /*
+ * Public key (base64).
+ */
+ start = isc_buffer_used(target);
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ false));
+ RETTOK(isc_base64_decodestring(DNS_AS_STR(token), target));
+
+ /*
+ * Fill in KEY len.
+ */
+ len = (unsigned char *)isc_buffer_used(target) - start;
+ if (len > 0xffffU) {
+ RETTOK(ISC_R_RANGE);
+ }
+ RETERR(uint16_tobuffer((uint32_t)len, &key_len));
+
+ if (origin == NULL) {
+ origin = dns_rootname;
+ }
+
+ /*
+ * Rendezvous Servers.
+ */
+ dns_name_init(&name, NULL);
+ do {
+ RETERR(isc_lex_getmastertoken(lexer, &token,
+ isc_tokentype_string, true));
+ if (token.type != isc_tokentype_string) {
+ break;
+ }
+ buffer_fromregion(&buffer, &token.value.as_region);
+ RETTOK(dns_name_fromtext(&name, &buffer, origin, options,
+ target));
+ } while (1);
+
+ /*
+ * Let upper layer handle eol/eof.
+ */
+ isc_lex_ungettoken(lexer, &token);
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+totext_hip(ARGS_TOTEXT) {
+ isc_region_t region;
+ dns_name_t name;
+ unsigned int length, key_len, hit_len;
+ unsigned char algorithm;
+ char buf[sizeof("225 ")];
+
+ REQUIRE(rdata->type == dns_rdatatype_hip);
+ REQUIRE(rdata->length != 0);
+
+ dns_rdata_toregion(rdata, &region);
+
+ hit_len = uint8_fromregion(&region);
+ isc_region_consume(&region, 1);
+
+ algorithm = uint8_fromregion(&region);
+ isc_region_consume(&region, 1);
+
+ key_len = uint16_fromregion(&region);
+ isc_region_consume(&region, 2);
+
+ if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) {
+ RETERR(str_totext("( ", target));
+ }
+
+ /*
+ * Algorithm
+ */
+ snprintf(buf, sizeof(buf), "%u ", algorithm);
+ RETERR(str_totext(buf, target));
+
+ /*
+ * HIT.
+ */
+ INSIST(hit_len < region.length);
+ length = region.length;
+ region.length = hit_len;
+ RETERR(isc_hex_totext(&region, 1, "", target));
+ region.length = length - hit_len;
+ RETERR(str_totext(tctx->linebreak, target));
+
+ /*
+ * Public KEY.
+ */
+ INSIST(key_len <= region.length);
+ length = region.length;
+ region.length = key_len;
+ RETERR(isc_base64_totext(&region, 1, "", target));
+ region.length = length - key_len;
+ if (region.length > 0) {
+ RETERR(str_totext(tctx->linebreak, target));
+ }
+
+ /*
+ * Rendezvous Servers.
+ */
+ dns_name_init(&name, NULL);
+ while (region.length > 0) {
+ dns_name_fromregion(&name, &region);
+
+ RETERR(dns_name_totext(&name, false, target));
+ isc_region_consume(&region, name.length);
+ if (region.length > 0) {
+ RETERR(str_totext(tctx->linebreak, target));
+ }
+ }
+ if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) {
+ RETERR(str_totext(" )", target));
+ }
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+fromwire_hip(ARGS_FROMWIRE) {
+ isc_region_t region, rr;
+ dns_name_t name;
+ uint8_t hit_len;
+ uint16_t key_len;
+ size_t len;
+
+ REQUIRE(type == dns_rdatatype_hip);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ isc_buffer_activeregion(source, &region);
+ if (region.length < 4U) {
+ RETERR(DNS_R_FORMERR);
+ }
+
+ rr = region;
+ hit_len = uint8_fromregion(&region);
+ if (hit_len == 0) {
+ RETERR(DNS_R_FORMERR);
+ }
+ isc_region_consume(&region, 2); /* hit length + algorithm */
+ key_len = uint16_fromregion(&region);
+ if (key_len == 0) {
+ RETERR(DNS_R_FORMERR);
+ }
+ isc_region_consume(&region, 2);
+ len = hit_len + key_len;
+ if (len > region.length) {
+ RETERR(DNS_R_FORMERR);
+ }
+
+ RETERR(mem_tobuffer(target, rr.base, 4 + len));
+ isc_buffer_forward(source, 4 + len);
+
+ dns_decompress_setmethods(dctx, DNS_COMPRESS_NONE);
+ while (isc_buffer_activelength(source) > 0) {
+ dns_name_init(&name, NULL);
+ RETERR(dns_name_fromwire(&name, source, dctx, options, target));
+ }
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+towire_hip(ARGS_TOWIRE) {
+ isc_region_t region;
+
+ REQUIRE(rdata->type == dns_rdatatype_hip);
+ REQUIRE(rdata->length != 0);
+
+ UNUSED(cctx);
+
+ dns_rdata_toregion(rdata, &region);
+ return (mem_tobuffer(target, region.base, region.length));
+}
+
+static int
+compare_hip(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_hip);
+ REQUIRE(rdata1->length != 0);
+ REQUIRE(rdata2->length != 0);
+
+ dns_rdata_toregion(rdata1, &region1);
+ dns_rdata_toregion(rdata2, &region2);
+ return (isc_region_compare(&region1, &region2));
+}
+
+static isc_result_t
+fromstruct_hip(ARGS_FROMSTRUCT) {
+ dns_rdata_hip_t *hip = source;
+ dns_rdata_hip_t myhip;
+ isc_result_t result;
+
+ REQUIRE(type == dns_rdatatype_hip);
+ REQUIRE(hip != NULL);
+ REQUIRE(hip->common.rdtype == type);
+ REQUIRE(hip->common.rdclass == rdclass);
+ REQUIRE(hip->hit_len > 0 && hip->hit != NULL);
+ REQUIRE(hip->key_len > 0 && hip->key != NULL);
+ REQUIRE((hip->servers == NULL && hip->servers_len == 0) ||
+ (hip->servers != NULL && hip->servers_len != 0));
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ RETERR(uint8_tobuffer(hip->hit_len, target));
+ RETERR(uint8_tobuffer(hip->algorithm, target));
+ RETERR(uint16_tobuffer(hip->key_len, target));
+ RETERR(mem_tobuffer(target, hip->hit, hip->hit_len));
+ RETERR(mem_tobuffer(target, hip->key, hip->key_len));
+
+ myhip = *hip;
+ for (result = dns_rdata_hip_first(&myhip); result == ISC_R_SUCCESS;
+ result = dns_rdata_hip_next(&myhip))
+ {
+ /* initialize the names */
+ }
+
+ return (mem_tobuffer(target, hip->servers, hip->servers_len));
+}
+
+static isc_result_t
+tostruct_hip(ARGS_TOSTRUCT) {
+ isc_region_t region;
+ dns_rdata_hip_t *hip = target;
+
+ REQUIRE(rdata->type == dns_rdatatype_hip);
+ REQUIRE(hip != NULL);
+ REQUIRE(rdata->length != 0);
+
+ hip->common.rdclass = rdata->rdclass;
+ hip->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&hip->common, link);
+
+ dns_rdata_toregion(rdata, &region);
+
+ hip->hit_len = uint8_fromregion(&region);
+ isc_region_consume(&region, 1);
+
+ hip->algorithm = uint8_fromregion(&region);
+ isc_region_consume(&region, 1);
+
+ hip->key_len = uint16_fromregion(&region);
+ isc_region_consume(&region, 2);
+
+ hip->hit = hip->key = hip->servers = NULL;
+
+ hip->hit = mem_maybedup(mctx, region.base, hip->hit_len);
+ if (hip->hit == NULL) {
+ goto cleanup;
+ }
+ isc_region_consume(&region, hip->hit_len);
+
+ INSIST(hip->key_len <= region.length);
+
+ hip->key = mem_maybedup(mctx, region.base, hip->key_len);
+ if (hip->key == NULL) {
+ goto cleanup;
+ }
+ isc_region_consume(&region, hip->key_len);
+
+ hip->servers_len = region.length;
+ if (hip->servers_len != 0) {
+ hip->servers = mem_maybedup(mctx, region.base, region.length);
+ if (hip->servers == NULL) {
+ goto cleanup;
+ }
+ }
+
+ hip->offset = hip->servers_len;
+ hip->mctx = mctx;
+ return (ISC_R_SUCCESS);
+
+cleanup:
+ if (hip->hit != NULL) {
+ isc_mem_free(mctx, hip->hit);
+ }
+ if (hip->key != NULL) {
+ isc_mem_free(mctx, hip->key);
+ }
+ if (hip->servers != NULL) {
+ isc_mem_free(mctx, hip->servers);
+ }
+ return (ISC_R_NOMEMORY);
+}
+
+static void
+freestruct_hip(ARGS_FREESTRUCT) {
+ dns_rdata_hip_t *hip = source;
+
+ REQUIRE(hip != NULL);
+
+ if (hip->mctx == NULL) {
+ return;
+ }
+
+ isc_mem_free(hip->mctx, hip->hit);
+ isc_mem_free(hip->mctx, hip->key);
+ if (hip->servers != NULL) {
+ isc_mem_free(hip->mctx, hip->servers);
+ }
+ hip->mctx = NULL;
+}
+
+static isc_result_t
+additionaldata_hip(ARGS_ADDLDATA) {
+ REQUIRE(rdata->type == dns_rdatatype_hip);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(add);
+ UNUSED(arg);
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+digest_hip(ARGS_DIGEST) {
+ isc_region_t r;
+
+ REQUIRE(rdata->type == dns_rdatatype_hip);
+
+ dns_rdata_toregion(rdata, &r);
+ return ((digest)(arg, &r));
+}
+
+static bool
+checkowner_hip(ARGS_CHECKOWNER) {
+ REQUIRE(type == dns_rdatatype_hip);
+
+ UNUSED(name);
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (true);
+}
+
+static bool
+checknames_hip(ARGS_CHECKNAMES) {
+ REQUIRE(rdata->type == dns_rdatatype_hip);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(bad);
+
+ return (true);
+}
+
+isc_result_t
+dns_rdata_hip_first(dns_rdata_hip_t *hip) {
+ if (hip->servers_len == 0) {
+ return (ISC_R_NOMORE);
+ }
+ hip->offset = 0;
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+dns_rdata_hip_next(dns_rdata_hip_t *hip) {
+ isc_region_t region;
+ dns_name_t name;
+
+ if (hip->offset >= hip->servers_len) {
+ return (ISC_R_NOMORE);
+ }
+
+ region.base = hip->servers + hip->offset;
+ region.length = hip->servers_len - hip->offset;
+ dns_name_init(&name, NULL);
+ dns_name_fromregion(&name, &region);
+ hip->offset += name.length;
+ INSIST(hip->offset <= hip->servers_len);
+ return (hip->offset < hip->servers_len ? ISC_R_SUCCESS : ISC_R_NOMORE);
+}
+
+void
+dns_rdata_hip_current(dns_rdata_hip_t *hip, dns_name_t *name) {
+ isc_region_t region;
+
+ REQUIRE(hip->offset < hip->servers_len);
+
+ region.base = hip->servers + hip->offset;
+ region.length = hip->servers_len - hip->offset;
+ dns_name_fromregion(name, &region);
+
+ INSIST(name->length + hip->offset <= hip->servers_len);
+}
+
+static int
+casecompare_hip(ARGS_COMPARE) {
+ isc_region_t r1;
+ isc_region_t r2;
+ dns_name_t name1;
+ dns_name_t name2;
+ int order;
+ uint8_t hit_len;
+ uint16_t key_len;
+
+ REQUIRE(rdata1->type == rdata2->type);
+ REQUIRE(rdata1->rdclass == rdata2->rdclass);
+ REQUIRE(rdata1->type == dns_rdatatype_hip);
+ REQUIRE(rdata1->length != 0);
+ REQUIRE(rdata2->length != 0);
+
+ dns_rdata_toregion(rdata1, &r1);
+ dns_rdata_toregion(rdata2, &r2);
+
+ INSIST(r1.length > 4);
+ INSIST(r2.length > 4);
+ order = memcmp(r1.base, r2.base, 4);
+ if (order != 0) {
+ return (order);
+ }
+
+ hit_len = uint8_fromregion(&r1);
+ isc_region_consume(&r1, 2); /* hit length + algorithm */
+ key_len = uint16_fromregion(&r1);
+ isc_region_consume(&r1, 2); /* key length */
+ isc_region_consume(&r2, 4);
+
+ INSIST(r1.length >= (unsigned)(hit_len + key_len));
+ INSIST(r2.length >= (unsigned)(hit_len + key_len));
+ order = memcmp(r1.base, r2.base, hit_len + key_len);
+ if (order != 0) {
+ return (order);
+ }
+ isc_region_consume(&r1, hit_len + key_len);
+ isc_region_consume(&r2, hit_len + key_len);
+
+ dns_name_init(&name1, NULL);
+ dns_name_init(&name2, NULL);
+ while (r1.length != 0 && r2.length != 0) {
+ dns_name_fromregion(&name1, &r1);
+ dns_name_fromregion(&name2, &r2);
+ order = dns_name_rdatacompare(&name1, &name2);
+ if (order != 0) {
+ return (order);
+ }
+
+ isc_region_consume(&r1, name_length(&name1));
+ isc_region_consume(&r2, name_length(&name2));
+ }
+ return (isc_region_compare(&r1, &r2));
+}
diff --git a/lib/dns/rdata/generic/hip_55.h b/lib/dns/rdata/generic/hip_55.h
new file mode 100644
index 0000000..617e9c9
--- /dev/null
+++ b/lib/dns/rdata/generic/hip_55.h
@@ -0,0 +1,39 @@
+/*
+ * 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
+
+/* RFC 5205 */
+
+typedef struct dns_rdata_hip {
+ dns_rdatacommon_t common;
+ isc_mem_t *mctx;
+ unsigned char *hit;
+ unsigned char *key;
+ unsigned char *servers;
+ uint8_t algorithm;
+ uint8_t hit_len;
+ uint16_t key_len;
+ uint16_t servers_len;
+ /* Private */
+ uint16_t offset;
+} dns_rdata_hip_t;
+
+isc_result_t
+dns_rdata_hip_first(dns_rdata_hip_t *);
+
+isc_result_t
+dns_rdata_hip_next(dns_rdata_hip_t *);
+
+void
+dns_rdata_hip_current(dns_rdata_hip_t *, dns_name_t *);
diff --git a/lib/dns/rdata/generic/ipseckey_45.c b/lib/dns/rdata/generic/ipseckey_45.c
new file mode 100644
index 0000000..a4232db
--- /dev/null
+++ b/lib/dns/rdata/generic/ipseckey_45.c
@@ -0,0 +1,527 @@
+/*
+ * 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_IPSECKEY_45_C
+#define RDATA_GENERIC_IPSECKEY_45_C
+
+#include <string.h>
+
+#include <isc/net.h>
+
+#define RRTYPE_IPSECKEY_ATTRIBUTES (0)
+
+static isc_result_t
+fromtext_ipseckey(ARGS_FROMTEXT) {
+ isc_token_t token;
+ dns_name_t name;
+ isc_buffer_t buffer;
+ unsigned int gateway;
+ struct in_addr addr;
+ unsigned char addr6[16];
+ isc_region_t region;
+
+ REQUIRE(type == dns_rdatatype_ipseckey);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(callbacks);
+
+ /*
+ * Precedence.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
+ false));
+ if (token.value.as_ulong > 0xffU) {
+ RETTOK(ISC_R_RANGE);
+ }
+ RETERR(uint8_tobuffer(token.value.as_ulong, target));
+
+ /*
+ * Gateway type.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
+ false));
+ if (token.value.as_ulong > 0x3U) {
+ RETTOK(ISC_R_RANGE);
+ }
+ RETERR(uint8_tobuffer(token.value.as_ulong, target));
+ gateway = token.value.as_ulong;
+
+ /*
+ * Algorithm.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
+ false));
+ if (token.value.as_ulong > 0xffU) {
+ RETTOK(ISC_R_RANGE);
+ }
+ RETERR(uint8_tobuffer(token.value.as_ulong, target));
+
+ /*
+ * Gateway.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ false));
+
+ switch (gateway) {
+ case 0:
+ if (strcmp(DNS_AS_STR(token), ".") != 0) {
+ RETTOK(DNS_R_SYNTAX);
+ }
+ break;
+
+ case 1:
+ if (inet_pton(AF_INET, DNS_AS_STR(token), &addr) != 1) {
+ RETTOK(DNS_R_BADDOTTEDQUAD);
+ }
+ isc_buffer_availableregion(target, &region);
+ if (region.length < 4) {
+ return (ISC_R_NOSPACE);
+ }
+ memmove(region.base, &addr, 4);
+ isc_buffer_add(target, 4);
+ break;
+
+ case 2:
+ if (inet_pton(AF_INET6, DNS_AS_STR(token), addr6) != 1) {
+ RETTOK(DNS_R_BADAAAA);
+ }
+ isc_buffer_availableregion(target, &region);
+ if (region.length < 16) {
+ return (ISC_R_NOSPACE);
+ }
+ memmove(region.base, addr6, 16);
+ isc_buffer_add(target, 16);
+ break;
+
+ case 3:
+ dns_name_init(&name, NULL);
+ buffer_fromregion(&buffer, &token.value.as_region);
+ if (origin == NULL) {
+ origin = dns_rootname;
+ }
+ RETTOK(dns_name_fromtext(&name, &buffer, origin, options,
+ target));
+ break;
+ }
+
+ /*
+ * Public key.
+ */
+ return (isc_base64_tobuffer(lexer, target, -2));
+}
+
+static isc_result_t
+totext_ipseckey(ARGS_TOTEXT) {
+ isc_region_t region;
+ dns_name_t name;
+ char buf[sizeof("255 ")];
+ unsigned short num;
+ unsigned short gateway;
+
+ REQUIRE(rdata->type == dns_rdatatype_ipseckey);
+ REQUIRE(rdata->length >= 3);
+
+ dns_name_init(&name, NULL);
+
+ if (rdata->data[1] > 3U) {
+ return (ISC_R_NOTIMPLEMENTED);
+ }
+
+ if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) {
+ RETERR(str_totext("( ", target));
+ }
+
+ /*
+ * Precedence.
+ */
+ dns_rdata_toregion(rdata, &region);
+ num = uint8_fromregion(&region);
+ isc_region_consume(&region, 1);
+ snprintf(buf, sizeof(buf), "%u ", num);
+ RETERR(str_totext(buf, target));
+
+ /*
+ * Gateway type.
+ */
+ gateway = uint8_fromregion(&region);
+ isc_region_consume(&region, 1);
+ snprintf(buf, sizeof(buf), "%u ", gateway);
+ RETERR(str_totext(buf, target));
+
+ /*
+ * Algorithm.
+ */
+ num = uint8_fromregion(&region);
+ isc_region_consume(&region, 1);
+ snprintf(buf, sizeof(buf), "%u ", num);
+ RETERR(str_totext(buf, target));
+
+ /*
+ * Gateway.
+ */
+ switch (gateway) {
+ case 0:
+ RETERR(str_totext(".", target));
+ break;
+
+ case 1:
+ RETERR(inet_totext(AF_INET, tctx->flags, &region, target));
+ isc_region_consume(&region, 4);
+ break;
+
+ case 2:
+ RETERR(inet_totext(AF_INET6, tctx->flags, &region, target));
+ isc_region_consume(&region, 16);
+ break;
+
+ case 3:
+ dns_name_fromregion(&name, &region);
+ RETERR(dns_name_totext(&name, false, target));
+ isc_region_consume(&region, name_length(&name));
+ break;
+ }
+
+ /*
+ * Key.
+ */
+ if (region.length > 0U) {
+ RETERR(str_totext(tctx->linebreak, target));
+ if (tctx->width == 0) { /* No splitting */
+ RETERR(isc_base64_totext(&region, 60, "", target));
+ } else {
+ RETERR(isc_base64_totext(&region, tctx->width - 2,
+ tctx->linebreak, target));
+ }
+ }
+
+ if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) {
+ RETERR(str_totext(" )", target));
+ }
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+fromwire_ipseckey(ARGS_FROMWIRE) {
+ dns_name_t name;
+ isc_region_t region;
+
+ REQUIRE(type == dns_rdatatype_ipseckey);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ dns_decompress_setmethods(dctx, DNS_COMPRESS_NONE);
+
+ dns_name_init(&name, NULL);
+
+ isc_buffer_activeregion(source, &region);
+ if (region.length < 3) {
+ return (ISC_R_UNEXPECTEDEND);
+ }
+
+ switch (region.base[1]) {
+ case 0:
+ if (region.length < 4) {
+ return (ISC_R_UNEXPECTEDEND);
+ }
+ isc_buffer_forward(source, region.length);
+ return (mem_tobuffer(target, region.base, region.length));
+
+ case 1:
+ if (region.length < 8) {
+ return (ISC_R_UNEXPECTEDEND);
+ }
+ isc_buffer_forward(source, region.length);
+ return (mem_tobuffer(target, region.base, region.length));
+
+ case 2:
+ if (region.length < 20) {
+ return (ISC_R_UNEXPECTEDEND);
+ }
+ isc_buffer_forward(source, region.length);
+ return (mem_tobuffer(target, region.base, region.length));
+
+ case 3:
+ RETERR(mem_tobuffer(target, region.base, 3));
+ isc_buffer_forward(source, 3);
+ RETERR(dns_name_fromwire(&name, source, dctx, options, target));
+ isc_buffer_activeregion(source, &region);
+ isc_buffer_forward(source, region.length);
+ if (region.length < 1) {
+ return (ISC_R_UNEXPECTEDEND);
+ }
+ return (mem_tobuffer(target, region.base, region.length));
+
+ default:
+ return (ISC_R_NOTIMPLEMENTED);
+ }
+}
+
+static isc_result_t
+towire_ipseckey(ARGS_TOWIRE) {
+ isc_region_t region;
+
+ REQUIRE(rdata->type == dns_rdatatype_ipseckey);
+ REQUIRE(rdata->length != 0);
+
+ UNUSED(cctx);
+
+ dns_rdata_toregion(rdata, &region);
+ return (mem_tobuffer(target, region.base, region.length));
+}
+
+static int
+compare_ipseckey(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_ipseckey);
+ REQUIRE(rdata1->length >= 3);
+ REQUIRE(rdata2->length >= 3);
+
+ dns_rdata_toregion(rdata1, &region1);
+ dns_rdata_toregion(rdata2, &region2);
+
+ return (isc_region_compare(&region1, &region2));
+}
+
+static isc_result_t
+fromstruct_ipseckey(ARGS_FROMSTRUCT) {
+ dns_rdata_ipseckey_t *ipseckey = source;
+ isc_region_t region;
+ uint32_t n;
+
+ REQUIRE(type == dns_rdatatype_ipseckey);
+ REQUIRE(ipseckey != NULL);
+ REQUIRE(ipseckey->common.rdtype == type);
+ REQUIRE(ipseckey->common.rdclass == rdclass);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ if (ipseckey->gateway_type > 3U) {
+ return (ISC_R_NOTIMPLEMENTED);
+ }
+
+ RETERR(uint8_tobuffer(ipseckey->precedence, target));
+ RETERR(uint8_tobuffer(ipseckey->gateway_type, target));
+ RETERR(uint8_tobuffer(ipseckey->algorithm, target));
+
+ switch (ipseckey->gateway_type) {
+ case 0:
+ break;
+
+ case 1:
+ n = ntohl(ipseckey->in_addr.s_addr);
+ RETERR(uint32_tobuffer(n, target));
+ break;
+
+ case 2:
+ RETERR(mem_tobuffer(target, ipseckey->in6_addr.s6_addr, 16));
+ break;
+
+ case 3:
+ dns_name_toregion(&ipseckey->gateway, &region);
+ RETERR(isc_buffer_copyregion(target, &region));
+ break;
+ }
+
+ return (mem_tobuffer(target, ipseckey->key, ipseckey->keylength));
+}
+
+static isc_result_t
+tostruct_ipseckey(ARGS_TOSTRUCT) {
+ isc_region_t region;
+ dns_rdata_ipseckey_t *ipseckey = target;
+ dns_name_t name;
+ uint32_t n;
+
+ REQUIRE(rdata->type == dns_rdatatype_ipseckey);
+ REQUIRE(ipseckey != NULL);
+ REQUIRE(rdata->length >= 3);
+
+ if (rdata->data[1] > 3U) {
+ return (ISC_R_NOTIMPLEMENTED);
+ }
+
+ ipseckey->common.rdclass = rdata->rdclass;
+ ipseckey->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&ipseckey->common, link);
+
+ dns_name_init(&name, NULL);
+ dns_rdata_toregion(rdata, &region);
+
+ ipseckey->precedence = uint8_fromregion(&region);
+ isc_region_consume(&region, 1);
+
+ ipseckey->gateway_type = uint8_fromregion(&region);
+ isc_region_consume(&region, 1);
+
+ ipseckey->algorithm = uint8_fromregion(&region);
+ isc_region_consume(&region, 1);
+
+ switch (ipseckey->gateway_type) {
+ case 0:
+ break;
+
+ case 1:
+ n = uint32_fromregion(&region);
+ ipseckey->in_addr.s_addr = htonl(n);
+ isc_region_consume(&region, 4);
+ break;
+
+ case 2:
+ memmove(ipseckey->in6_addr.s6_addr, region.base, 16);
+ isc_region_consume(&region, 16);
+ break;
+
+ case 3:
+ dns_name_init(&ipseckey->gateway, NULL);
+ dns_name_fromregion(&name, &region);
+ name_duporclone(&name, mctx, &ipseckey->gateway);
+ isc_region_consume(&region, name_length(&name));
+ break;
+ }
+
+ ipseckey->keylength = region.length;
+ if (ipseckey->keylength != 0U) {
+ ipseckey->key = mem_maybedup(mctx, region.base,
+ ipseckey->keylength);
+ if (ipseckey->key == NULL) {
+ if (ipseckey->gateway_type == 3) {
+ dns_name_free(&ipseckey->gateway,
+ ipseckey->mctx);
+ }
+ return (ISC_R_NOMEMORY);
+ }
+ } else {
+ ipseckey->key = NULL;
+ }
+
+ ipseckey->mctx = mctx;
+ return (ISC_R_SUCCESS);
+}
+
+static void
+freestruct_ipseckey(ARGS_FREESTRUCT) {
+ dns_rdata_ipseckey_t *ipseckey = source;
+
+ REQUIRE(ipseckey != NULL);
+ REQUIRE(ipseckey->common.rdtype == dns_rdatatype_ipseckey);
+
+ if (ipseckey->mctx == NULL) {
+ return;
+ }
+
+ if (ipseckey->gateway_type == 3) {
+ dns_name_free(&ipseckey->gateway, ipseckey->mctx);
+ }
+
+ if (ipseckey->key != NULL) {
+ isc_mem_free(ipseckey->mctx, ipseckey->key);
+ }
+
+ ipseckey->mctx = NULL;
+}
+
+static isc_result_t
+additionaldata_ipseckey(ARGS_ADDLDATA) {
+ REQUIRE(rdata->type == dns_rdatatype_ipseckey);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(add);
+ UNUSED(arg);
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+digest_ipseckey(ARGS_DIGEST) {
+ isc_region_t region;
+
+ REQUIRE(rdata->type == dns_rdatatype_ipseckey);
+
+ dns_rdata_toregion(rdata, &region);
+ return ((digest)(arg, &region));
+}
+
+static bool
+checkowner_ipseckey(ARGS_CHECKOWNER) {
+ REQUIRE(type == dns_rdatatype_ipseckey);
+
+ UNUSED(name);
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (true);
+}
+
+static bool
+checknames_ipseckey(ARGS_CHECKNAMES) {
+ REQUIRE(rdata->type == dns_rdatatype_ipseckey);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(bad);
+
+ return (true);
+}
+
+static int
+casecompare_ipseckey(ARGS_COMPARE) {
+ isc_region_t region1;
+ isc_region_t region2;
+ dns_name_t name1;
+ dns_name_t name2;
+ int order;
+
+ REQUIRE(rdata1->type == rdata2->type);
+ REQUIRE(rdata1->rdclass == rdata2->rdclass);
+ REQUIRE(rdata1->type == dns_rdatatype_ipseckey);
+ REQUIRE(rdata1->length >= 3);
+ REQUIRE(rdata2->length >= 3);
+
+ dns_rdata_toregion(rdata1, &region1);
+ dns_rdata_toregion(rdata2, &region2);
+
+ if (memcmp(region1.base, region2.base, 3) != 0 || region1.base[1] != 3)
+ {
+ return (isc_region_compare(&region1, &region2));
+ }
+
+ dns_name_init(&name1, NULL);
+ dns_name_init(&name2, NULL);
+
+ isc_region_consume(&region1, 3);
+ isc_region_consume(&region2, 3);
+
+ dns_name_fromregion(&name1, &region1);
+ dns_name_fromregion(&name2, &region2);
+
+ order = dns_name_rdatacompare(&name1, &name2);
+ if (order != 0) {
+ return (order);
+ }
+
+ isc_region_consume(&region1, name_length(&name1));
+ isc_region_consume(&region2, name_length(&name2));
+
+ return (isc_region_compare(&region1, &region2));
+}
+
+#endif /* RDATA_GENERIC_IPSECKEY_45_C */
diff --git a/lib/dns/rdata/generic/ipseckey_45.h b/lib/dns/rdata/generic/ipseckey_45.h
new file mode 100644
index 0000000..829e9b4
--- /dev/null
+++ b/lib/dns/rdata/generic/ipseckey_45.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
+
+typedef struct dns_rdata_ipseckey {
+ dns_rdatacommon_t common;
+ isc_mem_t *mctx;
+ uint8_t precedence;
+ uint8_t gateway_type;
+ uint8_t algorithm;
+ struct in_addr in_addr; /* gateway type 1 */
+ struct in6_addr in6_addr; /* gateway type 2 */
+ dns_name_t gateway; /* gateway type 3 */
+ unsigned char *key;
+ uint16_t keylength;
+} dns_rdata_ipseckey_t;
diff --git a/lib/dns/rdata/generic/isdn_20.c b/lib/dns/rdata/generic/isdn_20.c
new file mode 100644
index 0000000..8218d06
--- /dev/null
+++ b/lib/dns/rdata/generic/isdn_20.c
@@ -0,0 +1,248 @@
+/*
+ * 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.
+ */
+
+/* RFC1183 */
+
+#ifndef RDATA_GENERIC_ISDN_20_C
+#define RDATA_GENERIC_ISDN_20_C
+
+#define RRTYPE_ISDN_ATTRIBUTES (0)
+
+static isc_result_t
+fromtext_isdn(ARGS_FROMTEXT) {
+ isc_token_t token;
+
+ REQUIRE(type == dns_rdatatype_isdn);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(origin);
+ UNUSED(options);
+ UNUSED(callbacks);
+
+ /* ISDN-address */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_qstring,
+ false));
+ RETTOK(txt_fromtext(&token.value.as_textregion, target));
+
+ /* sa: optional */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_qstring,
+ true));
+ if (token.type != isc_tokentype_string &&
+ token.type != isc_tokentype_qstring)
+ {
+ isc_lex_ungettoken(lexer, &token);
+ return (ISC_R_SUCCESS);
+ }
+ RETTOK(txt_fromtext(&token.value.as_textregion, target));
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+totext_isdn(ARGS_TOTEXT) {
+ isc_region_t region;
+
+ REQUIRE(rdata->type == dns_rdatatype_isdn);
+ REQUIRE(rdata->length != 0);
+
+ UNUSED(tctx);
+
+ dns_rdata_toregion(rdata, &region);
+ RETERR(txt_totext(&region, true, target));
+ if (region.length == 0) {
+ return (ISC_R_SUCCESS);
+ }
+ RETERR(str_totext(" ", target));
+ return (txt_totext(&region, true, target));
+}
+
+static isc_result_t
+fromwire_isdn(ARGS_FROMWIRE) {
+ REQUIRE(type == dns_rdatatype_isdn);
+
+ UNUSED(type);
+ UNUSED(dctx);
+ UNUSED(rdclass);
+ UNUSED(options);
+
+ RETERR(txt_fromwire(source, target));
+ if (buffer_empty(source)) {
+ return (ISC_R_SUCCESS);
+ }
+ return (txt_fromwire(source, target));
+}
+
+static isc_result_t
+towire_isdn(ARGS_TOWIRE) {
+ UNUSED(cctx);
+
+ REQUIRE(rdata->type == dns_rdatatype_isdn);
+ REQUIRE(rdata->length != 0);
+
+ return (mem_tobuffer(target, rdata->data, rdata->length));
+}
+
+static int
+compare_isdn(ARGS_COMPARE) {
+ isc_region_t r1;
+ isc_region_t r2;
+
+ REQUIRE(rdata1->type == rdata2->type);
+ REQUIRE(rdata1->rdclass == rdata2->rdclass);
+ REQUIRE(rdata1->type == dns_rdatatype_isdn);
+ REQUIRE(rdata1->length != 0);
+ REQUIRE(rdata2->length != 0);
+
+ dns_rdata_toregion(rdata1, &r1);
+ dns_rdata_toregion(rdata2, &r2);
+ return (isc_region_compare(&r1, &r2));
+}
+
+static isc_result_t
+fromstruct_isdn(ARGS_FROMSTRUCT) {
+ dns_rdata_isdn_t *isdn = source;
+
+ REQUIRE(type == dns_rdatatype_isdn);
+ REQUIRE(isdn != NULL);
+ REQUIRE(isdn->common.rdtype == type);
+ REQUIRE(isdn->common.rdclass == rdclass);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ RETERR(uint8_tobuffer(isdn->isdn_len, target));
+ RETERR(mem_tobuffer(target, isdn->isdn, isdn->isdn_len));
+ if (isdn->subaddress == NULL) {
+ return (ISC_R_SUCCESS);
+ }
+ RETERR(uint8_tobuffer(isdn->subaddress_len, target));
+ return (mem_tobuffer(target, isdn->subaddress, isdn->subaddress_len));
+}
+
+static isc_result_t
+tostruct_isdn(ARGS_TOSTRUCT) {
+ dns_rdata_isdn_t *isdn = target;
+ isc_region_t r;
+
+ REQUIRE(rdata->type == dns_rdatatype_isdn);
+ REQUIRE(isdn != NULL);
+ REQUIRE(rdata->length != 0);
+
+ isdn->common.rdclass = rdata->rdclass;
+ isdn->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&isdn->common, link);
+
+ dns_rdata_toregion(rdata, &r);
+
+ isdn->isdn_len = uint8_fromregion(&r);
+ isc_region_consume(&r, 1);
+ isdn->isdn = mem_maybedup(mctx, r.base, isdn->isdn_len);
+ if (isdn->isdn == NULL) {
+ return (ISC_R_NOMEMORY);
+ }
+ isc_region_consume(&r, isdn->isdn_len);
+
+ if (r.length == 0) {
+ isdn->subaddress_len = 0;
+ isdn->subaddress = NULL;
+ } else {
+ isdn->subaddress_len = uint8_fromregion(&r);
+ isc_region_consume(&r, 1);
+ isdn->subaddress = mem_maybedup(mctx, r.base,
+ isdn->subaddress_len);
+ if (isdn->subaddress == NULL) {
+ goto cleanup;
+ }
+ }
+
+ isdn->mctx = mctx;
+ return (ISC_R_SUCCESS);
+
+cleanup:
+ if (mctx != NULL && isdn->isdn != NULL) {
+ isc_mem_free(mctx, isdn->isdn);
+ }
+ return (ISC_R_NOMEMORY);
+}
+
+static void
+freestruct_isdn(ARGS_FREESTRUCT) {
+ dns_rdata_isdn_t *isdn = source;
+
+ REQUIRE(isdn != NULL);
+
+ if (isdn->mctx == NULL) {
+ return;
+ }
+
+ if (isdn->isdn != NULL) {
+ isc_mem_free(isdn->mctx, isdn->isdn);
+ }
+ if (isdn->subaddress != NULL) {
+ isc_mem_free(isdn->mctx, isdn->subaddress);
+ }
+ isdn->mctx = NULL;
+}
+
+static isc_result_t
+additionaldata_isdn(ARGS_ADDLDATA) {
+ REQUIRE(rdata->type == dns_rdatatype_isdn);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(add);
+ UNUSED(arg);
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+digest_isdn(ARGS_DIGEST) {
+ isc_region_t r;
+
+ REQUIRE(rdata->type == dns_rdatatype_isdn);
+
+ dns_rdata_toregion(rdata, &r);
+
+ return ((digest)(arg, &r));
+}
+
+static bool
+checkowner_isdn(ARGS_CHECKOWNER) {
+ REQUIRE(type == dns_rdatatype_isdn);
+
+ UNUSED(name);
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (true);
+}
+
+static bool
+checknames_isdn(ARGS_CHECKNAMES) {
+ REQUIRE(rdata->type == dns_rdatatype_isdn);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(bad);
+
+ return (true);
+}
+
+static int
+casecompare_isdn(ARGS_COMPARE) {
+ return (compare_isdn(rdata1, rdata2));
+}
+
+#endif /* RDATA_GENERIC_ISDN_20_C */
diff --git a/lib/dns/rdata/generic/isdn_20.h b/lib/dns/rdata/generic/isdn_20.h
new file mode 100644
index 0000000..d18aa63
--- /dev/null
+++ b/lib/dns/rdata/generic/isdn_20.h
@@ -0,0 +1,26 @@
+/*
+ * 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
+
+/*!
+ * \brief Per RFC1183 */
+
+typedef struct dns_rdata_isdn {
+ dns_rdatacommon_t common;
+ isc_mem_t *mctx;
+ char *isdn;
+ char *subaddress;
+ uint8_t isdn_len;
+ uint8_t subaddress_len;
+} dns_rdata_isdn_t;
diff --git a/lib/dns/rdata/generic/key_25.c b/lib/dns/rdata/generic/key_25.c
new file mode 100644
index 0000000..32c2db3
--- /dev/null
+++ b/lib/dns/rdata/generic/key_25.c
@@ -0,0 +1,469 @@
+/*
+ * 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.
+ */
+
+/* RFC2535 */
+
+#ifndef RDATA_GENERIC_KEY_25_C
+#define RDATA_GENERIC_KEY_25_C
+
+#include <dst/dst.h>
+
+#define RRTYPE_KEY_ATTRIBUTES \
+ (DNS_RDATATYPEATTR_ATCNAME | DNS_RDATATYPEATTR_ZONECUTAUTH)
+
+/*
+ * RFC 2535 section 3.1.2 says that if bits 0-1 of the Flags field are
+ * both set, it means there is no key information and the RR stops after
+ * the algorithm octet. However, this only applies to KEY records, as
+ * indicated by the specifications of the RR types based on KEY:
+ *
+ * CDNSKEY - RFC 7344
+ * DNSKEY - RFC 4034
+ * RKEY - draft-reid-dnsext-rkey-00
+ */
+static bool
+generic_key_nokey(dns_rdatatype_t type, unsigned int flags) {
+ switch (type) {
+ case dns_rdatatype_cdnskey:
+ case dns_rdatatype_dnskey:
+ case dns_rdatatype_rkey:
+ return (false);
+ case dns_rdatatype_key:
+ default:
+ return ((flags & DNS_KEYFLAG_TYPEMASK) == DNS_KEYTYPE_NOKEY);
+ }
+}
+
+static isc_result_t
+generic_fromtext_key(ARGS_FROMTEXT) {
+ isc_token_t token;
+ dns_secalg_t alg;
+ dns_secproto_t proto;
+ dns_keyflags_t flags;
+
+ UNUSED(rdclass);
+ UNUSED(origin);
+ UNUSED(options);
+ UNUSED(callbacks);
+
+ /* flags */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ false));
+ RETTOK(dns_keyflags_fromtext(&flags, &token.value.as_textregion));
+ if (type == dns_rdatatype_rkey && flags != 0U) {
+ RETTOK(DNS_R_FORMERR);
+ }
+ RETERR(uint16_tobuffer(flags, target));
+
+ /* protocol */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ false));
+ RETTOK(dns_secproto_fromtext(&proto, &token.value.as_textregion));
+ RETERR(mem_tobuffer(target, &proto, 1));
+
+ /* algorithm */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ false));
+ RETTOK(dns_secalg_fromtext(&alg, &token.value.as_textregion));
+ RETERR(mem_tobuffer(target, &alg, 1));
+
+ /* No Key? */
+ if (generic_key_nokey(type, flags)) {
+ return (ISC_R_SUCCESS);
+ }
+
+ return (isc_base64_tobuffer(lexer, target, -2));
+}
+
+static isc_result_t
+generic_totext_key(ARGS_TOTEXT) {
+ isc_region_t sr;
+ char buf[sizeof("[key id = 64000]")];
+ unsigned int flags;
+ unsigned char algorithm;
+ char algbuf[DNS_NAME_FORMATSIZE];
+ const char *keyinfo;
+ isc_region_t tmpr;
+
+ REQUIRE(rdata->length != 0);
+
+ dns_rdata_toregion(rdata, &sr);
+
+ /* flags */
+ flags = uint16_fromregion(&sr);
+ isc_region_consume(&sr, 2);
+ snprintf(buf, sizeof(buf), "%u", flags);
+ RETERR(str_totext(buf, target));
+ RETERR(str_totext(" ", target));
+ if ((flags & DNS_KEYFLAG_KSK) != 0) {
+ if (flags & DNS_KEYFLAG_REVOKE) {
+ keyinfo = "revoked KSK";
+ } else {
+ keyinfo = "KSK";
+ }
+ } else {
+ keyinfo = "ZSK";
+ }
+
+ /* protocol */
+ snprintf(buf, sizeof(buf), "%u", sr.base[0]);
+ isc_region_consume(&sr, 1);
+ RETERR(str_totext(buf, target));
+ RETERR(str_totext(" ", target));
+
+ /* algorithm */
+ algorithm = sr.base[0];
+ snprintf(buf, sizeof(buf), "%u", algorithm);
+ isc_region_consume(&sr, 1);
+ RETERR(str_totext(buf, target));
+
+ /* No Key? */
+ if (generic_key_nokey(rdata->type, flags)) {
+ return (ISC_R_SUCCESS);
+ }
+
+ if ((tctx->flags & DNS_STYLEFLAG_RRCOMMENT) != 0 &&
+ algorithm == DNS_KEYALG_PRIVATEDNS)
+ {
+ dns_name_t name;
+ dns_name_init(&name, NULL);
+ dns_name_fromregion(&name, &sr);
+ dns_name_format(&name, algbuf, sizeof(algbuf));
+ } else {
+ dns_secalg_format((dns_secalg_t)algorithm, algbuf,
+ sizeof(algbuf));
+ }
+
+ /* key */
+ if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) {
+ RETERR(str_totext(" (", target));
+ }
+ RETERR(str_totext(tctx->linebreak, target));
+
+ if ((tctx->flags & DNS_STYLEFLAG_NOCRYPTO) == 0) {
+ if (tctx->width == 0) { /* No splitting */
+ RETERR(isc_base64_totext(&sr, 60, "", target));
+ } else {
+ RETERR(isc_base64_totext(&sr, tctx->width - 2,
+ tctx->linebreak, target));
+ }
+ } else {
+ dns_rdata_toregion(rdata, &tmpr);
+ snprintf(buf, sizeof(buf), "[key id = %u]",
+ dst_region_computeid(&tmpr));
+ RETERR(str_totext(buf, target));
+ }
+
+ if ((tctx->flags & DNS_STYLEFLAG_RRCOMMENT) != 0) {
+ RETERR(str_totext(tctx->linebreak, target));
+ } else if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) {
+ RETERR(str_totext(" ", target));
+ }
+
+ if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) {
+ RETERR(str_totext(")", target));
+ }
+
+ if ((tctx->flags & DNS_STYLEFLAG_RRCOMMENT) != 0) {
+ if (rdata->type == dns_rdatatype_dnskey ||
+ rdata->type == dns_rdatatype_cdnskey)
+ {
+ RETERR(str_totext(" ; ", target));
+ RETERR(str_totext(keyinfo, target));
+ }
+ RETERR(str_totext("; alg = ", target));
+ RETERR(str_totext(algbuf, target));
+ RETERR(str_totext(" ; key id = ", target));
+ dns_rdata_toregion(rdata, &tmpr);
+ snprintf(buf, sizeof(buf), "%u", dst_region_computeid(&tmpr));
+ RETERR(str_totext(buf, target));
+ }
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+generic_fromwire_key(ARGS_FROMWIRE) {
+ unsigned char algorithm;
+ uint16_t flags;
+ isc_region_t sr;
+
+ UNUSED(rdclass);
+ UNUSED(dctx);
+ UNUSED(options);
+
+ isc_buffer_activeregion(source, &sr);
+ if (sr.length < 4) {
+ return (ISC_R_UNEXPECTEDEND);
+ }
+ flags = (sr.base[0] << 8) | sr.base[1];
+
+ if (type == dns_rdatatype_rkey && flags != 0U) {
+ return (DNS_R_FORMERR);
+ }
+
+ algorithm = sr.base[3];
+ RETERR(mem_tobuffer(target, sr.base, 4));
+ isc_region_consume(&sr, 4);
+ isc_buffer_forward(source, 4);
+
+ if (generic_key_nokey(type, flags)) {
+ return (ISC_R_SUCCESS);
+ }
+ if (sr.length == 0) {
+ return (ISC_R_UNEXPECTEDEND);
+ }
+
+ if (algorithm == DNS_KEYALG_PRIVATEDNS) {
+ dns_name_t name;
+ dns_decompress_setmethods(dctx, DNS_COMPRESS_NONE);
+ dns_name_init(&name, NULL);
+ RETERR(dns_name_fromwire(&name, source, dctx, options, target));
+ }
+
+ isc_buffer_activeregion(source, &sr);
+ isc_buffer_forward(source, sr.length);
+ return (mem_tobuffer(target, sr.base, sr.length));
+}
+
+static isc_result_t
+fromtext_key(ARGS_FROMTEXT) {
+ REQUIRE(type == dns_rdatatype_key);
+
+ return (generic_fromtext_key(CALL_FROMTEXT));
+}
+
+static isc_result_t
+totext_key(ARGS_TOTEXT) {
+ REQUIRE(rdata != NULL);
+ REQUIRE(rdata->type == dns_rdatatype_key);
+
+ return (generic_totext_key(CALL_TOTEXT));
+}
+
+static isc_result_t
+fromwire_key(ARGS_FROMWIRE) {
+ REQUIRE(type == dns_rdatatype_key);
+
+ return (generic_fromwire_key(CALL_FROMWIRE));
+}
+
+static isc_result_t
+towire_key(ARGS_TOWIRE) {
+ isc_region_t sr;
+
+ REQUIRE(rdata != NULL);
+ REQUIRE(rdata->type == dns_rdatatype_key);
+ REQUIRE(rdata->length != 0);
+
+ UNUSED(cctx);
+
+ dns_rdata_toregion(rdata, &sr);
+ return (mem_tobuffer(target, sr.base, sr.length));
+}
+
+static int
+compare_key(ARGS_COMPARE) {
+ isc_region_t r1;
+ isc_region_t r2;
+
+ REQUIRE(rdata1 != NULL);
+ REQUIRE(rdata2 != NULL);
+ REQUIRE(rdata1->type == rdata2->type);
+ REQUIRE(rdata1->rdclass == rdata2->rdclass);
+ REQUIRE(rdata1->type == dns_rdatatype_key);
+ REQUIRE(rdata1->length != 0);
+ REQUIRE(rdata2->length != 0);
+
+ dns_rdata_toregion(rdata1, &r1);
+ dns_rdata_toregion(rdata2, &r2);
+ return (isc_region_compare(&r1, &r2));
+}
+
+static isc_result_t
+generic_fromstruct_key(ARGS_FROMSTRUCT) {
+ dns_rdata_key_t *key = source;
+
+ REQUIRE(key != NULL);
+ REQUIRE(key->common.rdtype == type);
+ REQUIRE(key->common.rdclass == rdclass);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ if (type == dns_rdatatype_rkey) {
+ INSIST(key->flags == 0U);
+ }
+
+ /* Flags */
+ RETERR(uint16_tobuffer(key->flags, target));
+
+ /* Protocol */
+ RETERR(uint8_tobuffer(key->protocol, target));
+
+ /* Algorithm */
+ RETERR(uint8_tobuffer(key->algorithm, target));
+
+ /* Data */
+ return (mem_tobuffer(target, key->data, key->datalen));
+}
+
+static isc_result_t
+generic_tostruct_key(ARGS_TOSTRUCT) {
+ dns_rdata_key_t *key = target;
+ isc_region_t sr;
+
+ REQUIRE(key != NULL);
+ REQUIRE(rdata->length != 0);
+
+ REQUIRE(key != NULL);
+ REQUIRE(key->common.rdclass == rdata->rdclass);
+ REQUIRE(key->common.rdtype == rdata->type);
+ REQUIRE(!ISC_LINK_LINKED(&key->common, link));
+
+ dns_rdata_toregion(rdata, &sr);
+
+ /* Flags */
+ if (sr.length < 2) {
+ return (ISC_R_UNEXPECTEDEND);
+ }
+ key->flags = uint16_fromregion(&sr);
+ isc_region_consume(&sr, 2);
+
+ /* Protocol */
+ if (sr.length < 1) {
+ return (ISC_R_UNEXPECTEDEND);
+ }
+ key->protocol = uint8_fromregion(&sr);
+ isc_region_consume(&sr, 1);
+
+ /* Algorithm */
+ if (sr.length < 1) {
+ return (ISC_R_UNEXPECTEDEND);
+ }
+ key->algorithm = uint8_fromregion(&sr);
+ isc_region_consume(&sr, 1);
+
+ /* Data */
+ key->datalen = sr.length;
+ key->data = mem_maybedup(mctx, sr.base, key->datalen);
+ if (key->data == NULL) {
+ return (ISC_R_NOMEMORY);
+ }
+
+ key->mctx = mctx;
+ return (ISC_R_SUCCESS);
+}
+
+static void
+generic_freestruct_key(ARGS_FREESTRUCT) {
+ dns_rdata_key_t *key = (dns_rdata_key_t *)source;
+
+ REQUIRE(key != NULL);
+
+ if (key->mctx == NULL) {
+ return;
+ }
+
+ if (key->data != NULL) {
+ isc_mem_free(key->mctx, key->data);
+ }
+ key->mctx = NULL;
+}
+
+static isc_result_t
+fromstruct_key(ARGS_FROMSTRUCT) {
+ REQUIRE(type == dns_rdatatype_key);
+
+ return (generic_fromstruct_key(CALL_FROMSTRUCT));
+}
+
+static isc_result_t
+tostruct_key(ARGS_TOSTRUCT) {
+ dns_rdata_key_t *key = target;
+
+ REQUIRE(key != NULL);
+ REQUIRE(rdata != NULL);
+ REQUIRE(rdata->type == dns_rdatatype_key);
+
+ key->common.rdclass = rdata->rdclass;
+ key->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&key->common, link);
+
+ return (generic_tostruct_key(CALL_TOSTRUCT));
+}
+
+static void
+freestruct_key(ARGS_FREESTRUCT) {
+ dns_rdata_key_t *key = (dns_rdata_key_t *)source;
+
+ REQUIRE(key != NULL);
+ REQUIRE(key->common.rdtype == dns_rdatatype_key);
+
+ generic_freestruct_key(source);
+}
+
+static isc_result_t
+additionaldata_key(ARGS_ADDLDATA) {
+ REQUIRE(rdata != NULL);
+ REQUIRE(rdata->type == dns_rdatatype_key);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(add);
+ UNUSED(arg);
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+digest_key(ARGS_DIGEST) {
+ isc_region_t r;
+
+ REQUIRE(rdata != NULL);
+ REQUIRE(rdata->type == dns_rdatatype_key);
+
+ dns_rdata_toregion(rdata, &r);
+
+ return ((digest)(arg, &r));
+}
+
+static bool
+checkowner_key(ARGS_CHECKOWNER) {
+ REQUIRE(type == dns_rdatatype_key);
+
+ UNUSED(name);
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (true);
+}
+
+static bool
+checknames_key(ARGS_CHECKNAMES) {
+ REQUIRE(rdata != NULL);
+ REQUIRE(rdata->type == dns_rdatatype_key);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(bad);
+
+ return (true);
+}
+
+static int
+casecompare_key(ARGS_COMPARE) {
+ return (compare_key(rdata1, rdata2));
+}
+
+#endif /* RDATA_GENERIC_KEY_25_C */
diff --git a/lib/dns/rdata/generic/key_25.h b/lib/dns/rdata/generic/key_25.h
new file mode 100644
index 0000000..4702434
--- /dev/null
+++ b/lib/dns/rdata/generic/key_25.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
+
+/*!
+ * \brief Per RFC2535 */
+
+typedef struct dns_rdata_key {
+ dns_rdatacommon_t common;
+ isc_mem_t *mctx;
+ uint16_t flags;
+ dns_secproto_t protocol;
+ dns_secalg_t algorithm;
+ uint16_t datalen;
+ unsigned char *data;
+} dns_rdata_key_t;
diff --git a/lib/dns/rdata/generic/keydata_65533.c b/lib/dns/rdata/generic/keydata_65533.c
new file mode 100644
index 0000000..175afad
--- /dev/null
+++ b/lib/dns/rdata/generic/keydata_65533.c
@@ -0,0 +1,463 @@
+/*
+ * 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 GENERIC_KEYDATA_65533_C
+#define GENERIC_KEYDATA_65533_C 1
+
+#include <isc/stdtime.h>
+#include <isc/time.h>
+
+#include <dst/dst.h>
+
+#define RRTYPE_KEYDATA_ATTRIBUTES (0)
+
+static isc_result_t
+fromtext_keydata(ARGS_FROMTEXT) {
+ isc_token_t token;
+ dns_secalg_t alg;
+ dns_secproto_t proto;
+ dns_keyflags_t flags;
+ uint32_t refresh, addhd, removehd;
+
+ REQUIRE(type == dns_rdatatype_keydata);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(origin);
+ UNUSED(options);
+ UNUSED(callbacks);
+
+ /* refresh timer */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ false));
+ RETTOK(dns_time32_fromtext(DNS_AS_STR(token), &refresh));
+ RETERR(uint32_tobuffer(refresh, target));
+
+ /* add hold-down */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ false));
+ RETTOK(dns_time32_fromtext(DNS_AS_STR(token), &addhd));
+ RETERR(uint32_tobuffer(addhd, target));
+
+ /* remove hold-down */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ false));
+ RETTOK(dns_time32_fromtext(DNS_AS_STR(token), &removehd));
+ RETERR(uint32_tobuffer(removehd, target));
+
+ /* flags */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ false));
+ RETTOK(dns_keyflags_fromtext(&flags, &token.value.as_textregion));
+ RETERR(uint16_tobuffer(flags, target));
+
+ /* protocol */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ false));
+ RETTOK(dns_secproto_fromtext(&proto, &token.value.as_textregion));
+ RETERR(mem_tobuffer(target, &proto, 1));
+
+ /* algorithm */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ false));
+ RETTOK(dns_secalg_fromtext(&alg, &token.value.as_textregion));
+ RETERR(mem_tobuffer(target, &alg, 1));
+
+ /* Do we have a placeholder KEYDATA record? */
+ if (flags == 0 && proto == 0 && alg == 0) {
+ return (ISC_R_SUCCESS);
+ }
+
+ /* No Key? */
+ if ((flags & 0xc000) == 0xc000) {
+ return (ISC_R_SUCCESS);
+ }
+
+ return (isc_base64_tobuffer(lexer, target, -2));
+}
+
+static isc_result_t
+totext_keydata(ARGS_TOTEXT) {
+ isc_region_t sr;
+ char buf[sizeof("64000")];
+ unsigned int flags;
+ unsigned char proto, algorithm;
+ unsigned long refresh, add, deltime;
+ char algbuf[DNS_NAME_FORMATSIZE];
+ const char *keyinfo;
+
+ REQUIRE(rdata->type == dns_rdatatype_keydata);
+
+ if ((tctx->flags & DNS_STYLEFLAG_KEYDATA) == 0 || rdata->length < 16) {
+ return (unknown_totext(rdata, tctx, target));
+ }
+
+ dns_rdata_toregion(rdata, &sr);
+
+ /* refresh timer */
+ refresh = uint32_fromregion(&sr);
+ isc_region_consume(&sr, 4);
+ RETERR(dns_time32_totext(refresh, target));
+ RETERR(str_totext(" ", target));
+
+ /* add hold-down */
+ add = uint32_fromregion(&sr);
+ isc_region_consume(&sr, 4);
+ RETERR(dns_time32_totext(add, target));
+ RETERR(str_totext(" ", target));
+
+ /* remove hold-down */
+ deltime = uint32_fromregion(&sr);
+ isc_region_consume(&sr, 4);
+ RETERR(dns_time32_totext(deltime, target));
+ RETERR(str_totext(" ", target));
+
+ /* flags */
+ flags = uint16_fromregion(&sr);
+ isc_region_consume(&sr, 2);
+ snprintf(buf, sizeof(buf), "%u", flags);
+ RETERR(str_totext(buf, target));
+ RETERR(str_totext(" ", target));
+ if ((flags & DNS_KEYFLAG_KSK) != 0) {
+ if ((flags & DNS_KEYFLAG_REVOKE) != 0) {
+ keyinfo = "revoked KSK";
+ } else {
+ keyinfo = "KSK";
+ }
+ } else {
+ keyinfo = "ZSK";
+ }
+
+ /* protocol */
+ proto = sr.base[0];
+ snprintf(buf, sizeof(buf), "%u", proto);
+ isc_region_consume(&sr, 1);
+ RETERR(str_totext(buf, target));
+ RETERR(str_totext(" ", target));
+
+ /* algorithm */
+ algorithm = sr.base[0];
+ snprintf(buf, sizeof(buf), "%u", algorithm);
+ isc_region_consume(&sr, 1);
+ RETERR(str_totext(buf, target));
+
+ /* Do we have a placeholder KEYDATA record? */
+ if (flags == 0 && proto == 0 && algorithm == 0) {
+ if ((tctx->flags & DNS_STYLEFLAG_RRCOMMENT) != 0) {
+ RETERR(str_totext(" ; placeholder", target));
+ }
+ return (ISC_R_SUCCESS);
+ }
+
+ /* No Key? */
+ if ((flags & 0xc000) == 0xc000) {
+ return (ISC_R_SUCCESS);
+ }
+
+ /* key */
+ if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) {
+ RETERR(str_totext(" (", target));
+ }
+ RETERR(str_totext(tctx->linebreak, target));
+ if (tctx->width == 0) { /* No splitting */
+ RETERR(isc_base64_totext(&sr, 60, "", target));
+ } else {
+ RETERR(isc_base64_totext(&sr, tctx->width - 2, tctx->linebreak,
+ target));
+ }
+
+ if ((tctx->flags & DNS_STYLEFLAG_RRCOMMENT) != 0) {
+ RETERR(str_totext(tctx->linebreak, target));
+ } else if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) {
+ RETERR(str_totext(" ", target));
+ }
+
+ if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) {
+ RETERR(str_totext(")", target));
+ }
+
+ if ((tctx->flags & DNS_STYLEFLAG_RRCOMMENT) != 0) {
+ isc_region_t tmpr;
+ char rbuf[ISC_FORMATHTTPTIMESTAMP_SIZE];
+ char abuf[ISC_FORMATHTTPTIMESTAMP_SIZE];
+ char dbuf[ISC_FORMATHTTPTIMESTAMP_SIZE];
+ isc_time_t t;
+
+ RETERR(str_totext(" ; ", target));
+ RETERR(str_totext(keyinfo, target));
+ dns_secalg_format((dns_secalg_t)algorithm, algbuf,
+ sizeof(algbuf));
+ RETERR(str_totext("; alg = ", target));
+ RETERR(str_totext(algbuf, target));
+ RETERR(str_totext("; key id = ", target));
+ dns_rdata_toregion(rdata, &tmpr);
+ /* Skip over refresh, addhd, and removehd */
+ isc_region_consume(&tmpr, 12);
+ snprintf(buf, sizeof(buf), "%u", dst_region_computeid(&tmpr));
+ RETERR(str_totext(buf, target));
+
+ if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) {
+ isc_stdtime_t now;
+
+ isc_stdtime_get(&now);
+
+ RETERR(str_totext(tctx->linebreak, target));
+ RETERR(str_totext("; next refresh: ", target));
+ isc_time_set(&t, refresh, 0);
+ isc_time_formathttptimestamp(&t, rbuf, sizeof(rbuf));
+ RETERR(str_totext(rbuf, target));
+
+ if (add == 0U) {
+ RETERR(str_totext(tctx->linebreak, target));
+ RETERR(str_totext("; no trust", target));
+ } else {
+ RETERR(str_totext(tctx->linebreak, target));
+ if (add < now) {
+ RETERR(str_totext("; trusted since: ",
+ target));
+ } else {
+ RETERR(str_totext("; trust pending: ",
+ target));
+ }
+ isc_time_set(&t, add, 0);
+ isc_time_formathttptimestamp(&t, abuf,
+ sizeof(abuf));
+ RETERR(str_totext(abuf, target));
+ }
+
+ if (deltime != 0U) {
+ RETERR(str_totext(tctx->linebreak, target));
+ RETERR(str_totext("; removal pending: ",
+ target));
+ isc_time_set(&t, deltime, 0);
+ isc_time_formathttptimestamp(&t, dbuf,
+ sizeof(dbuf));
+ RETERR(str_totext(dbuf, target));
+ }
+ }
+ }
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+fromwire_keydata(ARGS_FROMWIRE) {
+ isc_region_t sr;
+
+ REQUIRE(type == dns_rdatatype_keydata);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(dctx);
+ UNUSED(options);
+
+ isc_buffer_activeregion(source, &sr);
+ isc_buffer_forward(source, sr.length);
+ return (mem_tobuffer(target, sr.base, sr.length));
+}
+
+static isc_result_t
+towire_keydata(ARGS_TOWIRE) {
+ isc_region_t sr;
+
+ REQUIRE(rdata->type == dns_rdatatype_keydata);
+
+ UNUSED(cctx);
+
+ dns_rdata_toregion(rdata, &sr);
+ return (mem_tobuffer(target, sr.base, sr.length));
+}
+
+static int
+compare_keydata(ARGS_COMPARE) {
+ isc_region_t r1;
+ isc_region_t r2;
+
+ REQUIRE(rdata1->type == rdata2->type);
+ REQUIRE(rdata1->rdclass == rdata2->rdclass);
+ REQUIRE(rdata1->type == dns_rdatatype_keydata);
+
+ dns_rdata_toregion(rdata1, &r1);
+ dns_rdata_toregion(rdata2, &r2);
+ return (isc_region_compare(&r1, &r2));
+}
+
+static isc_result_t
+fromstruct_keydata(ARGS_FROMSTRUCT) {
+ dns_rdata_keydata_t *keydata = source;
+
+ REQUIRE(type == dns_rdatatype_keydata);
+ REQUIRE(keydata != NULL);
+ REQUIRE(keydata->common.rdtype == type);
+ REQUIRE(keydata->common.rdclass == rdclass);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ /* Refresh timer */
+ RETERR(uint32_tobuffer(keydata->refresh, target));
+
+ /* Add hold-down */
+ RETERR(uint32_tobuffer(keydata->addhd, target));
+
+ /* Remove hold-down */
+ RETERR(uint32_tobuffer(keydata->removehd, target));
+
+ /* Flags */
+ RETERR(uint16_tobuffer(keydata->flags, target));
+
+ /* Protocol */
+ RETERR(uint8_tobuffer(keydata->protocol, target));
+
+ /* Algorithm */
+ RETERR(uint8_tobuffer(keydata->algorithm, target));
+
+ /* Data */
+ return (mem_tobuffer(target, keydata->data, keydata->datalen));
+}
+
+static isc_result_t
+tostruct_keydata(ARGS_TOSTRUCT) {
+ dns_rdata_keydata_t *keydata = target;
+ isc_region_t sr;
+
+ REQUIRE(rdata->type == dns_rdatatype_keydata);
+ REQUIRE(keydata != NULL);
+
+ keydata->common.rdclass = rdata->rdclass;
+ keydata->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&keydata->common, link);
+
+ dns_rdata_toregion(rdata, &sr);
+
+ /* Refresh timer */
+ if (sr.length < 4) {
+ return (ISC_R_UNEXPECTEDEND);
+ }
+ keydata->refresh = uint32_fromregion(&sr);
+ isc_region_consume(&sr, 4);
+
+ /* Add hold-down */
+ if (sr.length < 4) {
+ return (ISC_R_UNEXPECTEDEND);
+ }
+ keydata->addhd = uint32_fromregion(&sr);
+ isc_region_consume(&sr, 4);
+
+ /* Remove hold-down */
+ if (sr.length < 4) {
+ return (ISC_R_UNEXPECTEDEND);
+ }
+ keydata->removehd = uint32_fromregion(&sr);
+ isc_region_consume(&sr, 4);
+
+ /* Flags */
+ if (sr.length < 2) {
+ return (ISC_R_UNEXPECTEDEND);
+ }
+ keydata->flags = uint16_fromregion(&sr);
+ isc_region_consume(&sr, 2);
+
+ /* Protocol */
+ if (sr.length < 1) {
+ return (ISC_R_UNEXPECTEDEND);
+ }
+ keydata->protocol = uint8_fromregion(&sr);
+ isc_region_consume(&sr, 1);
+
+ /* Algorithm */
+ if (sr.length < 1) {
+ return (ISC_R_UNEXPECTEDEND);
+ }
+ keydata->algorithm = uint8_fromregion(&sr);
+ isc_region_consume(&sr, 1);
+
+ /* Data */
+ keydata->datalen = sr.length;
+ keydata->data = mem_maybedup(mctx, sr.base, keydata->datalen);
+ if (keydata->data == NULL) {
+ return (ISC_R_NOMEMORY);
+ }
+
+ keydata->mctx = mctx;
+ return (ISC_R_SUCCESS);
+}
+
+static void
+freestruct_keydata(ARGS_FREESTRUCT) {
+ dns_rdata_keydata_t *keydata = (dns_rdata_keydata_t *)source;
+
+ REQUIRE(keydata != NULL);
+ REQUIRE(keydata->common.rdtype == dns_rdatatype_keydata);
+
+ if (keydata->mctx == NULL) {
+ return;
+ }
+
+ if (keydata->data != NULL) {
+ isc_mem_free(keydata->mctx, keydata->data);
+ }
+ keydata->mctx = NULL;
+}
+
+static isc_result_t
+additionaldata_keydata(ARGS_ADDLDATA) {
+ REQUIRE(rdata->type == dns_rdatatype_keydata);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(add);
+ UNUSED(arg);
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+digest_keydata(ARGS_DIGEST) {
+ isc_region_t r;
+
+ REQUIRE(rdata->type == dns_rdatatype_keydata);
+
+ dns_rdata_toregion(rdata, &r);
+
+ return ((digest)(arg, &r));
+}
+
+static bool
+checkowner_keydata(ARGS_CHECKOWNER) {
+ REQUIRE(type == dns_rdatatype_keydata);
+
+ UNUSED(name);
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (true);
+}
+
+static bool
+checknames_keydata(ARGS_CHECKNAMES) {
+ REQUIRE(rdata->type == dns_rdatatype_keydata);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(bad);
+
+ return (true);
+}
+
+static int
+casecompare_keydata(ARGS_COMPARE) {
+ return (compare_keydata(rdata1, rdata2));
+}
+
+#endif /* GENERIC_KEYDATA_65533_C */
diff --git a/lib/dns/rdata/generic/keydata_65533.h b/lib/dns/rdata/generic/keydata_65533.h
new file mode 100644
index 0000000..598b31b
--- /dev/null
+++ b/lib/dns/rdata/generic/keydata_65533.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
+
+typedef struct dns_rdata_keydata {
+ dns_rdatacommon_t common;
+ isc_mem_t *mctx;
+ uint32_t refresh; /* Timer for refreshing data */
+ uint32_t addhd; /* Hold-down timer for adding */
+ uint32_t removehd; /* Hold-down timer for removing */
+ uint16_t flags; /* Copy of DNSKEY_48 */
+ dns_secproto_t protocol;
+ dns_secalg_t algorithm;
+ uint16_t datalen;
+ unsigned char *data;
+} dns_rdata_keydata_t;
diff --git a/lib/dns/rdata/generic/l32_105.c b/lib/dns/rdata/generic/l32_105.c
new file mode 100644
index 0000000..7ab6518
--- /dev/null
+++ b/lib/dns/rdata/generic/l32_105.c
@@ -0,0 +1,231 @@
+/*
+ * 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_L32_105_C
+#define RDATA_GENERIC_L32_105_C
+
+#include <string.h>
+
+#include <isc/net.h>
+
+#define RRTYPE_L32_ATTRIBUTES (0)
+
+static isc_result_t
+fromtext_l32(ARGS_FROMTEXT) {
+ isc_token_t token;
+ struct in_addr addr;
+ isc_region_t region;
+
+ REQUIRE(type == dns_rdatatype_l32);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(origin);
+ UNUSED(options);
+ UNUSED(callbacks);
+
+ 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));
+
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ false));
+
+ if (inet_pton(AF_INET, DNS_AS_STR(token), &addr) != 1) {
+ RETTOK(DNS_R_BADDOTTEDQUAD);
+ }
+ isc_buffer_availableregion(target, &region);
+ if (region.length < 4) {
+ return (ISC_R_NOSPACE);
+ }
+ memmove(region.base, &addr, 4);
+ isc_buffer_add(target, 4);
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+totext_l32(ARGS_TOTEXT) {
+ isc_region_t region;
+ char buf[sizeof("65000")];
+ unsigned short num;
+
+ REQUIRE(rdata->type == dns_rdatatype_l32);
+ REQUIRE(rdata->length == 6);
+
+ UNUSED(tctx);
+
+ dns_rdata_toregion(rdata, &region);
+ num = uint16_fromregion(&region);
+ isc_region_consume(&region, 2);
+ snprintf(buf, sizeof(buf), "%u", num);
+ RETERR(str_totext(buf, target));
+
+ RETERR(str_totext(" ", target));
+
+ return (inet_totext(AF_INET, tctx->flags, &region, target));
+}
+
+static isc_result_t
+fromwire_l32(ARGS_FROMWIRE) {
+ isc_region_t sregion;
+
+ REQUIRE(type == dns_rdatatype_l32);
+
+ UNUSED(type);
+ UNUSED(options);
+ UNUSED(rdclass);
+ UNUSED(dctx);
+
+ isc_buffer_activeregion(source, &sregion);
+ if (sregion.length != 6) {
+ return (DNS_R_FORMERR);
+ }
+ isc_buffer_forward(source, sregion.length);
+ return (mem_tobuffer(target, sregion.base, sregion.length));
+}
+
+static isc_result_t
+towire_l32(ARGS_TOWIRE) {
+ REQUIRE(rdata->type == dns_rdatatype_l32);
+ REQUIRE(rdata->length == 6);
+
+ UNUSED(cctx);
+
+ return (mem_tobuffer(target, rdata->data, rdata->length));
+}
+
+static int
+compare_l32(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_l32);
+ REQUIRE(rdata1->length == 6);
+ REQUIRE(rdata2->length == 6);
+
+ dns_rdata_toregion(rdata1, &region1);
+ dns_rdata_toregion(rdata2, &region2);
+ return (isc_region_compare(&region1, &region2));
+}
+
+static isc_result_t
+fromstruct_l32(ARGS_FROMSTRUCT) {
+ dns_rdata_l32_t *l32 = source;
+ uint32_t n;
+
+ REQUIRE(type == dns_rdatatype_l32);
+ REQUIRE(l32 != NULL);
+ REQUIRE(l32->common.rdtype == type);
+ REQUIRE(l32->common.rdclass == rdclass);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ RETERR(uint16_tobuffer(l32->pref, target));
+ n = ntohl(l32->l32.s_addr);
+ return (uint32_tobuffer(n, target));
+}
+
+static isc_result_t
+tostruct_l32(ARGS_TOSTRUCT) {
+ isc_region_t region;
+ dns_rdata_l32_t *l32 = target;
+ uint32_t n;
+
+ REQUIRE(rdata->type == dns_rdatatype_l32);
+ REQUIRE(l32 != NULL);
+ REQUIRE(rdata->length == 6);
+
+ UNUSED(mctx);
+
+ l32->common.rdclass = rdata->rdclass;
+ l32->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&l32->common, link);
+
+ dns_rdata_toregion(rdata, &region);
+ l32->pref = uint16_fromregion(&region);
+ n = uint32_fromregion(&region);
+ l32->l32.s_addr = htonl(n);
+ return (ISC_R_SUCCESS);
+}
+
+static void
+freestruct_l32(ARGS_FREESTRUCT) {
+ dns_rdata_l32_t *l32 = source;
+
+ REQUIRE(l32 != NULL);
+ REQUIRE(l32->common.rdtype == dns_rdatatype_l32);
+
+ return;
+}
+
+static isc_result_t
+additionaldata_l32(ARGS_ADDLDATA) {
+ REQUIRE(rdata->type == dns_rdatatype_l32);
+ REQUIRE(rdata->length == 6);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(add);
+ UNUSED(arg);
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+digest_l32(ARGS_DIGEST) {
+ isc_region_t r;
+
+ REQUIRE(rdata->type == dns_rdatatype_l32);
+ REQUIRE(rdata->length == 6);
+
+ dns_rdata_toregion(rdata, &r);
+
+ return ((digest)(arg, &r));
+}
+
+static bool
+checkowner_l32(ARGS_CHECKOWNER) {
+ REQUIRE(type == dns_rdatatype_l32);
+
+ UNUSED(name);
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (true);
+}
+
+static bool
+checknames_l32(ARGS_CHECKNAMES) {
+ REQUIRE(rdata->type == dns_rdatatype_l32);
+ REQUIRE(rdata->length == 6);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(bad);
+
+ return (true);
+}
+
+static int
+casecompare_l32(ARGS_COMPARE) {
+ return (compare_l32(rdata1, rdata2));
+}
+
+#endif /* RDATA_GENERIC_L32_105_C */
diff --git a/lib/dns/rdata/generic/l32_105.h b/lib/dns/rdata/generic/l32_105.h
new file mode 100644
index 0000000..58a76d2
--- /dev/null
+++ b/lib/dns/rdata/generic/l32_105.h
@@ -0,0 +1,21 @@
+/*
+ * 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_l32 {
+ dns_rdatacommon_t common;
+ uint16_t pref;
+ struct in_addr l32;
+} dns_rdata_l32_t;
diff --git a/lib/dns/rdata/generic/l64_106.c b/lib/dns/rdata/generic/l64_106.c
new file mode 100644
index 0000000..ee28f2e
--- /dev/null
+++ b/lib/dns/rdata/generic/l64_106.c
@@ -0,0 +1,225 @@
+/*
+ * 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_L64_106_C
+#define RDATA_GENERIC_L64_106_C
+
+#include <string.h>
+
+#include <isc/net.h>
+
+#define RRTYPE_L64_ATTRIBUTES (0)
+
+static isc_result_t
+fromtext_l64(ARGS_FROMTEXT) {
+ isc_token_t token;
+ unsigned char locator[NS_LOCATORSZ];
+
+ REQUIRE(type == dns_rdatatype_l64);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(origin);
+ UNUSED(options);
+ UNUSED(callbacks);
+
+ 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));
+
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ false));
+
+ if (locator_pton(DNS_AS_STR(token), locator) != 1) {
+ RETTOK(DNS_R_SYNTAX);
+ }
+ return (mem_tobuffer(target, locator, NS_LOCATORSZ));
+}
+
+static isc_result_t
+totext_l64(ARGS_TOTEXT) {
+ isc_region_t region;
+ char buf[sizeof("xxxx:xxxx:xxxx:xxxx")];
+ unsigned short num;
+
+ REQUIRE(rdata->type == dns_rdatatype_l64);
+ REQUIRE(rdata->length == 10);
+
+ UNUSED(tctx);
+
+ dns_rdata_toregion(rdata, &region);
+ num = uint16_fromregion(&region);
+ isc_region_consume(&region, 2);
+ snprintf(buf, sizeof(buf), "%u", num);
+ RETERR(str_totext(buf, target));
+
+ RETERR(str_totext(" ", target));
+
+ snprintf(buf, sizeof(buf), "%x:%x:%x:%x",
+ region.base[0] << 8 | region.base[1],
+ region.base[2] << 8 | region.base[3],
+ region.base[4] << 8 | region.base[5],
+ region.base[6] << 8 | region.base[7]);
+ return (str_totext(buf, target));
+}
+
+static isc_result_t
+fromwire_l64(ARGS_FROMWIRE) {
+ isc_region_t sregion;
+
+ REQUIRE(type == dns_rdatatype_l64);
+
+ UNUSED(type);
+ UNUSED(options);
+ UNUSED(rdclass);
+ UNUSED(dctx);
+
+ isc_buffer_activeregion(source, &sregion);
+ if (sregion.length != 10) {
+ return (DNS_R_FORMERR);
+ }
+ isc_buffer_forward(source, sregion.length);
+ return (mem_tobuffer(target, sregion.base, sregion.length));
+}
+
+static isc_result_t
+towire_l64(ARGS_TOWIRE) {
+ REQUIRE(rdata->type == dns_rdatatype_l64);
+ REQUIRE(rdata->length == 10);
+
+ UNUSED(cctx);
+
+ return (mem_tobuffer(target, rdata->data, rdata->length));
+}
+
+static int
+compare_l64(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_l64);
+ REQUIRE(rdata1->length == 10);
+ REQUIRE(rdata2->length == 10);
+
+ dns_rdata_toregion(rdata1, &region1);
+ dns_rdata_toregion(rdata2, &region2);
+ return (isc_region_compare(&region1, &region2));
+}
+
+static isc_result_t
+fromstruct_l64(ARGS_FROMSTRUCT) {
+ dns_rdata_l64_t *l64 = source;
+
+ REQUIRE(type == dns_rdatatype_l64);
+ REQUIRE(l64 != NULL);
+ REQUIRE(l64->common.rdtype == type);
+ REQUIRE(l64->common.rdclass == rdclass);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ RETERR(uint16_tobuffer(l64->pref, target));
+ return (mem_tobuffer(target, l64->l64, sizeof(l64->l64)));
+}
+
+static isc_result_t
+tostruct_l64(ARGS_TOSTRUCT) {
+ isc_region_t region;
+ dns_rdata_l64_t *l64 = target;
+
+ REQUIRE(rdata->type == dns_rdatatype_l64);
+ REQUIRE(l64 != NULL);
+ REQUIRE(rdata->length == 10);
+
+ UNUSED(mctx);
+
+ l64->common.rdclass = rdata->rdclass;
+ l64->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&l64->common, link);
+
+ dns_rdata_toregion(rdata, &region);
+ l64->pref = uint16_fromregion(&region);
+ memmove(l64->l64, region.base, region.length);
+ return (ISC_R_SUCCESS);
+}
+
+static void
+freestruct_l64(ARGS_FREESTRUCT) {
+ dns_rdata_l64_t *l64 = source;
+
+ REQUIRE(l64 != NULL);
+ REQUIRE(l64->common.rdtype == dns_rdatatype_l64);
+
+ return;
+}
+
+static isc_result_t
+additionaldata_l64(ARGS_ADDLDATA) {
+ REQUIRE(rdata->type == dns_rdatatype_l64);
+ REQUIRE(rdata->length == 10);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(add);
+ UNUSED(arg);
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+digest_l64(ARGS_DIGEST) {
+ isc_region_t r;
+
+ REQUIRE(rdata->type == dns_rdatatype_l64);
+ REQUIRE(rdata->length == 10);
+
+ dns_rdata_toregion(rdata, &r);
+
+ return ((digest)(arg, &r));
+}
+
+static bool
+checkowner_l64(ARGS_CHECKOWNER) {
+ REQUIRE(type == dns_rdatatype_l64);
+
+ UNUSED(name);
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (true);
+}
+
+static bool
+checknames_l64(ARGS_CHECKNAMES) {
+ REQUIRE(rdata->type == dns_rdatatype_l64);
+ REQUIRE(rdata->length == 10);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(bad);
+
+ return (true);
+}
+
+static int
+casecompare_l64(ARGS_COMPARE) {
+ return (compare_l64(rdata1, rdata2));
+}
+
+#endif /* RDATA_GENERIC_L64_106_C */
diff --git a/lib/dns/rdata/generic/l64_106.h b/lib/dns/rdata/generic/l64_106.h
new file mode 100644
index 0000000..aa4d9b8
--- /dev/null
+++ b/lib/dns/rdata/generic/l64_106.h
@@ -0,0 +1,21 @@
+/*
+ * 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_l64 {
+ dns_rdatacommon_t common;
+ uint16_t pref;
+ unsigned char l64[8];
+} dns_rdata_l64_t;
diff --git a/lib/dns/rdata/generic/loc_29.c b/lib/dns/rdata/generic/loc_29.c
new file mode 100644
index 0000000..c05e144
--- /dev/null
+++ b/lib/dns/rdata/generic/loc_29.c
@@ -0,0 +1,839 @@
+/*
+ * 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.
+ */
+
+/* RFC1876 */
+
+#ifndef RDATA_GENERIC_LOC_29_C
+#define RDATA_GENERIC_LOC_29_C
+
+#define RRTYPE_LOC_ATTRIBUTES (0)
+
+static isc_result_t
+loc_getdecimal(const char *str, unsigned long max, size_t precision, char units,
+ unsigned long *valuep) {
+ bool ok;
+ char *e;
+ size_t i;
+ long tmp;
+ unsigned long value;
+
+ value = strtoul(str, &e, 10);
+ if (*e != 0 && *e != '.' && *e != units) {
+ return (DNS_R_SYNTAX);
+ }
+ if (value > max) {
+ return (ISC_R_RANGE);
+ }
+ ok = e != str;
+ if (*e == '.') {
+ e++;
+ for (i = 0; i < precision; i++) {
+ if (*e == 0 || *e == units) {
+ break;
+ }
+ if ((tmp = decvalue(*e++)) < 0) {
+ return (DNS_R_SYNTAX);
+ }
+ ok = true;
+ value *= 10;
+ value += tmp;
+ }
+ for (; i < precision; i++) {
+ value *= 10;
+ }
+ } else {
+ for (i = 0; i < precision; i++) {
+ value *= 10;
+ }
+ }
+ if (*e != 0 && *e == units) {
+ e++;
+ }
+ if (!ok || *e != 0) {
+ return (DNS_R_SYNTAX);
+ }
+ *valuep = value;
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+loc_getprecision(const char *str, unsigned char *valuep) {
+ unsigned long poweroften[8] = { 1, 10, 100, 1000,
+ 10000, 100000, 1000000, 10000000 };
+ unsigned long m, cm;
+ bool ok;
+ char *e;
+ size_t i;
+ long tmp;
+ int man;
+ int exp;
+
+ m = strtoul(str, &e, 10);
+ if (*e != 0 && *e != '.' && *e != 'm') {
+ return (DNS_R_SYNTAX);
+ }
+ if (m > 90000000) {
+ return (ISC_R_RANGE);
+ }
+ cm = 0;
+ ok = e != str;
+ if (*e == '.') {
+ e++;
+ for (i = 0; i < 2; i++) {
+ if (*e == 0 || *e == 'm') {
+ break;
+ }
+ if ((tmp = decvalue(*e++)) < 0) {
+ return (DNS_R_SYNTAX);
+ }
+ ok = true;
+ cm *= 10;
+ cm += tmp;
+ }
+ for (; i < 2; i++) {
+ cm *= 10;
+ }
+ }
+ if (*e == 'm') {
+ e++;
+ }
+ if (!ok || *e != 0) {
+ return (DNS_R_SYNTAX);
+ }
+
+ /*
+ * We don't just multiply out as we will overflow.
+ */
+ if (m > 0) {
+ for (exp = 0; exp < 7; exp++) {
+ if (m < poweroften[exp + 1]) {
+ break;
+ }
+ }
+ man = m / poweroften[exp];
+ exp += 2;
+ } else if (cm >= 10) {
+ man = cm / 10;
+ exp = 1;
+ } else {
+ man = cm;
+ exp = 0;
+ }
+ *valuep = (man << 4) + exp;
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+get_degrees(isc_lex_t *lexer, isc_token_t *token, unsigned long *d) {
+ RETERR(isc_lex_getmastertoken(lexer, token, isc_tokentype_number,
+ false));
+ *d = token->value.as_ulong;
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+check_coordinate(unsigned long d, unsigned long m, unsigned long s,
+ unsigned long maxd) {
+ if (d > maxd || m > 59U) {
+ return (ISC_R_RANGE);
+ }
+ if (d == maxd && (m != 0 || s != 0)) {
+ return (ISC_R_RANGE);
+ }
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+get_minutes(isc_lex_t *lexer, isc_token_t *token, unsigned long *m) {
+ RETERR(isc_lex_getmastertoken(lexer, token, isc_tokentype_number,
+ false));
+
+ *m = token->value.as_ulong;
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+get_seconds(isc_lex_t *lexer, isc_token_t *token, unsigned long *s) {
+ RETERR(isc_lex_getmastertoken(lexer, token, isc_tokentype_string,
+ false));
+ RETERR(loc_getdecimal(DNS_AS_STR(*token), 59, 3, '\0', s));
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+get_direction(isc_lex_t *lexer, isc_token_t *token, const char *directions,
+ int *direction) {
+ RETERR(isc_lex_getmastertoken(lexer, token, isc_tokentype_string,
+ false));
+ if (DNS_AS_STR(*token)[0] == directions[1] &&
+ DNS_AS_STR(*token)[1] == 0)
+ {
+ *direction = DNS_AS_STR(*token)[0];
+ return (ISC_R_SUCCESS);
+ }
+
+ if (DNS_AS_STR(*token)[0] == directions[0] &&
+ DNS_AS_STR(*token)[1] == 0)
+ {
+ *direction = DNS_AS_STR(*token)[0];
+ return (ISC_R_SUCCESS);
+ }
+
+ *direction = 0;
+ isc_lex_ungettoken(lexer, token);
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+loc_getcoordinate(isc_lex_t *lexer, unsigned long *dp, unsigned long *mp,
+ unsigned long *sp, const char *directions, int *directionp,
+ unsigned long maxd) {
+ isc_result_t result = ISC_R_SUCCESS;
+ isc_token_t token;
+ unsigned long d, m, s;
+ int direction = 0;
+
+ m = 0;
+ s = 0;
+
+ /*
+ * Degrees.
+ */
+ RETERR(get_degrees(lexer, &token, &d));
+ RETTOK(check_coordinate(d, m, s, maxd));
+
+ /*
+ * Minutes.
+ */
+ RETERR(get_direction(lexer, &token, directions, &direction));
+ if (direction > 0) {
+ goto done;
+ }
+
+ RETERR(get_minutes(lexer, &token, &m));
+ RETTOK(check_coordinate(d, m, s, maxd));
+
+ /*
+ * Seconds.
+ */
+ RETERR(get_direction(lexer, &token, directions, &direction));
+ if (direction > 0) {
+ goto done;
+ }
+
+ result = get_seconds(lexer, &token, &s);
+ if (result == ISC_R_RANGE || result == DNS_R_SYNTAX) {
+ RETTOK(result);
+ }
+ RETERR(result);
+ RETTOK(check_coordinate(d, m, s, maxd));
+
+ /*
+ * Direction.
+ */
+ RETERR(get_direction(lexer, &token, directions, &direction));
+ if (direction == 0) {
+ RETERR(DNS_R_SYNTAX);
+ }
+done:
+
+ *directionp = direction;
+ *dp = d;
+ *mp = m;
+ *sp = s;
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+loc_getlatitude(isc_lex_t *lexer, unsigned long *latitude) {
+ unsigned long d1 = 0, m1 = 0, s1 = 0;
+ int direction = 0;
+
+ RETERR(loc_getcoordinate(lexer, &d1, &m1, &s1, "SN", &direction, 90U));
+
+ switch (direction) {
+ case 'N':
+ *latitude = 0x80000000 + (d1 * 3600 + m1 * 60) * 1000 + s1;
+ break;
+ case 'S':
+ *latitude = 0x80000000 - (d1 * 3600 + m1 * 60) * 1000 - s1;
+ break;
+ default:
+ UNREACHABLE();
+ }
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+loc_getlongitude(isc_lex_t *lexer, unsigned long *longitude) {
+ unsigned long d2 = 0, m2 = 0, s2 = 0;
+ int direction = 0;
+
+ RETERR(loc_getcoordinate(lexer, &d2, &m2, &s2, "WE", &direction, 180U));
+
+ switch (direction) {
+ case 'E':
+ *longitude = 0x80000000 + (d2 * 3600 + m2 * 60) * 1000 + s2;
+ break;
+ case 'W':
+ *longitude = 0x80000000 - (d2 * 3600 + m2 * 60) * 1000 - s2;
+ break;
+ default:
+ UNREACHABLE();
+ }
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+loc_getaltitude(isc_lex_t *lexer, unsigned long *altitude) {
+ isc_token_t token;
+ unsigned long cm;
+ const char *str;
+
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ false));
+ str = DNS_AS_STR(token);
+ if (DNS_AS_STR(token)[0] == '-') {
+ RETTOK(loc_getdecimal(str + 1, 100000, 2, 'm', &cm));
+ if (cm > 10000000UL) {
+ RETTOK(ISC_R_RANGE);
+ }
+ *altitude = 10000000 - cm;
+ } else {
+ RETTOK(loc_getdecimal(str, 42849672, 2, 'm', &cm));
+ if (cm > 4284967295UL) {
+ RETTOK(ISC_R_RANGE);
+ }
+ *altitude = 10000000 + cm;
+ }
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+loc_getoptionalprecision(isc_lex_t *lexer, unsigned char *valuep) {
+ isc_token_t token;
+
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ true));
+ if (token.type == isc_tokentype_eol || token.type == isc_tokentype_eof)
+ {
+ isc_lex_ungettoken(lexer, &token);
+ return (ISC_R_NOMORE);
+ }
+ RETTOK(loc_getprecision(DNS_AS_STR(token), valuep));
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+loc_getsize(isc_lex_t *lexer, unsigned char *sizep) {
+ return (loc_getoptionalprecision(lexer, sizep));
+}
+
+static isc_result_t
+loc_gethorizontalprecision(isc_lex_t *lexer, unsigned char *hpp) {
+ return (loc_getoptionalprecision(lexer, hpp));
+}
+
+static isc_result_t
+loc_getverticalprecision(isc_lex_t *lexer, unsigned char *vpp) {
+ return (loc_getoptionalprecision(lexer, vpp));
+}
+
+/* The LOC record is expressed in a master file in the following format:
+ *
+ * <owner> <TTL> <class> LOC ( d1 [m1 [s1]] {"N"|"S"} d2 [m2 [s2]]
+ * {"E"|"W"} alt["m"] [siz["m"] [hp["m"]
+ * [vp["m"]]]] )
+ *
+ * (The parentheses are used for multi-line data as specified in [RFC
+ * 1035] section 5.1.)
+ *
+ * where:
+ *
+ * d1: [0 .. 90] (degrees latitude)
+ * d2: [0 .. 180] (degrees longitude)
+ * m1, m2: [0 .. 59] (minutes latitude/longitude)
+ * s1, s2: [0 .. 59.999] (seconds latitude/longitude)
+ * alt: [-100000.00 .. 42849672.95] BY .01 (altitude in meters)
+ * siz, hp, vp: [0 .. 90000000.00] (size/precision in meters)
+ *
+ * If omitted, minutes and seconds default to zero, size defaults to 1m,
+ * horizontal precision defaults to 10000m, and vertical precision
+ * defaults to 10m. These defaults are chosen to represent typical
+ * ZIP/postal code area sizes, since it is often easy to find
+ * approximate geographical location by ZIP/postal code.
+ */
+static isc_result_t
+fromtext_loc(ARGS_FROMTEXT) {
+ isc_result_t result = ISC_R_SUCCESS;
+ unsigned long latitude = 0;
+ unsigned long longitude = 0;
+ unsigned long altitude = 0;
+ unsigned char size = 0x12; /* Default: 1.00m */
+ unsigned char hp = 0x16; /* Default: 10000.00 m */
+ unsigned char vp = 0x13; /* Default: 10.00 m */
+ unsigned char version = 0;
+
+ REQUIRE(type == dns_rdatatype_loc);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(origin);
+ UNUSED(options);
+ UNUSED(callbacks);
+
+ RETERR(loc_getlatitude(lexer, &latitude));
+ RETERR(loc_getlongitude(lexer, &longitude));
+ RETERR(loc_getaltitude(lexer, &altitude));
+ result = loc_getsize(lexer, &size);
+ if (result == ISC_R_NOMORE) {
+ result = ISC_R_SUCCESS;
+ goto encode;
+ }
+ RETERR(result);
+ result = loc_gethorizontalprecision(lexer, &hp);
+ if (result == ISC_R_NOMORE) {
+ result = ISC_R_SUCCESS;
+ goto encode;
+ }
+ RETERR(result);
+ result = loc_getverticalprecision(lexer, &vp);
+ if (result == ISC_R_NOMORE) {
+ result = ISC_R_SUCCESS;
+ goto encode;
+ }
+ RETERR(result);
+encode:
+ RETERR(mem_tobuffer(target, &version, 1));
+ RETERR(mem_tobuffer(target, &size, 1));
+ RETERR(mem_tobuffer(target, &hp, 1));
+ RETERR(mem_tobuffer(target, &vp, 1));
+
+ RETERR(uint32_tobuffer(latitude, target));
+ RETERR(uint32_tobuffer(longitude, target));
+ RETERR(uint32_tobuffer(altitude, target));
+
+ return (result);
+}
+
+static isc_result_t
+totext_loc(ARGS_TOTEXT) {
+ int d1, m1, s1, fs1;
+ int d2, m2, s2, fs2;
+ unsigned long latitude;
+ unsigned long longitude;
+ unsigned long altitude;
+ bool north;
+ bool east;
+ bool below;
+ isc_region_t sr;
+ char sbuf[sizeof("90000000m")];
+ char hbuf[sizeof("90000000m")];
+ char vbuf[sizeof("90000000m")];
+ /* "89 59 59.999 N 179 59 59.999 E " */
+ /* "-42849672.95m 90000000m 90000000m 90000000m"; */
+ char buf[8 * 6 + 12 * 1 + 2 * 10 + sizeof(sbuf) + sizeof(hbuf) +
+ sizeof(vbuf)];
+ unsigned char size, hp, vp;
+ unsigned long poweroften[8] = { 1, 10, 100, 1000,
+ 10000, 100000, 1000000, 10000000 };
+
+ UNUSED(tctx);
+
+ REQUIRE(rdata->type == dns_rdatatype_loc);
+ REQUIRE(rdata->length != 0);
+
+ dns_rdata_toregion(rdata, &sr);
+
+ if (sr.base[0] != 0) {
+ return (ISC_R_NOTIMPLEMENTED);
+ }
+
+ REQUIRE(rdata->length == 16);
+
+ size = sr.base[1];
+ INSIST((size & 0x0f) < 10 && (size >> 4) < 10);
+ if ((size & 0x0f) > 1) {
+ snprintf(sbuf, sizeof(sbuf), "%lum",
+ (size >> 4) * poweroften[(size & 0x0f) - 2]);
+ } else {
+ snprintf(sbuf, sizeof(sbuf), "0.%02lum",
+ (size >> 4) * poweroften[(size & 0x0f)]);
+ }
+ hp = sr.base[2];
+ INSIST((hp & 0x0f) < 10 && (hp >> 4) < 10);
+ if ((hp & 0x0f) > 1) {
+ snprintf(hbuf, sizeof(hbuf), "%lum",
+ (hp >> 4) * poweroften[(hp & 0x0f) - 2]);
+ } else {
+ snprintf(hbuf, sizeof(hbuf), "0.%02lum",
+ (hp >> 4) * poweroften[(hp & 0x0f)]);
+ }
+ vp = sr.base[3];
+ INSIST((vp & 0x0f) < 10 && (vp >> 4) < 10);
+ if ((vp & 0x0f) > 1) {
+ snprintf(vbuf, sizeof(vbuf), "%lum",
+ (vp >> 4) * poweroften[(vp & 0x0f) - 2]);
+ } else {
+ snprintf(vbuf, sizeof(vbuf), "0.%02lum",
+ (vp >> 4) * poweroften[(vp & 0x0f)]);
+ }
+ isc_region_consume(&sr, 4);
+
+ latitude = uint32_fromregion(&sr);
+ isc_region_consume(&sr, 4);
+ if (latitude >= 0x80000000) {
+ north = true;
+ latitude -= 0x80000000;
+ } else {
+ north = false;
+ latitude = 0x80000000 - latitude;
+ }
+ fs1 = (int)(latitude % 1000);
+ latitude /= 1000;
+ s1 = (int)(latitude % 60);
+ latitude /= 60;
+ m1 = (int)(latitude % 60);
+ latitude /= 60;
+ d1 = (int)latitude;
+ INSIST(latitude <= 90U);
+
+ longitude = uint32_fromregion(&sr);
+ isc_region_consume(&sr, 4);
+ if (longitude >= 0x80000000) {
+ east = true;
+ longitude -= 0x80000000;
+ } else {
+ east = false;
+ longitude = 0x80000000 - longitude;
+ }
+ fs2 = (int)(longitude % 1000);
+ longitude /= 1000;
+ s2 = (int)(longitude % 60);
+ longitude /= 60;
+ m2 = (int)(longitude % 60);
+ longitude /= 60;
+ d2 = (int)longitude;
+ INSIST(longitude <= 180U);
+
+ altitude = uint32_fromregion(&sr);
+ isc_region_consume(&sr, 4);
+ if (altitude < 10000000U) {
+ below = true;
+ altitude = 10000000 - altitude;
+ } else {
+ below = false;
+ altitude -= 10000000;
+ }
+
+ snprintf(buf, sizeof(buf),
+ "%d %d %d.%03d %s %d %d %d.%03d %s %s%lu.%02lum %s %s %s", d1,
+ m1, s1, fs1, north ? "N" : "S", d2, m2, s2, fs2,
+ east ? "E" : "W", below ? "-" : "", altitude / 100,
+ altitude % 100, sbuf, hbuf, vbuf);
+
+ return (str_totext(buf, target));
+}
+
+static isc_result_t
+fromwire_loc(ARGS_FROMWIRE) {
+ isc_region_t sr;
+ unsigned char c;
+ unsigned long latitude;
+ unsigned long longitude;
+
+ REQUIRE(type == dns_rdatatype_loc);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(dctx);
+ UNUSED(options);
+
+ isc_buffer_activeregion(source, &sr);
+ if (sr.length < 1) {
+ return (ISC_R_UNEXPECTEDEND);
+ }
+ if (sr.base[0] != 0) {
+ /* Treat as unknown. */
+ isc_buffer_forward(source, sr.length);
+ return (mem_tobuffer(target, sr.base, sr.length));
+ }
+ if (sr.length < 16) {
+ return (ISC_R_UNEXPECTEDEND);
+ }
+
+ /*
+ * Size.
+ */
+ c = sr.base[1];
+ if (c != 0) {
+ if ((c & 0xf) > 9 || ((c >> 4) & 0xf) > 9 ||
+ ((c >> 4) & 0xf) == 0)
+ {
+ return (ISC_R_RANGE);
+
+ /*
+ * Horizontal precision.
+ */
+ }
+ }
+
+ /*
+ * Horizontal precision.
+ */
+ c = sr.base[2];
+ if (c != 0) {
+ if ((c & 0xf) > 9 || ((c >> 4) & 0xf) > 9 ||
+ ((c >> 4) & 0xf) == 0)
+ {
+ return (ISC_R_RANGE);
+
+ /*
+ * Vertical precision.
+ */
+ }
+ }
+
+ /*
+ * Vertical precision.
+ */
+ c = sr.base[3];
+ if (c != 0) {
+ if ((c & 0xf) > 9 || ((c >> 4) & 0xf) > 9 ||
+ ((c >> 4) & 0xf) == 0)
+ {
+ return (ISC_R_RANGE);
+ }
+ }
+ isc_region_consume(&sr, 4);
+
+ /*
+ * Latitude.
+ */
+ latitude = uint32_fromregion(&sr);
+ if (latitude < (0x80000000UL - 90 * 3600000) ||
+ latitude > (0x80000000UL + 90 * 3600000))
+ {
+ return (ISC_R_RANGE);
+ }
+ isc_region_consume(&sr, 4);
+
+ /*
+ * Longitude.
+ */
+ longitude = uint32_fromregion(&sr);
+ if (longitude < (0x80000000UL - 180 * 3600000) ||
+ longitude > (0x80000000UL + 180 * 3600000))
+ {
+ return (ISC_R_RANGE);
+ }
+
+ /*
+ * Altitude.
+ * All values possible.
+ */
+
+ isc_buffer_activeregion(source, &sr);
+ isc_buffer_forward(source, 16);
+ return (mem_tobuffer(target, sr.base, 16));
+}
+
+static isc_result_t
+towire_loc(ARGS_TOWIRE) {
+ UNUSED(cctx);
+
+ REQUIRE(rdata->type == dns_rdatatype_loc);
+ REQUIRE(rdata->length != 0);
+
+ return (mem_tobuffer(target, rdata->data, rdata->length));
+}
+
+static int
+compare_loc(ARGS_COMPARE) {
+ isc_region_t r1;
+ isc_region_t r2;
+
+ REQUIRE(rdata1->type == rdata2->type);
+ REQUIRE(rdata1->rdclass == rdata2->rdclass);
+ REQUIRE(rdata1->type == dns_rdatatype_loc);
+ REQUIRE(rdata1->length != 0);
+ REQUIRE(rdata2->length != 0);
+
+ dns_rdata_toregion(rdata1, &r1);
+ dns_rdata_toregion(rdata2, &r2);
+ return (isc_region_compare(&r1, &r2));
+}
+
+static isc_result_t
+fromstruct_loc(ARGS_FROMSTRUCT) {
+ dns_rdata_loc_t *loc = source;
+ uint8_t c;
+
+ REQUIRE(type == dns_rdatatype_loc);
+ REQUIRE(loc != NULL);
+ REQUIRE(loc->common.rdtype == type);
+ REQUIRE(loc->common.rdclass == rdclass);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ if (loc->v.v0.version != 0) {
+ return (ISC_R_NOTIMPLEMENTED);
+ }
+ RETERR(uint8_tobuffer(loc->v.v0.version, target));
+
+ c = loc->v.v0.size;
+ if ((c & 0xf) > 9 || ((c >> 4) & 0xf) > 9 || ((c >> 4) & 0xf) == 0) {
+ return (ISC_R_RANGE);
+ }
+ RETERR(uint8_tobuffer(loc->v.v0.size, target));
+
+ c = loc->v.v0.horizontal;
+ if ((c & 0xf) > 9 || ((c >> 4) & 0xf) > 9 || ((c >> 4) & 0xf) == 0) {
+ return (ISC_R_RANGE);
+ }
+ RETERR(uint8_tobuffer(loc->v.v0.horizontal, target));
+
+ c = loc->v.v0.vertical;
+ if ((c & 0xf) > 9 || ((c >> 4) & 0xf) > 9 || ((c >> 4) & 0xf) == 0) {
+ return (ISC_R_RANGE);
+ }
+ RETERR(uint8_tobuffer(loc->v.v0.vertical, target));
+
+ if (loc->v.v0.latitude < (0x80000000UL - 90 * 3600000) ||
+ loc->v.v0.latitude > (0x80000000UL + 90 * 3600000))
+ {
+ return (ISC_R_RANGE);
+ }
+ RETERR(uint32_tobuffer(loc->v.v0.latitude, target));
+
+ if (loc->v.v0.longitude < (0x80000000UL - 180 * 3600000) ||
+ loc->v.v0.longitude > (0x80000000UL + 180 * 3600000))
+ {
+ return (ISC_R_RANGE);
+ }
+ RETERR(uint32_tobuffer(loc->v.v0.longitude, target));
+ return (uint32_tobuffer(loc->v.v0.altitude, target));
+}
+
+static isc_result_t
+tostruct_loc(ARGS_TOSTRUCT) {
+ dns_rdata_loc_t *loc = target;
+ isc_region_t r;
+ uint8_t version;
+
+ REQUIRE(rdata->type == dns_rdatatype_loc);
+ REQUIRE(loc != NULL);
+ REQUIRE(rdata->length != 0);
+
+ UNUSED(mctx);
+
+ dns_rdata_toregion(rdata, &r);
+ version = uint8_fromregion(&r);
+ if (version != 0) {
+ return (ISC_R_NOTIMPLEMENTED);
+ }
+
+ loc->common.rdclass = rdata->rdclass;
+ loc->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&loc->common, link);
+
+ loc->v.v0.version = version;
+ isc_region_consume(&r, 1);
+ loc->v.v0.size = uint8_fromregion(&r);
+ isc_region_consume(&r, 1);
+ loc->v.v0.horizontal = uint8_fromregion(&r);
+ isc_region_consume(&r, 1);
+ loc->v.v0.vertical = uint8_fromregion(&r);
+ isc_region_consume(&r, 1);
+ loc->v.v0.latitude = uint32_fromregion(&r);
+ isc_region_consume(&r, 4);
+ loc->v.v0.longitude = uint32_fromregion(&r);
+ isc_region_consume(&r, 4);
+ loc->v.v0.altitude = uint32_fromregion(&r);
+ isc_region_consume(&r, 4);
+ return (ISC_R_SUCCESS);
+}
+
+static void
+freestruct_loc(ARGS_FREESTRUCT) {
+ dns_rdata_loc_t *loc = source;
+
+ REQUIRE(loc != NULL);
+ REQUIRE(loc->common.rdtype == dns_rdatatype_loc);
+
+ UNUSED(source);
+ UNUSED(loc);
+}
+
+static isc_result_t
+additionaldata_loc(ARGS_ADDLDATA) {
+ REQUIRE(rdata->type == dns_rdatatype_loc);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(add);
+ UNUSED(arg);
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+digest_loc(ARGS_DIGEST) {
+ isc_region_t r;
+
+ REQUIRE(rdata->type == dns_rdatatype_loc);
+
+ dns_rdata_toregion(rdata, &r);
+
+ return ((digest)(arg, &r));
+}
+
+static bool
+checkowner_loc(ARGS_CHECKOWNER) {
+ REQUIRE(type == dns_rdatatype_loc);
+
+ UNUSED(name);
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (true);
+}
+
+static bool
+checknames_loc(ARGS_CHECKNAMES) {
+ REQUIRE(rdata->type == dns_rdatatype_loc);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(bad);
+
+ return (true);
+}
+
+static int
+casecompare_loc(ARGS_COMPARE) {
+ return (compare_loc(rdata1, rdata2));
+}
+
+#endif /* RDATA_GENERIC_LOC_29_C */
diff --git a/lib/dns/rdata/generic/loc_29.h b/lib/dns/rdata/generic/loc_29.h
new file mode 100644
index 0000000..635563a
--- /dev/null
+++ b/lib/dns/rdata/generic/loc_29.h
@@ -0,0 +1,34 @@
+/*
+ * 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
+
+/*!
+ * \brief Per RFC1876 */
+
+typedef struct dns_rdata_loc_0 {
+ uint8_t version; /* must be first and zero */
+ uint8_t size;
+ uint8_t horizontal;
+ uint8_t vertical;
+ uint32_t latitude;
+ uint32_t longitude;
+ uint32_t altitude;
+} dns_rdata_loc_0_t;
+
+typedef struct dns_rdata_loc {
+ dns_rdatacommon_t common;
+ union {
+ dns_rdata_loc_0_t v0;
+ } v;
+} dns_rdata_loc_t;
diff --git a/lib/dns/rdata/generic/lp_107.c b/lib/dns/rdata/generic/lp_107.c
new file mode 100644
index 0000000..c4342c0
--- /dev/null
+++ b/lib/dns/rdata/generic/lp_107.c
@@ -0,0 +1,278 @@
+/*
+ * 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_LP_107_C
+#define RDATA_GENERIC_LP_107_C
+
+#include <string.h>
+
+#include <isc/net.h>
+
+#define RRTYPE_LP_ATTRIBUTES (0)
+
+static isc_result_t
+fromtext_lp(ARGS_FROMTEXT) {
+ isc_token_t token;
+ dns_name_t name;
+ isc_buffer_t buffer;
+
+ REQUIRE(type == dns_rdatatype_lp);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(callbacks);
+
+ 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));
+
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ false));
+
+ dns_name_init(&name, NULL);
+ buffer_fromregion(&buffer, &token.value.as_region);
+ if (origin == NULL) {
+ origin = dns_rootname;
+ }
+ return (dns_name_fromtext(&name, &buffer, origin, options, target));
+}
+
+static isc_result_t
+totext_lp(ARGS_TOTEXT) {
+ isc_region_t region;
+ dns_name_t name;
+ dns_name_t prefix;
+ bool sub;
+ char buf[sizeof("64000")];
+ unsigned short num;
+
+ REQUIRE(rdata->type == dns_rdatatype_lp);
+ REQUIRE(rdata->length != 0);
+
+ dns_name_init(&name, NULL);
+ dns_name_init(&prefix, NULL);
+
+ dns_rdata_toregion(rdata, &region);
+ num = uint16_fromregion(&region);
+ isc_region_consume(&region, 2);
+ snprintf(buf, sizeof(buf), "%u", num);
+ RETERR(str_totext(buf, target));
+
+ RETERR(str_totext(" ", target));
+
+ dns_name_fromregion(&name, &region);
+ sub = name_prefix(&name, tctx->origin, &prefix);
+ return (dns_name_totext(&prefix, sub, target));
+}
+
+static isc_result_t
+fromwire_lp(ARGS_FROMWIRE) {
+ dns_name_t name;
+ isc_region_t sregion;
+
+ REQUIRE(type == dns_rdatatype_lp);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ dns_decompress_setmethods(dctx, DNS_COMPRESS_GLOBAL14);
+
+ dns_name_init(&name, NULL);
+
+ isc_buffer_activeregion(source, &sregion);
+ if (sregion.length < 2) {
+ return (ISC_R_UNEXPECTEDEND);
+ }
+ RETERR(mem_tobuffer(target, sregion.base, 2));
+ isc_buffer_forward(source, 2);
+ return (dns_name_fromwire(&name, source, dctx, options, target));
+}
+
+static isc_result_t
+towire_lp(ARGS_TOWIRE) {
+ REQUIRE(rdata->type == dns_rdatatype_lp);
+ REQUIRE(rdata->length != 0);
+
+ UNUSED(cctx);
+
+ return (mem_tobuffer(target, rdata->data, rdata->length));
+}
+
+static int
+compare_lp(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_lp);
+ REQUIRE(rdata1->length != 0);
+ REQUIRE(rdata2->length != 0);
+
+ dns_rdata_toregion(rdata1, &region1);
+ dns_rdata_toregion(rdata2, &region2);
+
+ return (isc_region_compare(&region1, &region2));
+}
+
+static isc_result_t
+fromstruct_lp(ARGS_FROMSTRUCT) {
+ dns_rdata_lp_t *lp = source;
+ isc_region_t region;
+
+ REQUIRE(type == dns_rdatatype_lp);
+ REQUIRE(lp != NULL);
+ REQUIRE(lp->common.rdtype == type);
+ REQUIRE(lp->common.rdclass == rdclass);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ RETERR(uint16_tobuffer(lp->pref, target));
+ dns_name_toregion(&lp->lp, &region);
+ return (isc_buffer_copyregion(target, &region));
+}
+
+static isc_result_t
+tostruct_lp(ARGS_TOSTRUCT) {
+ isc_region_t region;
+ dns_rdata_lp_t *lp = target;
+ dns_name_t name;
+
+ REQUIRE(rdata->type == dns_rdatatype_lp);
+ REQUIRE(lp != NULL);
+ REQUIRE(rdata->length != 0);
+
+ lp->common.rdclass = rdata->rdclass;
+ lp->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&lp->common, link);
+
+ dns_name_init(&name, NULL);
+ dns_rdata_toregion(rdata, &region);
+ lp->pref = uint16_fromregion(&region);
+ isc_region_consume(&region, 2);
+ dns_name_fromregion(&name, &region);
+ dns_name_init(&lp->lp, NULL);
+ name_duporclone(&name, mctx, &lp->lp);
+ lp->mctx = mctx;
+ return (ISC_R_SUCCESS);
+}
+
+static void
+freestruct_lp(ARGS_FREESTRUCT) {
+ dns_rdata_lp_t *lp = source;
+
+ REQUIRE(lp != NULL);
+ REQUIRE(lp->common.rdtype == dns_rdatatype_lp);
+
+ if (lp->mctx == NULL) {
+ return;
+ }
+
+ dns_name_free(&lp->lp, lp->mctx);
+ lp->mctx = NULL;
+}
+
+static isc_result_t
+additionaldata_lp(ARGS_ADDLDATA) {
+ dns_name_t name;
+ dns_offsets_t offsets;
+ isc_region_t region;
+ isc_result_t result;
+
+ REQUIRE(rdata->type == dns_rdatatype_lp);
+
+ UNUSED(owner);
+
+ dns_name_init(&name, offsets);
+ dns_rdata_toregion(rdata, &region);
+ isc_region_consume(&region, 2);
+ dns_name_fromregion(&name, &region);
+
+ result = (add)(arg, &name, dns_rdatatype_l32, NULL);
+ if (result != ISC_R_SUCCESS) {
+ return (result);
+ }
+ return ((add)(arg, &name, dns_rdatatype_l64, NULL));
+}
+
+static isc_result_t
+digest_lp(ARGS_DIGEST) {
+ isc_region_t region;
+
+ REQUIRE(rdata->type == dns_rdatatype_lp);
+
+ dns_rdata_toregion(rdata, &region);
+ return ((digest)(arg, &region));
+}
+
+static bool
+checkowner_lp(ARGS_CHECKOWNER) {
+ REQUIRE(type == dns_rdatatype_lp);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(name);
+ UNUSED(wildcard);
+
+ return (true);
+}
+
+static bool
+checknames_lp(ARGS_CHECKNAMES) {
+ REQUIRE(rdata->type == dns_rdatatype_lp);
+
+ UNUSED(bad);
+ UNUSED(owner);
+
+ return (true);
+}
+
+static int
+casecompare_lp(ARGS_COMPARE) {
+ dns_name_t name1;
+ dns_name_t name2;
+ isc_region_t region1;
+ isc_region_t region2;
+ int order;
+
+ REQUIRE(rdata1->type == rdata2->type);
+ REQUIRE(rdata1->rdclass == rdata2->rdclass);
+ REQUIRE(rdata1->type == dns_rdatatype_lp);
+ REQUIRE(rdata1->length != 0);
+ REQUIRE(rdata2->length != 0);
+
+ order = memcmp(rdata1->data, rdata2->data, 2);
+ if (order != 0) {
+ return (order < 0 ? -1 : 1);
+ }
+
+ dns_name_init(&name1, NULL);
+ dns_name_init(&name2, NULL);
+
+ dns_rdata_toregion(rdata1, &region1);
+ dns_rdata_toregion(rdata2, &region2);
+
+ isc_region_consume(&region1, 2);
+ isc_region_consume(&region2, 2);
+
+ dns_name_fromregion(&name1, &region1);
+ dns_name_fromregion(&name2, &region2);
+
+ return (dns_name_rdatacompare(&name1, &name2));
+}
+
+#endif /* RDATA_GENERIC_LP_107_C */
diff --git a/lib/dns/rdata/generic/lp_107.h b/lib/dns/rdata/generic/lp_107.h
new file mode 100644
index 0000000..09031c4
--- /dev/null
+++ b/lib/dns/rdata/generic/lp_107.h
@@ -0,0 +1,22 @@
+/*
+ * 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_lp {
+ dns_rdatacommon_t common;
+ isc_mem_t *mctx;
+ uint16_t pref;
+ dns_name_t lp;
+} dns_rdata_lp_t;
diff --git a/lib/dns/rdata/generic/mb_7.c b/lib/dns/rdata/generic/mb_7.c
new file mode 100644
index 0000000..23e9e09
--- /dev/null
+++ b/lib/dns/rdata/generic/mb_7.c
@@ -0,0 +1,234 @@
+/*
+ * 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_MB_7_C
+#define RDATA_GENERIC_MB_7_C
+
+#define RRTYPE_MB_ATTRIBUTES (0)
+
+static isc_result_t
+fromtext_mb(ARGS_FROMTEXT) {
+ isc_token_t token;
+ dns_name_t name;
+ isc_buffer_t buffer;
+
+ REQUIRE(type == dns_rdatatype_mb);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(callbacks);
+
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ false));
+
+ dns_name_init(&name, NULL);
+ buffer_fromregion(&buffer, &token.value.as_region);
+ if (origin == NULL) {
+ origin = dns_rootname;
+ }
+ RETTOK(dns_name_fromtext(&name, &buffer, origin, options, target));
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+totext_mb(ARGS_TOTEXT) {
+ isc_region_t region;
+ dns_name_t name;
+ dns_name_t prefix;
+ bool sub;
+
+ REQUIRE(rdata->type == dns_rdatatype_mb);
+ REQUIRE(rdata->length != 0);
+
+ dns_name_init(&name, NULL);
+ dns_name_init(&prefix, NULL);
+
+ dns_rdata_toregion(rdata, &region);
+ dns_name_fromregion(&name, &region);
+
+ sub = name_prefix(&name, tctx->origin, &prefix);
+
+ return (dns_name_totext(&prefix, sub, target));
+}
+
+static isc_result_t
+fromwire_mb(ARGS_FROMWIRE) {
+ dns_name_t name;
+
+ REQUIRE(type == dns_rdatatype_mb);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ dns_decompress_setmethods(dctx, DNS_COMPRESS_GLOBAL14);
+
+ dns_name_init(&name, NULL);
+ return (dns_name_fromwire(&name, source, dctx, options, target));
+}
+
+static isc_result_t
+towire_mb(ARGS_TOWIRE) {
+ dns_name_t name;
+ dns_offsets_t offsets;
+ isc_region_t region;
+
+ REQUIRE(rdata->type == dns_rdatatype_mb);
+ REQUIRE(rdata->length != 0);
+
+ dns_compress_setmethods(cctx, DNS_COMPRESS_GLOBAL14);
+
+ dns_name_init(&name, offsets);
+ dns_rdata_toregion(rdata, &region);
+ dns_name_fromregion(&name, &region);
+
+ return (dns_name_towire(&name, cctx, target));
+}
+
+static int
+compare_mb(ARGS_COMPARE) {
+ dns_name_t name1;
+ dns_name_t name2;
+ isc_region_t region1;
+ isc_region_t region2;
+
+ REQUIRE(rdata1->type == rdata2->type);
+ REQUIRE(rdata1->rdclass == rdata2->rdclass);
+ REQUIRE(rdata1->type == dns_rdatatype_mb);
+ REQUIRE(rdata1->length != 0);
+ REQUIRE(rdata2->length != 0);
+
+ dns_name_init(&name1, NULL);
+ dns_name_init(&name2, NULL);
+
+ dns_rdata_toregion(rdata1, &region1);
+ dns_rdata_toregion(rdata2, &region2);
+
+ dns_name_fromregion(&name1, &region1);
+ dns_name_fromregion(&name2, &region2);
+
+ return (dns_name_rdatacompare(&name1, &name2));
+}
+
+static isc_result_t
+fromstruct_mb(ARGS_FROMSTRUCT) {
+ dns_rdata_mb_t *mb = source;
+ isc_region_t region;
+
+ REQUIRE(type == dns_rdatatype_mb);
+ REQUIRE(mb != NULL);
+ REQUIRE(mb->common.rdtype == type);
+ REQUIRE(mb->common.rdclass == rdclass);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ dns_name_toregion(&mb->mb, &region);
+ return (isc_buffer_copyregion(target, &region));
+}
+
+static isc_result_t
+tostruct_mb(ARGS_TOSTRUCT) {
+ isc_region_t region;
+ dns_rdata_mb_t *mb = target;
+ dns_name_t name;
+
+ REQUIRE(rdata->type == dns_rdatatype_mb);
+ REQUIRE(mb != NULL);
+ REQUIRE(rdata->length != 0);
+
+ mb->common.rdclass = rdata->rdclass;
+ mb->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&mb->common, link);
+
+ dns_name_init(&name, NULL);
+ dns_rdata_toregion(rdata, &region);
+ dns_name_fromregion(&name, &region);
+ dns_name_init(&mb->mb, NULL);
+ name_duporclone(&name, mctx, &mb->mb);
+ mb->mctx = mctx;
+ return (ISC_R_SUCCESS);
+}
+
+static void
+freestruct_mb(ARGS_FREESTRUCT) {
+ dns_rdata_mb_t *mb = source;
+
+ REQUIRE(mb != NULL);
+
+ if (mb->mctx == NULL) {
+ return;
+ }
+
+ dns_name_free(&mb->mb, mb->mctx);
+ mb->mctx = NULL;
+}
+
+static isc_result_t
+additionaldata_mb(ARGS_ADDLDATA) {
+ dns_name_t name;
+ dns_offsets_t offsets;
+ isc_region_t region;
+
+ REQUIRE(rdata->type == dns_rdatatype_mb);
+
+ UNUSED(owner);
+
+ dns_name_init(&name, offsets);
+ dns_rdata_toregion(rdata, &region);
+ dns_name_fromregion(&name, &region);
+
+ return ((add)(arg, &name, dns_rdatatype_a, NULL));
+}
+
+static isc_result_t
+digest_mb(ARGS_DIGEST) {
+ isc_region_t r;
+ dns_name_t name;
+
+ REQUIRE(rdata->type == dns_rdatatype_mb);
+
+ dns_rdata_toregion(rdata, &r);
+ dns_name_init(&name, NULL);
+ dns_name_fromregion(&name, &r);
+
+ return (dns_name_digest(&name, digest, arg));
+}
+
+static bool
+checkowner_mb(ARGS_CHECKOWNER) {
+ REQUIRE(type == dns_rdatatype_mb);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (dns_name_ismailbox(name));
+}
+
+static bool
+checknames_mb(ARGS_CHECKNAMES) {
+ REQUIRE(rdata->type == dns_rdatatype_mb);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(bad);
+
+ return (true);
+}
+
+static int
+casecompare_mb(ARGS_COMPARE) {
+ return (compare_mb(rdata1, rdata2));
+}
+
+#endif /* RDATA_GENERIC_MB_7_C */
diff --git a/lib/dns/rdata/generic/mb_7.h b/lib/dns/rdata/generic/mb_7.h
new file mode 100644
index 0000000..187e657
--- /dev/null
+++ b/lib/dns/rdata/generic/mb_7.h
@@ -0,0 +1,21 @@
+/*
+ * 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_mb {
+ dns_rdatacommon_t common;
+ isc_mem_t *mctx;
+ dns_name_t mb;
+} dns_rdata_mb_t;
diff --git a/lib/dns/rdata/generic/md_3.c b/lib/dns/rdata/generic/md_3.c
new file mode 100644
index 0000000..38d48d3
--- /dev/null
+++ b/lib/dns/rdata/generic/md_3.c
@@ -0,0 +1,236 @@
+/*
+ * 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_MD_3_C
+#define RDATA_GENERIC_MD_3_C
+
+#define RRTYPE_MD_ATTRIBUTES (0)
+
+static isc_result_t
+fromtext_md(ARGS_FROMTEXT) {
+ isc_token_t token;
+ dns_name_t name;
+ isc_buffer_t buffer;
+
+ REQUIRE(type == dns_rdatatype_md);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(callbacks);
+
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ false));
+
+ dns_name_init(&name, NULL);
+ buffer_fromregion(&buffer, &token.value.as_region);
+ if (origin == NULL) {
+ origin = dns_rootname;
+ }
+ RETTOK(dns_name_fromtext(&name, &buffer, origin, options, target));
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+totext_md(ARGS_TOTEXT) {
+ isc_region_t region;
+ dns_name_t name;
+ dns_name_t prefix;
+ bool sub;
+
+ REQUIRE(rdata->type == dns_rdatatype_md);
+ REQUIRE(rdata->length != 0);
+
+ dns_name_init(&name, NULL);
+ dns_name_init(&prefix, NULL);
+
+ dns_rdata_toregion(rdata, &region);
+ dns_name_fromregion(&name, &region);
+
+ sub = name_prefix(&name, tctx->origin, &prefix);
+
+ return (dns_name_totext(&prefix, sub, target));
+}
+
+static isc_result_t
+fromwire_md(ARGS_FROMWIRE) {
+ dns_name_t name;
+
+ REQUIRE(type == dns_rdatatype_md);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ dns_decompress_setmethods(dctx, DNS_COMPRESS_GLOBAL14);
+
+ dns_name_init(&name, NULL);
+ return (dns_name_fromwire(&name, source, dctx, options, target));
+}
+
+static isc_result_t
+towire_md(ARGS_TOWIRE) {
+ dns_name_t name;
+ dns_offsets_t offsets;
+ isc_region_t region;
+
+ REQUIRE(rdata->type == dns_rdatatype_md);
+ REQUIRE(rdata->length != 0);
+
+ dns_compress_setmethods(cctx, DNS_COMPRESS_GLOBAL14);
+
+ dns_name_init(&name, offsets);
+ dns_rdata_toregion(rdata, &region);
+ dns_name_fromregion(&name, &region);
+
+ return (dns_name_towire(&name, cctx, target));
+}
+
+static int
+compare_md(ARGS_COMPARE) {
+ dns_name_t name1;
+ dns_name_t name2;
+ isc_region_t region1;
+ isc_region_t region2;
+
+ REQUIRE(rdata1->type == rdata2->type);
+ REQUIRE(rdata1->rdclass == rdata2->rdclass);
+ REQUIRE(rdata1->type == dns_rdatatype_md);
+ REQUIRE(rdata1->length != 0);
+ REQUIRE(rdata2->length != 0);
+
+ dns_name_init(&name1, NULL);
+ dns_name_init(&name2, NULL);
+
+ dns_rdata_toregion(rdata1, &region1);
+ dns_rdata_toregion(rdata2, &region2);
+
+ dns_name_fromregion(&name1, &region1);
+ dns_name_fromregion(&name2, &region2);
+
+ return (dns_name_rdatacompare(&name1, &name2));
+}
+
+static isc_result_t
+fromstruct_md(ARGS_FROMSTRUCT) {
+ dns_rdata_md_t *md = source;
+ isc_region_t region;
+
+ REQUIRE(type == dns_rdatatype_md);
+ REQUIRE(md != NULL);
+ REQUIRE(md->common.rdtype == type);
+ REQUIRE(md->common.rdclass == rdclass);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ dns_name_toregion(&md->md, &region);
+ return (isc_buffer_copyregion(target, &region));
+}
+
+static isc_result_t
+tostruct_md(ARGS_TOSTRUCT) {
+ dns_rdata_md_t *md = target;
+ isc_region_t r;
+ dns_name_t name;
+
+ REQUIRE(rdata->type == dns_rdatatype_md);
+ REQUIRE(md != NULL);
+ REQUIRE(rdata->length != 0);
+
+ md->common.rdclass = rdata->rdclass;
+ md->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&md->common, link);
+
+ dns_name_init(&name, NULL);
+ dns_rdata_toregion(rdata, &r);
+ dns_name_fromregion(&name, &r);
+ dns_name_init(&md->md, NULL);
+ name_duporclone(&name, mctx, &md->md);
+ md->mctx = mctx;
+ return (ISC_R_SUCCESS);
+}
+
+static void
+freestruct_md(ARGS_FREESTRUCT) {
+ dns_rdata_md_t *md = source;
+
+ REQUIRE(md != NULL);
+ REQUIRE(md->common.rdtype == dns_rdatatype_md);
+
+ if (md->mctx == NULL) {
+ return;
+ }
+
+ dns_name_free(&md->md, md->mctx);
+ md->mctx = NULL;
+}
+
+static isc_result_t
+additionaldata_md(ARGS_ADDLDATA) {
+ dns_name_t name;
+ dns_offsets_t offsets;
+ isc_region_t region;
+
+ REQUIRE(rdata->type == dns_rdatatype_md);
+
+ UNUSED(owner);
+
+ dns_name_init(&name, offsets);
+ dns_rdata_toregion(rdata, &region);
+ dns_name_fromregion(&name, &region);
+
+ return ((add)(arg, &name, dns_rdatatype_a, NULL));
+}
+
+static isc_result_t
+digest_md(ARGS_DIGEST) {
+ isc_region_t r;
+ dns_name_t name;
+
+ REQUIRE(rdata->type == dns_rdatatype_md);
+
+ dns_rdata_toregion(rdata, &r);
+ dns_name_init(&name, NULL);
+ dns_name_fromregion(&name, &r);
+
+ return (dns_name_digest(&name, digest, arg));
+}
+
+static bool
+checkowner_md(ARGS_CHECKOWNER) {
+ REQUIRE(type == dns_rdatatype_md);
+
+ UNUSED(name);
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (true);
+}
+
+static bool
+checknames_md(ARGS_CHECKNAMES) {
+ REQUIRE(rdata->type == dns_rdatatype_md);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(bad);
+
+ return (true);
+}
+
+static int
+casecompare_md(ARGS_COMPARE) {
+ return (compare_md(rdata1, rdata2));
+}
+
+#endif /* RDATA_GENERIC_MD_3_C */
diff --git a/lib/dns/rdata/generic/md_3.h b/lib/dns/rdata/generic/md_3.h
new file mode 100644
index 0000000..530e2cb
--- /dev/null
+++ b/lib/dns/rdata/generic/md_3.h
@@ -0,0 +1,21 @@
+/*
+ * 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_md {
+ dns_rdatacommon_t common;
+ isc_mem_t *mctx;
+ dns_name_t md;
+} dns_rdata_md_t;
diff --git a/lib/dns/rdata/generic/mf_4.c b/lib/dns/rdata/generic/mf_4.c
new file mode 100644
index 0000000..3590767
--- /dev/null
+++ b/lib/dns/rdata/generic/mf_4.c
@@ -0,0 +1,235 @@
+/*
+ * 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_MF_4_C
+#define RDATA_GENERIC_MF_4_C
+
+#define RRTYPE_MF_ATTRIBUTES (0)
+
+static isc_result_t
+fromtext_mf(ARGS_FROMTEXT) {
+ isc_token_t token;
+ dns_name_t name;
+ isc_buffer_t buffer;
+
+ REQUIRE(type == dns_rdatatype_mf);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(callbacks);
+
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ false));
+
+ dns_name_init(&name, NULL);
+ buffer_fromregion(&buffer, &token.value.as_region);
+ if (origin == NULL) {
+ origin = dns_rootname;
+ }
+ RETTOK(dns_name_fromtext(&name, &buffer, origin, options, target));
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+totext_mf(ARGS_TOTEXT) {
+ isc_region_t region;
+ dns_name_t name;
+ dns_name_t prefix;
+ bool sub;
+
+ REQUIRE(rdata->type == dns_rdatatype_mf);
+ REQUIRE(rdata->length != 0);
+
+ dns_name_init(&name, NULL);
+ dns_name_init(&prefix, NULL);
+
+ dns_rdata_toregion(rdata, &region);
+ dns_name_fromregion(&name, &region);
+
+ sub = name_prefix(&name, tctx->origin, &prefix);
+
+ return (dns_name_totext(&prefix, sub, target));
+}
+
+static isc_result_t
+fromwire_mf(ARGS_FROMWIRE) {
+ dns_name_t name;
+
+ REQUIRE(type == dns_rdatatype_mf);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ dns_decompress_setmethods(dctx, DNS_COMPRESS_GLOBAL14);
+
+ dns_name_init(&name, NULL);
+ return (dns_name_fromwire(&name, source, dctx, options, target));
+}
+
+static isc_result_t
+towire_mf(ARGS_TOWIRE) {
+ dns_name_t name;
+ dns_offsets_t offsets;
+ isc_region_t region;
+
+ REQUIRE(rdata->type == dns_rdatatype_mf);
+ REQUIRE(rdata->length != 0);
+
+ dns_compress_setmethods(cctx, DNS_COMPRESS_GLOBAL14);
+
+ dns_name_init(&name, offsets);
+ dns_rdata_toregion(rdata, &region);
+ dns_name_fromregion(&name, &region);
+
+ return (dns_name_towire(&name, cctx, target));
+}
+
+static int
+compare_mf(ARGS_COMPARE) {
+ dns_name_t name1;
+ dns_name_t name2;
+ isc_region_t region1;
+ isc_region_t region2;
+
+ REQUIRE(rdata1->type == rdata2->type);
+ REQUIRE(rdata1->rdclass == rdata2->rdclass);
+ REQUIRE(rdata1->type == dns_rdatatype_mf);
+ REQUIRE(rdata1->length != 0);
+ REQUIRE(rdata2->length != 0);
+
+ dns_name_init(&name1, NULL);
+ dns_name_init(&name2, NULL);
+
+ dns_rdata_toregion(rdata1, &region1);
+ dns_rdata_toregion(rdata2, &region2);
+
+ dns_name_fromregion(&name1, &region1);
+ dns_name_fromregion(&name2, &region2);
+
+ return (dns_name_rdatacompare(&name1, &name2));
+}
+
+static isc_result_t
+fromstruct_mf(ARGS_FROMSTRUCT) {
+ dns_rdata_mf_t *mf = source;
+ isc_region_t region;
+
+ REQUIRE(type == dns_rdatatype_mf);
+ REQUIRE(mf != NULL);
+ REQUIRE(mf->common.rdtype == type);
+ REQUIRE(mf->common.rdclass == rdclass);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ dns_name_toregion(&mf->mf, &region);
+ return (isc_buffer_copyregion(target, &region));
+}
+
+static isc_result_t
+tostruct_mf(ARGS_TOSTRUCT) {
+ dns_rdata_mf_t *mf = target;
+ isc_region_t r;
+ dns_name_t name;
+
+ REQUIRE(rdata->type == dns_rdatatype_mf);
+ REQUIRE(mf != NULL);
+ REQUIRE(rdata->length != 0);
+
+ mf->common.rdclass = rdata->rdclass;
+ mf->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&mf->common, link);
+
+ dns_name_init(&name, NULL);
+ dns_rdata_toregion(rdata, &r);
+ dns_name_fromregion(&name, &r);
+ dns_name_init(&mf->mf, NULL);
+ name_duporclone(&name, mctx, &mf->mf);
+ mf->mctx = mctx;
+ return (ISC_R_SUCCESS);
+}
+
+static void
+freestruct_mf(ARGS_FREESTRUCT) {
+ dns_rdata_mf_t *mf = source;
+
+ REQUIRE(mf != NULL);
+ REQUIRE(mf->common.rdtype == dns_rdatatype_mf);
+
+ if (mf->mctx == NULL) {
+ return;
+ }
+ dns_name_free(&mf->mf, mf->mctx);
+ mf->mctx = NULL;
+}
+
+static isc_result_t
+additionaldata_mf(ARGS_ADDLDATA) {
+ dns_name_t name;
+ dns_offsets_t offsets;
+ isc_region_t region;
+
+ REQUIRE(rdata->type == dns_rdatatype_mf);
+
+ UNUSED(owner);
+
+ dns_name_init(&name, offsets);
+ dns_rdata_toregion(rdata, &region);
+ dns_name_fromregion(&name, &region);
+
+ return ((add)(arg, &name, dns_rdatatype_a, NULL));
+}
+
+static isc_result_t
+digest_mf(ARGS_DIGEST) {
+ isc_region_t r;
+ dns_name_t name;
+
+ REQUIRE(rdata->type == dns_rdatatype_mf);
+
+ dns_rdata_toregion(rdata, &r);
+ dns_name_init(&name, NULL);
+ dns_name_fromregion(&name, &r);
+
+ return (dns_name_digest(&name, digest, arg));
+}
+
+static bool
+checkowner_mf(ARGS_CHECKOWNER) {
+ REQUIRE(type == dns_rdatatype_mf);
+
+ UNUSED(name);
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (true);
+}
+
+static bool
+checknames_mf(ARGS_CHECKNAMES) {
+ REQUIRE(rdata->type == dns_rdatatype_mf);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(bad);
+
+ return (true);
+}
+
+static int
+casecompare_mf(ARGS_COMPARE) {
+ return (compare_mf(rdata1, rdata2));
+}
+
+#endif /* RDATA_GENERIC_MF_4_C */
diff --git a/lib/dns/rdata/generic/mf_4.h b/lib/dns/rdata/generic/mf_4.h
new file mode 100644
index 0000000..eb1559a
--- /dev/null
+++ b/lib/dns/rdata/generic/mf_4.h
@@ -0,0 +1,21 @@
+/*
+ * 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_mf {
+ dns_rdatacommon_t common;
+ isc_mem_t *mctx;
+ dns_name_t mf;
+} dns_rdata_mf_t;
diff --git a/lib/dns/rdata/generic/mg_8.c b/lib/dns/rdata/generic/mg_8.c
new file mode 100644
index 0000000..201a295
--- /dev/null
+++ b/lib/dns/rdata/generic/mg_8.c
@@ -0,0 +1,229 @@
+/*
+ * 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_MG_8_C
+#define RDATA_GENERIC_MG_8_C
+
+#define RRTYPE_MG_ATTRIBUTES (0)
+
+static isc_result_t
+fromtext_mg(ARGS_FROMTEXT) {
+ isc_token_t token;
+ dns_name_t name;
+ isc_buffer_t buffer;
+
+ REQUIRE(type == dns_rdatatype_mg);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(callbacks);
+
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ false));
+
+ dns_name_init(&name, NULL);
+ buffer_fromregion(&buffer, &token.value.as_region);
+ if (origin == NULL) {
+ origin = dns_rootname;
+ }
+ RETTOK(dns_name_fromtext(&name, &buffer, origin, options, target));
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+totext_mg(ARGS_TOTEXT) {
+ isc_region_t region;
+ dns_name_t name;
+ dns_name_t prefix;
+ bool sub;
+
+ REQUIRE(rdata->type == dns_rdatatype_mg);
+ REQUIRE(rdata->length != 0);
+
+ dns_name_init(&name, NULL);
+ dns_name_init(&prefix, NULL);
+
+ dns_rdata_toregion(rdata, &region);
+ dns_name_fromregion(&name, &region);
+
+ sub = name_prefix(&name, tctx->origin, &prefix);
+
+ return (dns_name_totext(&prefix, sub, target));
+}
+
+static isc_result_t
+fromwire_mg(ARGS_FROMWIRE) {
+ dns_name_t name;
+
+ REQUIRE(type == dns_rdatatype_mg);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ dns_decompress_setmethods(dctx, DNS_COMPRESS_GLOBAL14);
+
+ dns_name_init(&name, NULL);
+ return (dns_name_fromwire(&name, source, dctx, options, target));
+}
+
+static isc_result_t
+towire_mg(ARGS_TOWIRE) {
+ dns_name_t name;
+ dns_offsets_t offsets;
+ isc_region_t region;
+
+ REQUIRE(rdata->type == dns_rdatatype_mg);
+ REQUIRE(rdata->length != 0);
+
+ dns_compress_setmethods(cctx, DNS_COMPRESS_GLOBAL14);
+
+ dns_name_init(&name, offsets);
+ dns_rdata_toregion(rdata, &region);
+ dns_name_fromregion(&name, &region);
+
+ return (dns_name_towire(&name, cctx, target));
+}
+
+static int
+compare_mg(ARGS_COMPARE) {
+ dns_name_t name1;
+ dns_name_t name2;
+ isc_region_t region1;
+ isc_region_t region2;
+
+ REQUIRE(rdata1->type == rdata2->type);
+ REQUIRE(rdata1->rdclass == rdata2->rdclass);
+ REQUIRE(rdata1->type == dns_rdatatype_mg);
+ REQUIRE(rdata1->length != 0);
+ REQUIRE(rdata2->length != 0);
+
+ dns_name_init(&name1, NULL);
+ dns_name_init(&name2, NULL);
+
+ dns_rdata_toregion(rdata1, &region1);
+ dns_rdata_toregion(rdata2, &region2);
+
+ dns_name_fromregion(&name1, &region1);
+ dns_name_fromregion(&name2, &region2);
+
+ return (dns_name_rdatacompare(&name1, &name2));
+}
+
+static isc_result_t
+fromstruct_mg(ARGS_FROMSTRUCT) {
+ dns_rdata_mg_t *mg = source;
+ isc_region_t region;
+
+ REQUIRE(type == dns_rdatatype_mg);
+ REQUIRE(mg != NULL);
+ REQUIRE(mg->common.rdtype == type);
+ REQUIRE(mg->common.rdclass == rdclass);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ dns_name_toregion(&mg->mg, &region);
+ return (isc_buffer_copyregion(target, &region));
+}
+
+static isc_result_t
+tostruct_mg(ARGS_TOSTRUCT) {
+ isc_region_t region;
+ dns_rdata_mg_t *mg = target;
+ dns_name_t name;
+
+ REQUIRE(rdata->type == dns_rdatatype_mg);
+ REQUIRE(mg != NULL);
+ REQUIRE(rdata->length != 0);
+
+ mg->common.rdclass = rdata->rdclass;
+ mg->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&mg->common, link);
+
+ dns_name_init(&name, NULL);
+ dns_rdata_toregion(rdata, &region);
+ dns_name_fromregion(&name, &region);
+ dns_name_init(&mg->mg, NULL);
+ name_duporclone(&name, mctx, &mg->mg);
+ mg->mctx = mctx;
+ return (ISC_R_SUCCESS);
+}
+
+static void
+freestruct_mg(ARGS_FREESTRUCT) {
+ dns_rdata_mg_t *mg = source;
+
+ REQUIRE(mg != NULL);
+ REQUIRE(mg->common.rdtype == dns_rdatatype_mg);
+
+ if (mg->mctx == NULL) {
+ return;
+ }
+ dns_name_free(&mg->mg, mg->mctx);
+ mg->mctx = NULL;
+}
+
+static isc_result_t
+additionaldata_mg(ARGS_ADDLDATA) {
+ REQUIRE(rdata->type == dns_rdatatype_mg);
+
+ UNUSED(add);
+ UNUSED(arg);
+ UNUSED(rdata);
+ UNUSED(owner);
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+digest_mg(ARGS_DIGEST) {
+ isc_region_t r;
+ dns_name_t name;
+
+ REQUIRE(rdata->type == dns_rdatatype_mg);
+
+ dns_rdata_toregion(rdata, &r);
+ dns_name_init(&name, NULL);
+ dns_name_fromregion(&name, &r);
+
+ return (dns_name_digest(&name, digest, arg));
+}
+
+static bool
+checkowner_mg(ARGS_CHECKOWNER) {
+ REQUIRE(type == dns_rdatatype_mg);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (dns_name_ismailbox(name));
+}
+
+static bool
+checknames_mg(ARGS_CHECKNAMES) {
+ REQUIRE(rdata->type == dns_rdatatype_mg);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(bad);
+
+ return (true);
+}
+
+static int
+casecompare_mg(ARGS_COMPARE) {
+ return (compare_mg(rdata1, rdata2));
+}
+
+#endif /* RDATA_GENERIC_MG_8_C */
diff --git a/lib/dns/rdata/generic/mg_8.h b/lib/dns/rdata/generic/mg_8.h
new file mode 100644
index 0000000..09fd206
--- /dev/null
+++ b/lib/dns/rdata/generic/mg_8.h
@@ -0,0 +1,21 @@
+/*
+ * 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_mg {
+ dns_rdatacommon_t common;
+ isc_mem_t *mctx;
+ dns_name_t mg;
+} dns_rdata_mg_t;
diff --git a/lib/dns/rdata/generic/minfo_14.c b/lib/dns/rdata/generic/minfo_14.c
new file mode 100644
index 0000000..38ff8bd
--- /dev/null
+++ b/lib/dns/rdata/generic/minfo_14.c
@@ -0,0 +1,323 @@
+/*
+ * 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_MINFO_14_C
+#define RDATA_GENERIC_MINFO_14_C
+
+#define RRTYPE_MINFO_ATTRIBUTES (0)
+
+static isc_result_t
+fromtext_minfo(ARGS_FROMTEXT) {
+ isc_token_t token;
+ dns_name_t name;
+ isc_buffer_t buffer;
+ int i;
+ bool ok;
+
+ REQUIRE(type == dns_rdatatype_minfo);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(callbacks);
+
+ if (origin == NULL) {
+ origin = dns_rootname;
+ }
+
+ for (i = 0; i < 2; i++) {
+ RETERR(isc_lex_getmastertoken(lexer, &token,
+ isc_tokentype_string, false));
+ dns_name_init(&name, NULL);
+ buffer_fromregion(&buffer, &token.value.as_region);
+ RETTOK(dns_name_fromtext(&name, &buffer, origin, options,
+ target));
+ ok = true;
+ if ((options & DNS_RDATA_CHECKNAMES) != 0) {
+ ok = dns_name_ismailbox(&name);
+ }
+ 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_minfo(ARGS_TOTEXT) {
+ isc_region_t region;
+ dns_name_t rmail;
+ dns_name_t email;
+ dns_name_t prefix;
+ bool sub;
+
+ REQUIRE(rdata->type == dns_rdatatype_minfo);
+ REQUIRE(rdata->length != 0);
+
+ dns_name_init(&rmail, NULL);
+ dns_name_init(&email, NULL);
+ dns_name_init(&prefix, NULL);
+
+ dns_rdata_toregion(rdata, &region);
+
+ dns_name_fromregion(&rmail, &region);
+ isc_region_consume(&region, rmail.length);
+
+ dns_name_fromregion(&email, &region);
+ isc_region_consume(&region, email.length);
+
+ sub = name_prefix(&rmail, tctx->origin, &prefix);
+
+ RETERR(dns_name_totext(&prefix, sub, target));
+
+ RETERR(str_totext(" ", target));
+
+ sub = name_prefix(&email, tctx->origin, &prefix);
+ return (dns_name_totext(&prefix, sub, target));
+}
+
+static isc_result_t
+fromwire_minfo(ARGS_FROMWIRE) {
+ dns_name_t rmail;
+ dns_name_t email;
+
+ REQUIRE(type == dns_rdatatype_minfo);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ dns_decompress_setmethods(dctx, DNS_COMPRESS_GLOBAL14);
+
+ dns_name_init(&rmail, NULL);
+ dns_name_init(&email, NULL);
+
+ RETERR(dns_name_fromwire(&rmail, source, dctx, options, target));
+ return (dns_name_fromwire(&email, source, dctx, options, target));
+}
+
+static isc_result_t
+towire_minfo(ARGS_TOWIRE) {
+ isc_region_t region;
+ dns_name_t rmail;
+ dns_name_t email;
+ dns_offsets_t roffsets;
+ dns_offsets_t eoffsets;
+
+ REQUIRE(rdata->type == dns_rdatatype_minfo);
+ REQUIRE(rdata->length != 0);
+
+ dns_compress_setmethods(cctx, DNS_COMPRESS_GLOBAL14);
+
+ dns_name_init(&rmail, roffsets);
+ dns_name_init(&email, eoffsets);
+
+ dns_rdata_toregion(rdata, &region);
+
+ dns_name_fromregion(&rmail, &region);
+ isc_region_consume(&region, name_length(&rmail));
+
+ RETERR(dns_name_towire(&rmail, cctx, target));
+
+ dns_name_fromregion(&rmail, &region);
+ isc_region_consume(&region, rmail.length);
+
+ return (dns_name_towire(&rmail, cctx, target));
+}
+
+static int
+compare_minfo(ARGS_COMPARE) {
+ isc_region_t region1;
+ isc_region_t region2;
+ dns_name_t name1;
+ dns_name_t name2;
+ int order;
+
+ REQUIRE(rdata1->type == rdata2->type);
+ REQUIRE(rdata1->rdclass == rdata2->rdclass);
+ REQUIRE(rdata1->type == dns_rdatatype_minfo);
+ REQUIRE(rdata1->length != 0);
+ REQUIRE(rdata2->length != 0);
+
+ dns_name_init(&name1, NULL);
+ dns_name_init(&name2, NULL);
+
+ dns_rdata_toregion(rdata1, &region1);
+ dns_rdata_toregion(rdata2, &region2);
+
+ dns_name_fromregion(&name1, &region1);
+ dns_name_fromregion(&name2, &region2);
+
+ order = dns_name_rdatacompare(&name1, &name2);
+ if (order != 0) {
+ return (order);
+ }
+
+ isc_region_consume(&region1, name_length(&name1));
+ isc_region_consume(&region2, name_length(&name2));
+
+ dns_name_init(&name1, NULL);
+ dns_name_init(&name2, NULL);
+
+ dns_name_fromregion(&name1, &region1);
+ dns_name_fromregion(&name2, &region2);
+
+ order = dns_name_rdatacompare(&name1, &name2);
+ return (order);
+}
+
+static isc_result_t
+fromstruct_minfo(ARGS_FROMSTRUCT) {
+ dns_rdata_minfo_t *minfo = source;
+ isc_region_t region;
+
+ REQUIRE(type == dns_rdatatype_minfo);
+ REQUIRE(minfo != NULL);
+ REQUIRE(minfo->common.rdtype == type);
+ REQUIRE(minfo->common.rdclass == rdclass);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ dns_name_toregion(&minfo->rmailbox, &region);
+ RETERR(isc_buffer_copyregion(target, &region));
+ dns_name_toregion(&minfo->emailbox, &region);
+ return (isc_buffer_copyregion(target, &region));
+}
+
+static isc_result_t
+tostruct_minfo(ARGS_TOSTRUCT) {
+ dns_rdata_minfo_t *minfo = target;
+ isc_region_t region;
+ dns_name_t name;
+
+ REQUIRE(rdata->type == dns_rdatatype_minfo);
+ REQUIRE(minfo != NULL);
+ REQUIRE(rdata->length != 0);
+
+ minfo->common.rdclass = rdata->rdclass;
+ minfo->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&minfo->common, link);
+
+ dns_name_init(&name, NULL);
+ dns_rdata_toregion(rdata, &region);
+ dns_name_fromregion(&name, &region);
+ dns_name_init(&minfo->rmailbox, NULL);
+ name_duporclone(&name, mctx, &minfo->rmailbox);
+ isc_region_consume(&region, name_length(&name));
+
+ dns_name_fromregion(&name, &region);
+ dns_name_init(&minfo->emailbox, NULL);
+ name_duporclone(&name, mctx, &minfo->emailbox);
+ minfo->mctx = mctx;
+ return (ISC_R_SUCCESS);
+}
+
+static void
+freestruct_minfo(ARGS_FREESTRUCT) {
+ dns_rdata_minfo_t *minfo = source;
+
+ REQUIRE(minfo != NULL);
+ REQUIRE(minfo->common.rdtype == dns_rdatatype_minfo);
+
+ if (minfo->mctx == NULL) {
+ return;
+ }
+
+ dns_name_free(&minfo->rmailbox, minfo->mctx);
+ dns_name_free(&minfo->emailbox, minfo->mctx);
+ minfo->mctx = NULL;
+}
+
+static isc_result_t
+additionaldata_minfo(ARGS_ADDLDATA) {
+ REQUIRE(rdata->type == dns_rdatatype_minfo);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(add);
+ UNUSED(arg);
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+digest_minfo(ARGS_DIGEST) {
+ isc_region_t r;
+ dns_name_t name;
+ isc_result_t result;
+
+ REQUIRE(rdata->type == dns_rdatatype_minfo);
+
+ dns_rdata_toregion(rdata, &r);
+ dns_name_init(&name, NULL);
+ dns_name_fromregion(&name, &r);
+ result = dns_name_digest(&name, digest, arg);
+ if (result != ISC_R_SUCCESS) {
+ return (result);
+ }
+ isc_region_consume(&r, name_length(&name));
+ dns_name_init(&name, NULL);
+ dns_name_fromregion(&name, &r);
+
+ return (dns_name_digest(&name, digest, arg));
+}
+
+static bool
+checkowner_minfo(ARGS_CHECKOWNER) {
+ REQUIRE(type == dns_rdatatype_minfo);
+
+ UNUSED(name);
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (true);
+}
+
+static bool
+checknames_minfo(ARGS_CHECKNAMES) {
+ isc_region_t region;
+ dns_name_t name;
+
+ REQUIRE(rdata->type == dns_rdatatype_minfo);
+
+ UNUSED(owner);
+
+ dns_rdata_toregion(rdata, &region);
+ dns_name_init(&name, NULL);
+ dns_name_fromregion(&name, &region);
+ if (!dns_name_ismailbox(&name)) {
+ if (bad != NULL) {
+ dns_name_clone(&name, bad);
+ }
+ return (false);
+ }
+ isc_region_consume(&region, name_length(&name));
+ dns_name_fromregion(&name, &region);
+ if (!dns_name_ismailbox(&name)) {
+ if (bad != NULL) {
+ dns_name_clone(&name, bad);
+ }
+ return (false);
+ }
+ return (true);
+}
+
+static int
+casecompare_minfo(ARGS_COMPARE) {
+ return (compare_minfo(rdata1, rdata2));
+}
+
+#endif /* RDATA_GENERIC_MINFO_14_C */
diff --git a/lib/dns/rdata/generic/minfo_14.h b/lib/dns/rdata/generic/minfo_14.h
new file mode 100644
index 0000000..f2a530a
--- /dev/null
+++ b/lib/dns/rdata/generic/minfo_14.h
@@ -0,0 +1,22 @@
+/*
+ * 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_minfo {
+ dns_rdatacommon_t common;
+ isc_mem_t *mctx;
+ dns_name_t rmailbox;
+ dns_name_t emailbox;
+} dns_rdata_minfo_t;
diff --git a/lib/dns/rdata/generic/mr_9.c b/lib/dns/rdata/generic/mr_9.c
new file mode 100644
index 0000000..4ea279b
--- /dev/null
+++ b/lib/dns/rdata/generic/mr_9.c
@@ -0,0 +1,230 @@
+/*
+ * 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_MR_9_C
+#define RDATA_GENERIC_MR_9_C
+
+#define RRTYPE_MR_ATTRIBUTES (0)
+
+static isc_result_t
+fromtext_mr(ARGS_FROMTEXT) {
+ isc_token_t token;
+ dns_name_t name;
+ isc_buffer_t buffer;
+
+ REQUIRE(type == dns_rdatatype_mr);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(callbacks);
+
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ false));
+
+ dns_name_init(&name, NULL);
+ buffer_fromregion(&buffer, &token.value.as_region);
+ if (origin == NULL) {
+ origin = dns_rootname;
+ }
+ RETTOK(dns_name_fromtext(&name, &buffer, origin, options, target));
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+totext_mr(ARGS_TOTEXT) {
+ isc_region_t region;
+ dns_name_t name;
+ dns_name_t prefix;
+ bool sub;
+
+ REQUIRE(rdata->type == dns_rdatatype_mr);
+ REQUIRE(rdata->length != 0);
+
+ dns_name_init(&name, NULL);
+ dns_name_init(&prefix, NULL);
+
+ dns_rdata_toregion(rdata, &region);
+ dns_name_fromregion(&name, &region);
+
+ sub = name_prefix(&name, tctx->origin, &prefix);
+
+ return (dns_name_totext(&prefix, sub, target));
+}
+
+static isc_result_t
+fromwire_mr(ARGS_FROMWIRE) {
+ dns_name_t name;
+
+ REQUIRE(type == dns_rdatatype_mr);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ dns_decompress_setmethods(dctx, DNS_COMPRESS_GLOBAL14);
+
+ dns_name_init(&name, NULL);
+ return (dns_name_fromwire(&name, source, dctx, options, target));
+}
+
+static isc_result_t
+towire_mr(ARGS_TOWIRE) {
+ dns_name_t name;
+ dns_offsets_t offsets;
+ isc_region_t region;
+
+ REQUIRE(rdata->type == dns_rdatatype_mr);
+ REQUIRE(rdata->length != 0);
+
+ dns_compress_setmethods(cctx, DNS_COMPRESS_GLOBAL14);
+
+ dns_name_init(&name, offsets);
+ dns_rdata_toregion(rdata, &region);
+ dns_name_fromregion(&name, &region);
+
+ return (dns_name_towire(&name, cctx, target));
+}
+
+static int
+compare_mr(ARGS_COMPARE) {
+ dns_name_t name1;
+ dns_name_t name2;
+ isc_region_t region1;
+ isc_region_t region2;
+
+ REQUIRE(rdata1->type == rdata2->type);
+ REQUIRE(rdata1->rdclass == rdata2->rdclass);
+ REQUIRE(rdata1->type == dns_rdatatype_mr);
+ REQUIRE(rdata1->length != 0);
+ REQUIRE(rdata2->length != 0);
+
+ dns_name_init(&name1, NULL);
+ dns_name_init(&name2, NULL);
+
+ dns_rdata_toregion(rdata1, &region1);
+ dns_rdata_toregion(rdata2, &region2);
+
+ dns_name_fromregion(&name1, &region1);
+ dns_name_fromregion(&name2, &region2);
+
+ return (dns_name_rdatacompare(&name1, &name2));
+}
+
+static isc_result_t
+fromstruct_mr(ARGS_FROMSTRUCT) {
+ dns_rdata_mr_t *mr = source;
+ isc_region_t region;
+
+ REQUIRE(type == dns_rdatatype_mr);
+ REQUIRE(mr != NULL);
+ REQUIRE(mr->common.rdtype == type);
+ REQUIRE(mr->common.rdclass == rdclass);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ dns_name_toregion(&mr->mr, &region);
+ return (isc_buffer_copyregion(target, &region));
+}
+
+static isc_result_t
+tostruct_mr(ARGS_TOSTRUCT) {
+ isc_region_t region;
+ dns_rdata_mr_t *mr = target;
+ dns_name_t name;
+
+ REQUIRE(rdata->type == dns_rdatatype_mr);
+ REQUIRE(mr != NULL);
+ REQUIRE(rdata->length != 0);
+
+ mr->common.rdclass = rdata->rdclass;
+ mr->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&mr->common, link);
+
+ dns_name_init(&name, NULL);
+ dns_rdata_toregion(rdata, &region);
+ dns_name_fromregion(&name, &region);
+ dns_name_init(&mr->mr, NULL);
+ name_duporclone(&name, mctx, &mr->mr);
+ mr->mctx = mctx;
+ return (ISC_R_SUCCESS);
+}
+
+static void
+freestruct_mr(ARGS_FREESTRUCT) {
+ dns_rdata_mr_t *mr = source;
+
+ REQUIRE(mr != NULL);
+ REQUIRE(mr->common.rdtype == dns_rdatatype_mr);
+
+ if (mr->mctx == NULL) {
+ return;
+ }
+ dns_name_free(&mr->mr, mr->mctx);
+ mr->mctx = NULL;
+}
+
+static isc_result_t
+additionaldata_mr(ARGS_ADDLDATA) {
+ REQUIRE(rdata->type == dns_rdatatype_mr);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(add);
+ UNUSED(arg);
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+digest_mr(ARGS_DIGEST) {
+ isc_region_t r;
+ dns_name_t name;
+
+ REQUIRE(rdata->type == dns_rdatatype_mr);
+
+ dns_rdata_toregion(rdata, &r);
+ dns_name_init(&name, NULL);
+ dns_name_fromregion(&name, &r);
+
+ return (dns_name_digest(&name, digest, arg));
+}
+
+static bool
+checkowner_mr(ARGS_CHECKOWNER) {
+ REQUIRE(type == dns_rdatatype_mr);
+
+ UNUSED(name);
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (true);
+}
+
+static bool
+checknames_mr(ARGS_CHECKNAMES) {
+ REQUIRE(rdata->type == dns_rdatatype_mr);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(bad);
+
+ return (true);
+}
+
+static int
+casecompare_mr(ARGS_COMPARE) {
+ return (compare_mr(rdata1, rdata2));
+}
+
+#endif /* RDATA_GENERIC_MR_9_C */
diff --git a/lib/dns/rdata/generic/mr_9.h b/lib/dns/rdata/generic/mr_9.h
new file mode 100644
index 0000000..e9a876e
--- /dev/null
+++ b/lib/dns/rdata/generic/mr_9.h
@@ -0,0 +1,21 @@
+/*
+ * 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_mr {
+ dns_rdatacommon_t common;
+ isc_mem_t *mctx;
+ dns_name_t mr;
+} dns_rdata_mr_t;
diff --git a/lib/dns/rdata/generic/mx_15.c b/lib/dns/rdata/generic/mx_15.c
new file mode 100644
index 0000000..9356f0d
--- /dev/null
+++ b/lib/dns/rdata/generic/mx_15.c
@@ -0,0 +1,359 @@
+/*
+ * 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_MX_15_C
+#define RDATA_GENERIC_MX_15_C
+
+#include <string.h>
+
+#include <isc/net.h>
+
+#include <dns/fixedname.h>
+
+#define RRTYPE_MX_ATTRIBUTES (0)
+
+static bool
+check_mx(isc_token_t *token) {
+ char tmp[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:123.123.123.123.")];
+ struct in_addr addr;
+ struct in6_addr addr6;
+
+ if (strlcpy(tmp, DNS_AS_STR(*token), sizeof(tmp)) >= sizeof(tmp)) {
+ return (true);
+ }
+
+ if (tmp[strlen(tmp) - 1] == '.') {
+ tmp[strlen(tmp) - 1] = '\0';
+ }
+ if (inet_pton(AF_INET, tmp, &addr) == 1 ||
+ inet_pton(AF_INET6, tmp, &addr6) == 1)
+ {
+ return (false);
+ }
+
+ return (true);
+}
+
+static isc_result_t
+fromtext_mx(ARGS_FROMTEXT) {
+ isc_token_t token;
+ dns_name_t name;
+ isc_buffer_t buffer;
+ bool ok;
+
+ REQUIRE(type == dns_rdatatype_mx);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ 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));
+
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ false));
+
+ ok = true;
+ if ((options & DNS_RDATA_CHECKMX) != 0) {
+ ok = check_mx(&token);
+ }
+ if (!ok && (options & DNS_RDATA_CHECKMXFAIL) != 0) {
+ RETTOK(DNS_R_MXISADDRESS);
+ }
+ if (!ok && callbacks != NULL) {
+ warn_badmx(&token, lexer, callbacks);
+ }
+
+ dns_name_init(&name, NULL);
+ buffer_fromregion(&buffer, &token.value.as_region);
+ if (origin == NULL) {
+ origin = dns_rootname;
+ }
+ RETTOK(dns_name_fromtext(&name, &buffer, origin, options, target));
+ ok = true;
+ 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_mx(ARGS_TOTEXT) {
+ isc_region_t region;
+ dns_name_t name;
+ dns_name_t prefix;
+ bool sub;
+ char buf[sizeof("64000")];
+ unsigned short num;
+
+ REQUIRE(rdata->type == dns_rdatatype_mx);
+ REQUIRE(rdata->length != 0);
+
+ dns_name_init(&name, NULL);
+ dns_name_init(&prefix, NULL);
+
+ dns_rdata_toregion(rdata, &region);
+ num = uint16_fromregion(&region);
+ isc_region_consume(&region, 2);
+ snprintf(buf, sizeof(buf), "%u", num);
+ RETERR(str_totext(buf, target));
+
+ RETERR(str_totext(" ", target));
+
+ dns_name_fromregion(&name, &region);
+ sub = name_prefix(&name, tctx->origin, &prefix);
+ return (dns_name_totext(&prefix, sub, target));
+}
+
+static isc_result_t
+fromwire_mx(ARGS_FROMWIRE) {
+ dns_name_t name;
+ isc_region_t sregion;
+
+ REQUIRE(type == dns_rdatatype_mx);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ dns_decompress_setmethods(dctx, DNS_COMPRESS_GLOBAL14);
+
+ dns_name_init(&name, NULL);
+
+ isc_buffer_activeregion(source, &sregion);
+ if (sregion.length < 2) {
+ return (ISC_R_UNEXPECTEDEND);
+ }
+ RETERR(mem_tobuffer(target, sregion.base, 2));
+ isc_buffer_forward(source, 2);
+ return (dns_name_fromwire(&name, source, dctx, options, target));
+}
+
+static isc_result_t
+towire_mx(ARGS_TOWIRE) {
+ dns_name_t name;
+ dns_offsets_t offsets;
+ isc_region_t region;
+
+ REQUIRE(rdata->type == dns_rdatatype_mx);
+ REQUIRE(rdata->length != 0);
+
+ dns_compress_setmethods(cctx, DNS_COMPRESS_GLOBAL14);
+
+ dns_rdata_toregion(rdata, &region);
+ RETERR(mem_tobuffer(target, region.base, 2));
+ isc_region_consume(&region, 2);
+
+ dns_name_init(&name, offsets);
+ dns_name_fromregion(&name, &region);
+
+ return (dns_name_towire(&name, cctx, target));
+}
+
+static int
+compare_mx(ARGS_COMPARE) {
+ dns_name_t name1;
+ dns_name_t name2;
+ isc_region_t region1;
+ isc_region_t region2;
+ int order;
+
+ REQUIRE(rdata1->type == rdata2->type);
+ REQUIRE(rdata1->rdclass == rdata2->rdclass);
+ REQUIRE(rdata1->type == dns_rdatatype_mx);
+ REQUIRE(rdata1->length != 0);
+ REQUIRE(rdata2->length != 0);
+
+ order = memcmp(rdata1->data, rdata2->data, 2);
+ if (order != 0) {
+ return (order < 0 ? -1 : 1);
+ }
+
+ dns_name_init(&name1, NULL);
+ dns_name_init(&name2, NULL);
+
+ dns_rdata_toregion(rdata1, &region1);
+ dns_rdata_toregion(rdata2, &region2);
+
+ isc_region_consume(&region1, 2);
+ isc_region_consume(&region2, 2);
+
+ dns_name_fromregion(&name1, &region1);
+ dns_name_fromregion(&name2, &region2);
+
+ return (dns_name_rdatacompare(&name1, &name2));
+}
+
+static isc_result_t
+fromstruct_mx(ARGS_FROMSTRUCT) {
+ dns_rdata_mx_t *mx = source;
+ isc_region_t region;
+
+ REQUIRE(type == dns_rdatatype_mx);
+ REQUIRE(mx != NULL);
+ REQUIRE(mx->common.rdtype == type);
+ REQUIRE(mx->common.rdclass == rdclass);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ RETERR(uint16_tobuffer(mx->pref, target));
+ dns_name_toregion(&mx->mx, &region);
+ return (isc_buffer_copyregion(target, &region));
+}
+
+static isc_result_t
+tostruct_mx(ARGS_TOSTRUCT) {
+ isc_region_t region;
+ dns_rdata_mx_t *mx = target;
+ dns_name_t name;
+
+ REQUIRE(rdata->type == dns_rdatatype_mx);
+ REQUIRE(mx != NULL);
+ REQUIRE(rdata->length != 0);
+
+ mx->common.rdclass = rdata->rdclass;
+ mx->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&mx->common, link);
+
+ dns_name_init(&name, NULL);
+ dns_rdata_toregion(rdata, &region);
+ mx->pref = uint16_fromregion(&region);
+ isc_region_consume(&region, 2);
+ dns_name_fromregion(&name, &region);
+ dns_name_init(&mx->mx, NULL);
+ name_duporclone(&name, mctx, &mx->mx);
+ mx->mctx = mctx;
+ return (ISC_R_SUCCESS);
+}
+
+static void
+freestruct_mx(ARGS_FREESTRUCT) {
+ dns_rdata_mx_t *mx = source;
+
+ REQUIRE(mx != NULL);
+ REQUIRE(mx->common.rdtype == dns_rdatatype_mx);
+
+ if (mx->mctx == NULL) {
+ return;
+ }
+
+ dns_name_free(&mx->mx, mx->mctx);
+ mx->mctx = NULL;
+}
+
+static unsigned char port25_offset[] = { 0, 3 };
+static unsigned char port25_ndata[] = "\003_25\004_tcp";
+static dns_name_t port25 = DNS_NAME_INITNONABSOLUTE(port25_ndata,
+ port25_offset);
+
+static isc_result_t
+additionaldata_mx(ARGS_ADDLDATA) {
+ isc_result_t result;
+ dns_fixedname_t fixed;
+ dns_name_t name;
+ dns_offsets_t offsets;
+ isc_region_t region;
+
+ REQUIRE(rdata->type == dns_rdatatype_mx);
+
+ UNUSED(owner);
+
+ dns_name_init(&name, offsets);
+ dns_rdata_toregion(rdata, &region);
+ isc_region_consume(&region, 2);
+ dns_name_fromregion(&name, &region);
+
+ if (dns_name_equal(&name, dns_rootname)) {
+ return (ISC_R_SUCCESS);
+ }
+
+ result = (add)(arg, &name, dns_rdatatype_a, NULL);
+ if (result != ISC_R_SUCCESS) {
+ return (result);
+ }
+
+ dns_fixedname_init(&fixed);
+ result = dns_name_concatenate(&port25, &name,
+ dns_fixedname_name(&fixed), NULL);
+ if (result != ISC_R_SUCCESS) {
+ return (ISC_R_SUCCESS);
+ }
+
+ return ((add)(arg, dns_fixedname_name(&fixed), dns_rdatatype_tlsa,
+ NULL));
+}
+
+static isc_result_t
+digest_mx(ARGS_DIGEST) {
+ isc_region_t r1, r2;
+ dns_name_t name;
+
+ REQUIRE(rdata->type == dns_rdatatype_mx);
+
+ dns_rdata_toregion(rdata, &r1);
+ r2 = r1;
+ isc_region_consume(&r2, 2);
+ r1.length = 2;
+ RETERR((digest)(arg, &r1));
+ dns_name_init(&name, NULL);
+ dns_name_fromregion(&name, &r2);
+ return (dns_name_digest(&name, digest, arg));
+}
+
+static bool
+checkowner_mx(ARGS_CHECKOWNER) {
+ REQUIRE(type == dns_rdatatype_mx);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ return (dns_name_ishostname(name, wildcard));
+}
+
+static bool
+checknames_mx(ARGS_CHECKNAMES) {
+ isc_region_t region;
+ dns_name_t name;
+
+ REQUIRE(rdata->type == dns_rdatatype_mx);
+
+ UNUSED(owner);
+
+ dns_rdata_toregion(rdata, &region);
+ isc_region_consume(&region, 2);
+ dns_name_init(&name, NULL);
+ dns_name_fromregion(&name, &region);
+ if (!dns_name_ishostname(&name, false)) {
+ if (bad != NULL) {
+ dns_name_clone(&name, bad);
+ }
+ return (false);
+ }
+ return (true);
+}
+
+static int
+casecompare_mx(ARGS_COMPARE) {
+ return (compare_mx(rdata1, rdata2));
+}
+
+#endif /* RDATA_GENERIC_MX_15_C */
diff --git a/lib/dns/rdata/generic/mx_15.h b/lib/dns/rdata/generic/mx_15.h
new file mode 100644
index 0000000..f651591
--- /dev/null
+++ b/lib/dns/rdata/generic/mx_15.h
@@ -0,0 +1,22 @@
+/*
+ * 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_mx {
+ dns_rdatacommon_t common;
+ isc_mem_t *mctx;
+ uint16_t pref;
+ dns_name_t mx;
+} dns_rdata_mx_t;
diff --git a/lib/dns/rdata/generic/naptr_35.c b/lib/dns/rdata/generic/naptr_35.c
new file mode 100644
index 0000000..3db485a
--- /dev/null
+++ b/lib/dns/rdata/generic/naptr_35.c
@@ -0,0 +1,738 @@
+/*
+ * 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.
+ */
+
+/* RFC2915 */
+
+#ifndef RDATA_GENERIC_NAPTR_35_C
+#define RDATA_GENERIC_NAPTR_35_C
+
+#define RRTYPE_NAPTR_ATTRIBUTES (0)
+
+#include <isc/regex.h>
+
+/*
+ * Check the wire format of the Regexp field.
+ * Don't allow embedded NUL's.
+ */
+static isc_result_t
+txt_valid_regex(const unsigned char *txt) {
+ unsigned int nsub = 0;
+ char regex[256];
+ char *cp;
+ bool flags = false;
+ bool replace = false;
+ unsigned char c;
+ unsigned char delim;
+ unsigned int len;
+ int n;
+
+ len = *txt++;
+ if (len == 0U) {
+ return (ISC_R_SUCCESS);
+ }
+
+ delim = *txt++;
+ len--;
+
+ /*
+ * Digits, backslash and flags can't be delimiters.
+ */
+ switch (delim) {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ case '\\':
+ case 'i':
+ case 0:
+ return (DNS_R_SYNTAX);
+ }
+
+ cp = regex;
+ while (len-- > 0) {
+ c = *txt++;
+ if (c == 0) {
+ return (DNS_R_SYNTAX);
+ }
+ if (c == delim && !replace) {
+ replace = true;
+ continue;
+ } else if (c == delim && !flags) {
+ flags = true;
+ continue;
+ } else if (c == delim) {
+ return (DNS_R_SYNTAX);
+ }
+ /*
+ * Flags are not escaped.
+ */
+ if (flags) {
+ switch (c) {
+ case 'i':
+ continue;
+ default:
+ return (DNS_R_SYNTAX);
+ }
+ }
+ if (!replace) {
+ *cp++ = c;
+ }
+ if (c == '\\') {
+ if (len == 0) {
+ return (DNS_R_SYNTAX);
+ }
+ c = *txt++;
+ if (c == 0) {
+ return (DNS_R_SYNTAX);
+ }
+ len--;
+ if (replace) {
+ switch (c) {
+ case '0':
+ return (DNS_R_SYNTAX);
+ case '1':
+ if (nsub < 1) {
+ nsub = 1;
+ }
+ break;
+ case '2':
+ if (nsub < 2) {
+ nsub = 2;
+ }
+ break;
+ case '3':
+ if (nsub < 3) {
+ nsub = 3;
+ }
+ break;
+ case '4':
+ if (nsub < 4) {
+ nsub = 4;
+ }
+ break;
+ case '5':
+ if (nsub < 5) {
+ nsub = 5;
+ }
+ break;
+ case '6':
+ if (nsub < 6) {
+ nsub = 6;
+ }
+ break;
+ case '7':
+ if (nsub < 7) {
+ nsub = 7;
+ }
+ break;
+ case '8':
+ if (nsub < 8) {
+ nsub = 8;
+ }
+ break;
+ case '9':
+ if (nsub < 9) {
+ nsub = 9;
+ }
+ break;
+ }
+ }
+ if (!replace) {
+ *cp++ = c;
+ }
+ }
+ }
+ if (!flags) {
+ return (DNS_R_SYNTAX);
+ }
+ *cp = '\0';
+ n = isc_regex_validate(regex);
+ if (n < 0 || nsub > (unsigned int)n) {
+ return (DNS_R_SYNTAX);
+ }
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+fromtext_naptr(ARGS_FROMTEXT) {
+ isc_token_t token;
+ dns_name_t name;
+ isc_buffer_t buffer;
+ unsigned char *regex;
+
+ REQUIRE(type == dns_rdatatype_naptr);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(callbacks);
+
+ /*
+ * Order.
+ */
+ 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));
+
+ /*
+ * Preference.
+ */
+ 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));
+
+ /*
+ * Flags.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_qstring,
+ false));
+ RETTOK(txt_fromtext(&token.value.as_textregion, target));
+
+ /*
+ * Service.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_qstring,
+ false));
+ RETTOK(txt_fromtext(&token.value.as_textregion, target));
+
+ /*
+ * Regexp.
+ */
+ regex = isc_buffer_used(target);
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_qstring,
+ false));
+ RETTOK(txt_fromtext(&token.value.as_textregion, target));
+ RETTOK(txt_valid_regex(regex));
+
+ /*
+ * Replacement.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ false));
+ dns_name_init(&name, NULL);
+ buffer_fromregion(&buffer, &token.value.as_region);
+ if (origin == NULL) {
+ origin = dns_rootname;
+ }
+ RETTOK(dns_name_fromtext(&name, &buffer, origin, options, target));
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+totext_naptr(ARGS_TOTEXT) {
+ isc_region_t region;
+ dns_name_t name;
+ dns_name_t prefix;
+ bool sub;
+ char buf[sizeof("64000")];
+ unsigned short num;
+
+ REQUIRE(rdata->type == dns_rdatatype_naptr);
+ REQUIRE(rdata->length != 0);
+
+ dns_name_init(&name, NULL);
+ dns_name_init(&prefix, NULL);
+
+ dns_rdata_toregion(rdata, &region);
+
+ /*
+ * Order.
+ */
+ num = uint16_fromregion(&region);
+ isc_region_consume(&region, 2);
+ snprintf(buf, sizeof(buf), "%u", num);
+ RETERR(str_totext(buf, target));
+ RETERR(str_totext(" ", target));
+
+ /*
+ * Preference.
+ */
+ num = uint16_fromregion(&region);
+ isc_region_consume(&region, 2);
+ snprintf(buf, sizeof(buf), "%u", num);
+ RETERR(str_totext(buf, target));
+ RETERR(str_totext(" ", target));
+
+ /*
+ * Flags.
+ */
+ RETERR(txt_totext(&region, true, target));
+ RETERR(str_totext(" ", target));
+
+ /*
+ * Service.
+ */
+ RETERR(txt_totext(&region, true, target));
+ RETERR(str_totext(" ", target));
+
+ /*
+ * Regexp.
+ */
+ RETERR(txt_totext(&region, true, target));
+ RETERR(str_totext(" ", target));
+
+ /*
+ * Replacement.
+ */
+ dns_name_fromregion(&name, &region);
+ sub = name_prefix(&name, tctx->origin, &prefix);
+ return (dns_name_totext(&prefix, sub, target));
+}
+
+static isc_result_t
+fromwire_naptr(ARGS_FROMWIRE) {
+ dns_name_t name;
+ isc_region_t sr;
+ unsigned char *regex;
+
+ REQUIRE(type == dns_rdatatype_naptr);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ dns_decompress_setmethods(dctx, DNS_COMPRESS_NONE);
+
+ dns_name_init(&name, NULL);
+
+ /*
+ * Order, preference.
+ */
+ isc_buffer_activeregion(source, &sr);
+ if (sr.length < 4) {
+ return (ISC_R_UNEXPECTEDEND);
+ }
+ RETERR(mem_tobuffer(target, sr.base, 4));
+ isc_buffer_forward(source, 4);
+
+ /*
+ * Flags.
+ */
+ RETERR(txt_fromwire(source, target));
+
+ /*
+ * Service.
+ */
+ RETERR(txt_fromwire(source, target));
+
+ /*
+ * Regexp.
+ */
+ regex = isc_buffer_used(target);
+ RETERR(txt_fromwire(source, target));
+ RETERR(txt_valid_regex(regex));
+
+ /*
+ * Replacement.
+ */
+ return (dns_name_fromwire(&name, source, dctx, options, target));
+}
+
+static isc_result_t
+towire_naptr(ARGS_TOWIRE) {
+ dns_name_t name;
+ dns_offsets_t offsets;
+ isc_region_t sr;
+
+ REQUIRE(rdata->type == dns_rdatatype_naptr);
+ REQUIRE(rdata->length != 0);
+
+ dns_compress_setmethods(cctx, DNS_COMPRESS_NONE);
+ /*
+ * Order, preference.
+ */
+ dns_rdata_toregion(rdata, &sr);
+ RETERR(mem_tobuffer(target, sr.base, 4));
+ isc_region_consume(&sr, 4);
+
+ /*
+ * Flags.
+ */
+ RETERR(mem_tobuffer(target, sr.base, sr.base[0] + 1));
+ isc_region_consume(&sr, sr.base[0] + 1);
+
+ /*
+ * Service.
+ */
+ RETERR(mem_tobuffer(target, sr.base, sr.base[0] + 1));
+ isc_region_consume(&sr, sr.base[0] + 1);
+
+ /*
+ * Regexp.
+ */
+ RETERR(mem_tobuffer(target, sr.base, sr.base[0] + 1));
+ isc_region_consume(&sr, sr.base[0] + 1);
+
+ /*
+ * Replacement.
+ */
+ dns_name_init(&name, offsets);
+ dns_name_fromregion(&name, &sr);
+ return (dns_name_towire(&name, cctx, target));
+}
+
+static int
+compare_naptr(ARGS_COMPARE) {
+ dns_name_t name1;
+ dns_name_t name2;
+ isc_region_t region1;
+ isc_region_t region2;
+ int order, len;
+
+ REQUIRE(rdata1->type == rdata2->type);
+ REQUIRE(rdata1->rdclass == rdata2->rdclass);
+ REQUIRE(rdata1->type == dns_rdatatype_naptr);
+ REQUIRE(rdata1->length != 0);
+ REQUIRE(rdata2->length != 0);
+
+ dns_rdata_toregion(rdata1, &region1);
+ dns_rdata_toregion(rdata2, &region2);
+
+ /*
+ * Order, preference.
+ */
+ order = memcmp(region1.base, region2.base, 4);
+ if (order != 0) {
+ return (order < 0 ? -1 : 1);
+ }
+ isc_region_consume(&region1, 4);
+ isc_region_consume(&region2, 4);
+
+ /*
+ * Flags.
+ */
+ len = ISC_MIN(region1.base[0], region2.base[0]);
+ order = memcmp(region1.base, region2.base, len + 1);
+ if (order != 0) {
+ return (order < 0 ? -1 : 1);
+ }
+ isc_region_consume(&region1, region1.base[0] + 1);
+ isc_region_consume(&region2, region2.base[0] + 1);
+
+ /*
+ * Service.
+ */
+ len = ISC_MIN(region1.base[0], region2.base[0]);
+ order = memcmp(region1.base, region2.base, len + 1);
+ if (order != 0) {
+ return (order < 0 ? -1 : 1);
+ }
+ isc_region_consume(&region1, region1.base[0] + 1);
+ isc_region_consume(&region2, region2.base[0] + 1);
+
+ /*
+ * Regexp.
+ */
+ len = ISC_MIN(region1.base[0], region2.base[0]);
+ order = memcmp(region1.base, region2.base, len + 1);
+ if (order != 0) {
+ return (order < 0 ? -1 : 1);
+ }
+ isc_region_consume(&region1, region1.base[0] + 1);
+ isc_region_consume(&region2, region2.base[0] + 1);
+
+ /*
+ * Replacement.
+ */
+ dns_name_init(&name1, NULL);
+ dns_name_init(&name2, NULL);
+
+ dns_name_fromregion(&name1, &region1);
+ dns_name_fromregion(&name2, &region2);
+
+ return (dns_name_rdatacompare(&name1, &name2));
+}
+
+static isc_result_t
+fromstruct_naptr(ARGS_FROMSTRUCT) {
+ dns_rdata_naptr_t *naptr = source;
+ isc_region_t region;
+
+ REQUIRE(type == dns_rdatatype_naptr);
+ REQUIRE(naptr != NULL);
+ REQUIRE(naptr->common.rdtype == type);
+ REQUIRE(naptr->common.rdclass == rdclass);
+ REQUIRE(naptr->flags != NULL || naptr->flags_len == 0);
+ REQUIRE(naptr->service != NULL || naptr->service_len == 0);
+ REQUIRE(naptr->regexp != NULL || naptr->regexp_len == 0);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ RETERR(uint16_tobuffer(naptr->order, target));
+ RETERR(uint16_tobuffer(naptr->preference, target));
+ RETERR(uint8_tobuffer(naptr->flags_len, target));
+ RETERR(mem_tobuffer(target, naptr->flags, naptr->flags_len));
+ RETERR(uint8_tobuffer(naptr->service_len, target));
+ RETERR(mem_tobuffer(target, naptr->service, naptr->service_len));
+ RETERR(uint8_tobuffer(naptr->regexp_len, target));
+ RETERR(mem_tobuffer(target, naptr->regexp, naptr->regexp_len));
+ dns_name_toregion(&naptr->replacement, &region);
+ return (isc_buffer_copyregion(target, &region));
+}
+
+static isc_result_t
+tostruct_naptr(ARGS_TOSTRUCT) {
+ dns_rdata_naptr_t *naptr = target;
+ isc_region_t r;
+ dns_name_t name;
+
+ REQUIRE(rdata->type == dns_rdatatype_naptr);
+ REQUIRE(naptr != NULL);
+ REQUIRE(rdata->length != 0);
+
+ naptr->common.rdclass = rdata->rdclass;
+ naptr->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&naptr->common, link);
+
+ naptr->flags = NULL;
+ naptr->service = NULL;
+ naptr->regexp = NULL;
+
+ dns_rdata_toregion(rdata, &r);
+
+ naptr->order = uint16_fromregion(&r);
+ isc_region_consume(&r, 2);
+
+ naptr->preference = uint16_fromregion(&r);
+ isc_region_consume(&r, 2);
+
+ naptr->flags_len = uint8_fromregion(&r);
+ isc_region_consume(&r, 1);
+ INSIST(naptr->flags_len <= r.length);
+ naptr->flags = mem_maybedup(mctx, r.base, naptr->flags_len);
+ if (naptr->flags == NULL) {
+ goto cleanup;
+ }
+ isc_region_consume(&r, naptr->flags_len);
+
+ naptr->service_len = uint8_fromregion(&r);
+ isc_region_consume(&r, 1);
+ INSIST(naptr->service_len <= r.length);
+ naptr->service = mem_maybedup(mctx, r.base, naptr->service_len);
+ if (naptr->service == NULL) {
+ goto cleanup;
+ }
+ isc_region_consume(&r, naptr->service_len);
+
+ naptr->regexp_len = uint8_fromregion(&r);
+ isc_region_consume(&r, 1);
+ INSIST(naptr->regexp_len <= r.length);
+ naptr->regexp = mem_maybedup(mctx, r.base, naptr->regexp_len);
+ if (naptr->regexp == NULL) {
+ goto cleanup;
+ }
+ isc_region_consume(&r, naptr->regexp_len);
+
+ dns_name_init(&name, NULL);
+ dns_name_fromregion(&name, &r);
+ dns_name_init(&naptr->replacement, NULL);
+ name_duporclone(&name, mctx, &naptr->replacement);
+ naptr->mctx = mctx;
+ return (ISC_R_SUCCESS);
+
+cleanup:
+ if (mctx != NULL && naptr->flags != NULL) {
+ isc_mem_free(mctx, naptr->flags);
+ }
+ if (mctx != NULL && naptr->service != NULL) {
+ isc_mem_free(mctx, naptr->service);
+ }
+ if (mctx != NULL && naptr->regexp != NULL) {
+ isc_mem_free(mctx, naptr->regexp);
+ }
+ return (ISC_R_NOMEMORY);
+}
+
+static void
+freestruct_naptr(ARGS_FREESTRUCT) {
+ dns_rdata_naptr_t *naptr = source;
+
+ REQUIRE(naptr != NULL);
+ REQUIRE(naptr->common.rdtype == dns_rdatatype_naptr);
+
+ if (naptr->mctx == NULL) {
+ return;
+ }
+
+ if (naptr->flags != NULL) {
+ isc_mem_free(naptr->mctx, naptr->flags);
+ }
+ if (naptr->service != NULL) {
+ isc_mem_free(naptr->mctx, naptr->service);
+ }
+ if (naptr->regexp != NULL) {
+ isc_mem_free(naptr->mctx, naptr->regexp);
+ }
+ dns_name_free(&naptr->replacement, naptr->mctx);
+ naptr->mctx = NULL;
+}
+
+static isc_result_t
+additionaldata_naptr(ARGS_ADDLDATA) {
+ dns_name_t name;
+ dns_offsets_t offsets;
+ isc_region_t sr;
+ dns_rdatatype_t atype;
+ unsigned int i, flagslen;
+ char *cp;
+
+ REQUIRE(rdata->type == dns_rdatatype_naptr);
+
+ UNUSED(owner);
+
+ /*
+ * Order, preference.
+ */
+ dns_rdata_toregion(rdata, &sr);
+ isc_region_consume(&sr, 4);
+
+ /*
+ * Flags.
+ */
+ atype = 0;
+ flagslen = sr.base[0];
+ cp = (char *)&sr.base[1];
+ for (i = 0; i < flagslen; i++, cp++) {
+ if (*cp == 'S' || *cp == 's') {
+ atype = dns_rdatatype_srv;
+ break;
+ }
+ if (*cp == 'A' || *cp == 'a') {
+ atype = dns_rdatatype_a;
+ break;
+ }
+ }
+ isc_region_consume(&sr, flagslen + 1);
+
+ /*
+ * Service.
+ */
+ isc_region_consume(&sr, sr.base[0] + 1);
+
+ /*
+ * Regexp.
+ */
+ isc_region_consume(&sr, sr.base[0] + 1);
+
+ /*
+ * Replacement.
+ */
+ dns_name_init(&name, offsets);
+ dns_name_fromregion(&name, &sr);
+
+ if (atype != 0) {
+ return ((add)(arg, &name, atype, NULL));
+ }
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+digest_naptr(ARGS_DIGEST) {
+ isc_region_t r1, r2;
+ unsigned int length, n;
+ isc_result_t result;
+ dns_name_t name;
+
+ REQUIRE(rdata->type == dns_rdatatype_naptr);
+
+ dns_rdata_toregion(rdata, &r1);
+ r2 = r1;
+ length = 0;
+
+ /*
+ * Order, preference.
+ */
+ length += 4;
+ isc_region_consume(&r2, 4);
+
+ /*
+ * Flags.
+ */
+ n = r2.base[0] + 1;
+ length += n;
+ isc_region_consume(&r2, n);
+
+ /*
+ * Service.
+ */
+ n = r2.base[0] + 1;
+ length += n;
+ isc_region_consume(&r2, n);
+
+ /*
+ * Regexp.
+ */
+ n = r2.base[0] + 1;
+ length += n;
+ isc_region_consume(&r2, n);
+
+ /*
+ * Digest the RR up to the replacement name.
+ */
+ r1.length = length;
+ result = (digest)(arg, &r1);
+ if (result != ISC_R_SUCCESS) {
+ return (result);
+ }
+
+ /*
+ * Replacement.
+ */
+
+ dns_name_init(&name, NULL);
+ dns_name_fromregion(&name, &r2);
+
+ return (dns_name_digest(&name, digest, arg));
+}
+
+static bool
+checkowner_naptr(ARGS_CHECKOWNER) {
+ REQUIRE(type == dns_rdatatype_naptr);
+
+ UNUSED(name);
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (true);
+}
+
+static bool
+checknames_naptr(ARGS_CHECKNAMES) {
+ REQUIRE(rdata->type == dns_rdatatype_naptr);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(bad);
+
+ return (true);
+}
+
+static int
+casecompare_naptr(ARGS_COMPARE) {
+ return (compare_naptr(rdata1, rdata2));
+}
+
+#endif /* RDATA_GENERIC_NAPTR_35_C */
diff --git a/lib/dns/rdata/generic/naptr_35.h b/lib/dns/rdata/generic/naptr_35.h
new file mode 100644
index 0000000..f414ddd
--- /dev/null
+++ b/lib/dns/rdata/generic/naptr_35.h
@@ -0,0 +1,31 @@
+/*
+ * 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
+
+/*!
+ * \brief Per RFC2915 */
+
+typedef struct dns_rdata_naptr {
+ dns_rdatacommon_t common;
+ isc_mem_t *mctx;
+ uint16_t order;
+ uint16_t preference;
+ char *flags;
+ uint8_t flags_len;
+ char *service;
+ uint8_t service_len;
+ char *regexp;
+ uint8_t regexp_len;
+ dns_name_t replacement;
+} dns_rdata_naptr_t;
diff --git a/lib/dns/rdata/generic/nid_104.c b/lib/dns/rdata/generic/nid_104.c
new file mode 100644
index 0000000..8a95813
--- /dev/null
+++ b/lib/dns/rdata/generic/nid_104.c
@@ -0,0 +1,225 @@
+/*
+ * 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_NID_104_C
+#define RDATA_GENERIC_NID_104_C
+
+#include <string.h>
+
+#include <isc/net.h>
+
+#define RRTYPE_NID_ATTRIBUTES (0)
+
+static isc_result_t
+fromtext_nid(ARGS_FROMTEXT) {
+ isc_token_t token;
+ unsigned char locator[NS_LOCATORSZ];
+
+ REQUIRE(type == dns_rdatatype_nid);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(origin);
+ UNUSED(options);
+ UNUSED(callbacks);
+
+ 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));
+
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ false));
+
+ if (locator_pton(DNS_AS_STR(token), locator) != 1) {
+ RETTOK(DNS_R_SYNTAX);
+ }
+ return (mem_tobuffer(target, locator, NS_LOCATORSZ));
+}
+
+static isc_result_t
+totext_nid(ARGS_TOTEXT) {
+ isc_region_t region;
+ char buf[sizeof("xxxx:xxxx:xxxx:xxxx")];
+ unsigned short num;
+
+ REQUIRE(rdata->type == dns_rdatatype_nid);
+ REQUIRE(rdata->length != 0);
+
+ UNUSED(tctx);
+
+ dns_rdata_toregion(rdata, &region);
+ num = uint16_fromregion(&region);
+ isc_region_consume(&region, 2);
+ snprintf(buf, sizeof(buf), "%u", num);
+ RETERR(str_totext(buf, target));
+
+ RETERR(str_totext(" ", target));
+
+ snprintf(buf, sizeof(buf), "%x:%x:%x:%x",
+ region.base[0] << 8 | region.base[1],
+ region.base[2] << 8 | region.base[3],
+ region.base[4] << 8 | region.base[5],
+ region.base[6] << 8 | region.base[7]);
+ return (str_totext(buf, target));
+}
+
+static isc_result_t
+fromwire_nid(ARGS_FROMWIRE) {
+ isc_region_t sregion;
+
+ REQUIRE(type == dns_rdatatype_nid);
+
+ UNUSED(type);
+ UNUSED(options);
+ UNUSED(rdclass);
+ UNUSED(dctx);
+
+ isc_buffer_activeregion(source, &sregion);
+ if (sregion.length != 10) {
+ return (DNS_R_FORMERR);
+ }
+ isc_buffer_forward(source, sregion.length);
+ return (mem_tobuffer(target, sregion.base, sregion.length));
+}
+
+static isc_result_t
+towire_nid(ARGS_TOWIRE) {
+ REQUIRE(rdata->type == dns_rdatatype_nid);
+ REQUIRE(rdata->length == 10);
+
+ UNUSED(cctx);
+
+ return (mem_tobuffer(target, rdata->data, rdata->length));
+}
+
+static int
+compare_nid(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_nid);
+ REQUIRE(rdata1->length == 10);
+ REQUIRE(rdata2->length == 10);
+
+ dns_rdata_toregion(rdata1, &region1);
+ dns_rdata_toregion(rdata2, &region2);
+ return (isc_region_compare(&region1, &region2));
+}
+
+static isc_result_t
+fromstruct_nid(ARGS_FROMSTRUCT) {
+ dns_rdata_nid_t *nid = source;
+
+ REQUIRE(type == dns_rdatatype_nid);
+ REQUIRE(nid != NULL);
+ REQUIRE(nid->common.rdtype == type);
+ REQUIRE(nid->common.rdclass == rdclass);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ RETERR(uint16_tobuffer(nid->pref, target));
+ return (mem_tobuffer(target, nid->nid, sizeof(nid->nid)));
+}
+
+static isc_result_t
+tostruct_nid(ARGS_TOSTRUCT) {
+ isc_region_t region;
+ dns_rdata_nid_t *nid = target;
+
+ REQUIRE(rdata->type == dns_rdatatype_nid);
+ REQUIRE(nid != NULL);
+ REQUIRE(rdata->length == 10);
+
+ UNUSED(mctx);
+
+ nid->common.rdclass = rdata->rdclass;
+ nid->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&nid->common, link);
+
+ dns_rdata_toregion(rdata, &region);
+ nid->pref = uint16_fromregion(&region);
+ memmove(nid->nid, region.base, region.length);
+ return (ISC_R_SUCCESS);
+}
+
+static void
+freestruct_nid(ARGS_FREESTRUCT) {
+ dns_rdata_nid_t *nid = source;
+
+ REQUIRE(nid != NULL);
+ REQUIRE(nid->common.rdtype == dns_rdatatype_nid);
+
+ return;
+}
+
+static isc_result_t
+additionaldata_nid(ARGS_ADDLDATA) {
+ REQUIRE(rdata->type == dns_rdatatype_nid);
+ REQUIRE(rdata->length == 10);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(add);
+ UNUSED(arg);
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+digest_nid(ARGS_DIGEST) {
+ isc_region_t r;
+
+ REQUIRE(rdata->type == dns_rdatatype_nid);
+ REQUIRE(rdata->length == 10);
+
+ dns_rdata_toregion(rdata, &r);
+
+ return ((digest)(arg, &r));
+}
+
+static bool
+checkowner_nid(ARGS_CHECKOWNER) {
+ REQUIRE(type == dns_rdatatype_nid);
+
+ UNUSED(name);
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (true);
+}
+
+static bool
+checknames_nid(ARGS_CHECKNAMES) {
+ REQUIRE(rdata->type == dns_rdatatype_nid);
+ REQUIRE(rdata->length == 10);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(bad);
+
+ return (true);
+}
+
+static int
+casecompare_nid(ARGS_COMPARE) {
+ return (compare_nid(rdata1, rdata2));
+}
+
+#endif /* RDATA_GENERIC_NID_104_C */
diff --git a/lib/dns/rdata/generic/nid_104.h b/lib/dns/rdata/generic/nid_104.h
new file mode 100644
index 0000000..194cefa
--- /dev/null
+++ b/lib/dns/rdata/generic/nid_104.h
@@ -0,0 +1,21 @@
+/*
+ * 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_nid {
+ dns_rdatacommon_t common;
+ uint16_t pref;
+ unsigned char nid[8];
+} dns_rdata_nid_t;
diff --git a/lib/dns/rdata/generic/ninfo_56.c b/lib/dns/rdata/generic/ninfo_56.c
new file mode 100644
index 0000000..8e0fae1
--- /dev/null
+++ b/lib/dns/rdata/generic/ninfo_56.c
@@ -0,0 +1,170 @@
+/*
+ * 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_NINFO_56_C
+#define RDATA_GENERIC_NINFO_56_C
+
+#define RRTYPE_NINFO_ATTRIBUTES (0)
+
+static isc_result_t
+fromtext_ninfo(ARGS_FROMTEXT) {
+ REQUIRE(type == dns_rdatatype_ninfo);
+
+ return (generic_fromtext_txt(CALL_FROMTEXT));
+}
+
+static isc_result_t
+totext_ninfo(ARGS_TOTEXT) {
+ REQUIRE(rdata != NULL);
+ REQUIRE(rdata->type == dns_rdatatype_ninfo);
+
+ return (generic_totext_txt(CALL_TOTEXT));
+}
+
+static isc_result_t
+fromwire_ninfo(ARGS_FROMWIRE) {
+ REQUIRE(type == dns_rdatatype_ninfo);
+
+ return (generic_fromwire_txt(CALL_FROMWIRE));
+}
+
+static isc_result_t
+towire_ninfo(ARGS_TOWIRE) {
+ REQUIRE(rdata->type == dns_rdatatype_ninfo);
+
+ UNUSED(cctx);
+
+ return (mem_tobuffer(target, rdata->data, rdata->length));
+}
+
+static int
+compare_ninfo(ARGS_COMPARE) {
+ isc_region_t r1;
+ isc_region_t r2;
+
+ REQUIRE(rdata1->type == rdata2->type);
+ REQUIRE(rdata1->rdclass == rdata2->rdclass);
+ REQUIRE(rdata1->type == dns_rdatatype_ninfo);
+
+ dns_rdata_toregion(rdata1, &r1);
+ dns_rdata_toregion(rdata2, &r2);
+ return (isc_region_compare(&r1, &r2));
+}
+
+static isc_result_t
+fromstruct_ninfo(ARGS_FROMSTRUCT) {
+ REQUIRE(type == dns_rdatatype_ninfo);
+
+ return (generic_fromstruct_txt(CALL_FROMSTRUCT));
+}
+
+static isc_result_t
+tostruct_ninfo(ARGS_TOSTRUCT) {
+ dns_rdata_ninfo_t *ninfo = target;
+
+ REQUIRE(rdata->type == dns_rdatatype_ninfo);
+ REQUIRE(ninfo != NULL);
+
+ ninfo->common.rdclass = rdata->rdclass;
+ ninfo->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&ninfo->common, link);
+
+ return (generic_tostruct_txt(CALL_TOSTRUCT));
+}
+
+static void
+freestruct_ninfo(ARGS_FREESTRUCT) {
+ dns_rdata_ninfo_t *ninfo = source;
+
+ REQUIRE(ninfo != NULL);
+ REQUIRE(ninfo->common.rdtype == dns_rdatatype_ninfo);
+
+ generic_freestruct_txt(source);
+}
+
+static isc_result_t
+additionaldata_ninfo(ARGS_ADDLDATA) {
+ REQUIRE(rdata->type == dns_rdatatype_ninfo);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(add);
+ UNUSED(arg);
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+digest_ninfo(ARGS_DIGEST) {
+ isc_region_t r;
+
+ REQUIRE(rdata->type == dns_rdatatype_ninfo);
+
+ dns_rdata_toregion(rdata, &r);
+
+ return ((digest)(arg, &r));
+}
+
+static bool
+checkowner_ninfo(ARGS_CHECKOWNER) {
+ REQUIRE(type == dns_rdatatype_ninfo);
+
+ UNUSED(name);
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (true);
+}
+
+static bool
+checknames_ninfo(ARGS_CHECKNAMES) {
+ REQUIRE(rdata->type == dns_rdatatype_ninfo);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(bad);
+
+ return (true);
+}
+
+static int
+casecompare_ninfo(ARGS_COMPARE) {
+ return (compare_ninfo(rdata1, rdata2));
+}
+
+isc_result_t
+dns_rdata_ninfo_first(dns_rdata_ninfo_t *ninfo) {
+ REQUIRE(ninfo != NULL);
+ REQUIRE(ninfo->common.rdtype == dns_rdatatype_ninfo);
+
+ return (generic_txt_first(ninfo));
+}
+
+isc_result_t
+dns_rdata_ninfo_next(dns_rdata_ninfo_t *ninfo) {
+ REQUIRE(ninfo != NULL);
+ REQUIRE(ninfo->common.rdtype == dns_rdatatype_ninfo);
+
+ return (generic_txt_next(ninfo));
+}
+
+isc_result_t
+dns_rdata_ninfo_current(dns_rdata_ninfo_t *ninfo,
+ dns_rdata_ninfo_string_t *string) {
+ REQUIRE(ninfo != NULL);
+ REQUIRE(ninfo->common.rdtype == dns_rdatatype_ninfo);
+
+ return (generic_txt_current(ninfo, string));
+}
+#endif /* RDATA_GENERIC_NINFO_56_C */
diff --git a/lib/dns/rdata/generic/ninfo_56.h b/lib/dns/rdata/generic/ninfo_56.h
new file mode 100644
index 0000000..66cf948
--- /dev/null
+++ b/lib/dns/rdata/generic/ninfo_56.h
@@ -0,0 +1,33 @@
+/*
+ * 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_txt_string dns_rdata_ninfo_string_t;
+
+typedef struct dns_rdata_txt dns_rdata_ninfo_t;
+
+/*
+ * ISC_LANG_BEGINDECLS and ISC_LANG_ENDDECLS are already done
+ * via rdatastructpre.h and rdatastructsuf.h.
+ */
+
+isc_result_t
+dns_rdata_ninfo_first(dns_rdata_ninfo_t *);
+
+isc_result_t
+dns_rdata_ninfo_next(dns_rdata_ninfo_t *);
+
+isc_result_t
+dns_rdata_ninfo_current(dns_rdata_ninfo_t *, dns_rdata_ninfo_string_t *);
diff --git a/lib/dns/rdata/generic/ns_2.c b/lib/dns/rdata/generic/ns_2.c
new file mode 100644
index 0000000..9fa8dba
--- /dev/null
+++ b/lib/dns/rdata/generic/ns_2.c
@@ -0,0 +1,256 @@
+/*
+ * 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_NS_2_C
+#define RDATA_GENERIC_NS_2_C
+
+#define RRTYPE_NS_ATTRIBUTES (DNS_RDATATYPEATTR_ZONECUTAUTH)
+
+static isc_result_t
+fromtext_ns(ARGS_FROMTEXT) {
+ isc_token_t token;
+ dns_name_t name;
+ isc_buffer_t buffer;
+ bool ok;
+
+ REQUIRE(type == dns_rdatatype_ns);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(callbacks);
+
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ false));
+
+ dns_name_init(&name, NULL);
+ buffer_fromregion(&buffer, &token.value.as_region);
+ if (origin == NULL) {
+ origin = dns_rootname;
+ }
+ RETTOK(dns_name_fromtext(&name, &buffer, origin, options, target));
+ ok = true;
+ 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_ns(ARGS_TOTEXT) {
+ isc_region_t region;
+ dns_name_t name;
+ dns_name_t prefix;
+ bool sub;
+
+ REQUIRE(rdata->type == dns_rdatatype_ns);
+ REQUIRE(rdata->length != 0);
+
+ dns_name_init(&name, NULL);
+ dns_name_init(&prefix, NULL);
+
+ dns_rdata_toregion(rdata, &region);
+ dns_name_fromregion(&name, &region);
+
+ sub = name_prefix(&name, tctx->origin, &prefix);
+
+ return (dns_name_totext(&prefix, sub, target));
+}
+
+static isc_result_t
+fromwire_ns(ARGS_FROMWIRE) {
+ dns_name_t name;
+
+ REQUIRE(type == dns_rdatatype_ns);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ dns_decompress_setmethods(dctx, DNS_COMPRESS_GLOBAL14);
+
+ dns_name_init(&name, NULL);
+ return (dns_name_fromwire(&name, source, dctx, options, target));
+}
+
+static isc_result_t
+towire_ns(ARGS_TOWIRE) {
+ dns_name_t name;
+ dns_offsets_t offsets;
+ isc_region_t region;
+
+ REQUIRE(rdata->type == dns_rdatatype_ns);
+ REQUIRE(rdata->length != 0);
+
+ dns_compress_setmethods(cctx, DNS_COMPRESS_GLOBAL14);
+
+ dns_name_init(&name, offsets);
+ dns_rdata_toregion(rdata, &region);
+ dns_name_fromregion(&name, &region);
+
+ return (dns_name_towire(&name, cctx, target));
+}
+
+static int
+compare_ns(ARGS_COMPARE) {
+ dns_name_t name1;
+ dns_name_t name2;
+ isc_region_t region1;
+ isc_region_t region2;
+
+ REQUIRE(rdata1->type == rdata2->type);
+ REQUIRE(rdata1->rdclass == rdata2->rdclass);
+ REQUIRE(rdata1->type == dns_rdatatype_ns);
+ REQUIRE(rdata1->length != 0);
+ REQUIRE(rdata2->length != 0);
+
+ dns_name_init(&name1, NULL);
+ dns_name_init(&name2, NULL);
+
+ dns_rdata_toregion(rdata1, &region1);
+ dns_rdata_toregion(rdata2, &region2);
+
+ dns_name_fromregion(&name1, &region1);
+ dns_name_fromregion(&name2, &region2);
+
+ return (dns_name_rdatacompare(&name1, &name2));
+}
+
+static isc_result_t
+fromstruct_ns(ARGS_FROMSTRUCT) {
+ dns_rdata_ns_t *ns = source;
+ isc_region_t region;
+
+ REQUIRE(type == dns_rdatatype_ns);
+ REQUIRE(ns != NULL);
+ REQUIRE(ns->common.rdtype == type);
+ REQUIRE(ns->common.rdclass == rdclass);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ dns_name_toregion(&ns->name, &region);
+ return (isc_buffer_copyregion(target, &region));
+}
+
+static isc_result_t
+tostruct_ns(ARGS_TOSTRUCT) {
+ isc_region_t region;
+ dns_rdata_ns_t *ns = target;
+ dns_name_t name;
+
+ REQUIRE(rdata->type == dns_rdatatype_ns);
+ REQUIRE(ns != NULL);
+ REQUIRE(rdata->length != 0);
+
+ ns->common.rdclass = rdata->rdclass;
+ ns->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&ns->common, link);
+
+ dns_name_init(&name, NULL);
+ dns_rdata_toregion(rdata, &region);
+ dns_name_fromregion(&name, &region);
+ dns_name_init(&ns->name, NULL);
+ name_duporclone(&name, mctx, &ns->name);
+ ns->mctx = mctx;
+ return (ISC_R_SUCCESS);
+}
+
+static void
+freestruct_ns(ARGS_FREESTRUCT) {
+ dns_rdata_ns_t *ns = source;
+
+ REQUIRE(ns != NULL);
+
+ if (ns->mctx == NULL) {
+ return;
+ }
+
+ dns_name_free(&ns->name, ns->mctx);
+ ns->mctx = NULL;
+}
+
+static isc_result_t
+additionaldata_ns(ARGS_ADDLDATA) {
+ dns_name_t name;
+ dns_offsets_t offsets;
+ isc_region_t region;
+
+ REQUIRE(rdata->type == dns_rdatatype_ns);
+
+ UNUSED(owner);
+
+ dns_name_init(&name, offsets);
+ dns_rdata_toregion(rdata, &region);
+ dns_name_fromregion(&name, &region);
+
+ return ((add)(arg, &name, dns_rdatatype_a, NULL));
+}
+
+static isc_result_t
+digest_ns(ARGS_DIGEST) {
+ isc_region_t r;
+ dns_name_t name;
+
+ REQUIRE(rdata->type == dns_rdatatype_ns);
+
+ dns_rdata_toregion(rdata, &r);
+ dns_name_init(&name, NULL);
+ dns_name_fromregion(&name, &r);
+
+ return (dns_name_digest(&name, digest, arg));
+}
+
+static bool
+checkowner_ns(ARGS_CHECKOWNER) {
+ REQUIRE(type == dns_rdatatype_ns);
+
+ UNUSED(name);
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (true);
+}
+
+static bool
+checknames_ns(ARGS_CHECKNAMES) {
+ isc_region_t region;
+ dns_name_t name;
+
+ REQUIRE(rdata->type == dns_rdatatype_ns);
+
+ UNUSED(owner);
+
+ dns_rdata_toregion(rdata, &region);
+ dns_name_init(&name, NULL);
+ dns_name_fromregion(&name, &region);
+ if (!dns_name_ishostname(&name, false)) {
+ if (bad != NULL) {
+ dns_name_clone(&name, bad);
+ }
+ return (false);
+ }
+ return (true);
+}
+
+static int
+casecompare_ns(ARGS_COMPARE) {
+ return (compare_ns(rdata1, rdata2));
+}
+
+#endif /* RDATA_GENERIC_NS_2_C */
diff --git a/lib/dns/rdata/generic/ns_2.h b/lib/dns/rdata/generic/ns_2.h
new file mode 100644
index 0000000..a9abd5d
--- /dev/null
+++ b/lib/dns/rdata/generic/ns_2.h
@@ -0,0 +1,21 @@
+/*
+ * 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_ns {
+ dns_rdatacommon_t common;
+ isc_mem_t *mctx;
+ dns_name_t name;
+} dns_rdata_ns_t;
diff --git a/lib/dns/rdata/generic/nsec3_50.c b/lib/dns/rdata/generic/nsec3_50.c
new file mode 100644
index 0000000..556616b
--- /dev/null
+++ b/lib/dns/rdata/generic/nsec3_50.c
@@ -0,0 +1,425 @@
+/*
+ * 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.
+ */
+
+/*
+ * Copyright (C) 2004 Nominet, Ltd.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND NOMINET DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* RFC 5155 */
+
+#ifndef RDATA_GENERIC_NSEC3_50_C
+#define RDATA_GENERIC_NSEC3_50_C
+
+#include <isc/base32.h>
+#include <isc/iterated_hash.h>
+
+#define RRTYPE_NSEC3_ATTRIBUTES DNS_RDATATYPEATTR_DNSSEC
+
+static isc_result_t
+fromtext_nsec3(ARGS_FROMTEXT) {
+ isc_token_t token;
+ unsigned int flags;
+ unsigned char hashalg;
+ isc_buffer_t b;
+ unsigned char buf[256];
+
+ REQUIRE(type == dns_rdatatype_nsec3);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(callbacks);
+ UNUSED(origin);
+ UNUSED(options);
+
+ /* Hash. */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ false));
+ RETTOK(dns_hashalg_fromtext(&hashalg, &token.value.as_textregion));
+ RETERR(uint8_tobuffer(hashalg, target));
+
+ /* Flags. */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
+ false));
+ flags = token.value.as_ulong;
+ if (flags > 255U) {
+ RETTOK(ISC_R_RANGE);
+ }
+ RETERR(uint8_tobuffer(flags, target));
+
+ /* Iterations. */
+ 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));
+
+ /* salt */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ false));
+ if (token.value.as_textregion.length > (255 * 2)) {
+ RETTOK(DNS_R_TEXTTOOLONG);
+ }
+ if (strcmp(DNS_AS_STR(token), "-") == 0) {
+ RETERR(uint8_tobuffer(0, target));
+ } else {
+ RETERR(uint8_tobuffer(strlen(DNS_AS_STR(token)) / 2, target));
+ RETERR(isc_hex_decodestring(DNS_AS_STR(token), target));
+ }
+
+ /*
+ * Next hash a single base32hex word.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ false));
+ isc_buffer_init(&b, buf, sizeof(buf));
+ RETTOK(isc_base32hexnp_decodestring(DNS_AS_STR(token), &b));
+ if (isc_buffer_usedlength(&b) > 0xffU) {
+ RETTOK(ISC_R_RANGE);
+ }
+ RETERR(uint8_tobuffer(isc_buffer_usedlength(&b), target));
+ RETERR(mem_tobuffer(target, &buf, isc_buffer_usedlength(&b)));
+
+ return (typemap_fromtext(lexer, target, true));
+}
+
+static isc_result_t
+totext_nsec3(ARGS_TOTEXT) {
+ isc_region_t sr;
+ unsigned int i, j;
+ unsigned char hash;
+ unsigned char flags;
+ char buf[sizeof("TYPE65535")];
+ uint32_t iterations;
+
+ REQUIRE(rdata->type == dns_rdatatype_nsec3);
+ REQUIRE(rdata->length != 0);
+
+ dns_rdata_toregion(rdata, &sr);
+
+ /* Hash */
+ hash = uint8_fromregion(&sr);
+ isc_region_consume(&sr, 1);
+ snprintf(buf, sizeof(buf), "%u ", hash);
+ RETERR(str_totext(buf, target));
+
+ /* Flags */
+ flags = uint8_fromregion(&sr);
+ isc_region_consume(&sr, 1);
+ snprintf(buf, sizeof(buf), "%u ", flags);
+ RETERR(str_totext(buf, target));
+
+ /* Iterations */
+ iterations = uint16_fromregion(&sr);
+ isc_region_consume(&sr, 2);
+ snprintf(buf, sizeof(buf), "%u ", iterations);
+ RETERR(str_totext(buf, target));
+
+ /* Salt */
+ j = uint8_fromregion(&sr);
+ isc_region_consume(&sr, 1);
+ INSIST(j <= sr.length);
+
+ if (j != 0) {
+ i = sr.length;
+ sr.length = j;
+ RETERR(isc_hex_totext(&sr, 1, "", target));
+ sr.length = i - j;
+ } else {
+ RETERR(str_totext("-", target));
+ }
+
+ if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) {
+ RETERR(str_totext(" (", target));
+ }
+ RETERR(str_totext(tctx->linebreak, target));
+
+ /* Next hash */
+ j = uint8_fromregion(&sr);
+ isc_region_consume(&sr, 1);
+ INSIST(j <= sr.length);
+
+ i = sr.length;
+ sr.length = j;
+ RETERR(isc_base32hexnp_totext(&sr, 1, "", target));
+ sr.length = i - j;
+
+ /*
+ * Don't leave a trailing space when there's no typemap present.
+ */
+ if (((tctx->flags & DNS_STYLEFLAG_MULTILINE) == 0) && (sr.length > 0)) {
+ RETERR(str_totext(" ", target));
+ }
+ RETERR(typemap_totext(&sr, tctx, target));
+
+ if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) {
+ RETERR(str_totext(" )", target));
+ }
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+fromwire_nsec3(ARGS_FROMWIRE) {
+ isc_region_t sr, rr;
+ unsigned int saltlen, hashlen;
+
+ REQUIRE(type == dns_rdatatype_nsec3);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(options);
+ UNUSED(dctx);
+
+ isc_buffer_activeregion(source, &sr);
+ rr = sr;
+
+ /* hash(1), flags(1), iteration(2), saltlen(1) */
+ if (sr.length < 5U) {
+ RETERR(DNS_R_FORMERR);
+ }
+ saltlen = sr.base[4];
+ isc_region_consume(&sr, 5);
+
+ if (sr.length < saltlen) {
+ RETERR(DNS_R_FORMERR);
+ }
+ isc_region_consume(&sr, saltlen);
+
+ if (sr.length < 1U) {
+ RETERR(DNS_R_FORMERR);
+ }
+ hashlen = sr.base[0];
+ isc_region_consume(&sr, 1);
+
+ if (hashlen < 1 || sr.length < hashlen) {
+ RETERR(DNS_R_FORMERR);
+ }
+ isc_region_consume(&sr, hashlen);
+
+ RETERR(typemap_test(&sr, true));
+
+ RETERR(mem_tobuffer(target, rr.base, rr.length));
+ isc_buffer_forward(source, rr.length);
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+towire_nsec3(ARGS_TOWIRE) {
+ isc_region_t sr;
+
+ REQUIRE(rdata->type == dns_rdatatype_nsec3);
+ REQUIRE(rdata->length != 0);
+
+ UNUSED(cctx);
+
+ dns_rdata_toregion(rdata, &sr);
+ return (mem_tobuffer(target, sr.base, sr.length));
+}
+
+static int
+compare_nsec3(ARGS_COMPARE) {
+ isc_region_t r1;
+ isc_region_t r2;
+
+ REQUIRE(rdata1->type == rdata2->type);
+ REQUIRE(rdata1->rdclass == rdata2->rdclass);
+ REQUIRE(rdata1->type == dns_rdatatype_nsec3);
+ REQUIRE(rdata1->length != 0);
+ REQUIRE(rdata2->length != 0);
+
+ dns_rdata_toregion(rdata1, &r1);
+ dns_rdata_toregion(rdata2, &r2);
+ return (isc_region_compare(&r1, &r2));
+}
+
+static isc_result_t
+fromstruct_nsec3(ARGS_FROMSTRUCT) {
+ dns_rdata_nsec3_t *nsec3 = source;
+ isc_region_t region;
+
+ REQUIRE(type == dns_rdatatype_nsec3);
+ REQUIRE(nsec3 != NULL);
+ REQUIRE(nsec3->common.rdtype == type);
+ REQUIRE(nsec3->common.rdclass == rdclass);
+ REQUIRE(nsec3->typebits != NULL || nsec3->len == 0);
+ REQUIRE(nsec3->hash == dns_hash_sha1);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ RETERR(uint8_tobuffer(nsec3->hash, target));
+ RETERR(uint8_tobuffer(nsec3->flags, target));
+ RETERR(uint16_tobuffer(nsec3->iterations, target));
+ RETERR(uint8_tobuffer(nsec3->salt_length, target));
+ RETERR(mem_tobuffer(target, nsec3->salt, nsec3->salt_length));
+ RETERR(uint8_tobuffer(nsec3->next_length, target));
+ RETERR(mem_tobuffer(target, nsec3->next, nsec3->next_length));
+
+ region.base = nsec3->typebits;
+ region.length = nsec3->len;
+ RETERR(typemap_test(&region, true));
+ return (mem_tobuffer(target, nsec3->typebits, nsec3->len));
+}
+
+static isc_result_t
+tostruct_nsec3(ARGS_TOSTRUCT) {
+ isc_region_t region;
+ dns_rdata_nsec3_t *nsec3 = target;
+
+ REQUIRE(rdata->type == dns_rdatatype_nsec3);
+ REQUIRE(nsec3 != NULL);
+ REQUIRE(rdata->length != 0);
+
+ nsec3->common.rdclass = rdata->rdclass;
+ nsec3->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&nsec3->common, link);
+
+ region.base = rdata->data;
+ region.length = rdata->length;
+ nsec3->hash = uint8_consume_fromregion(&region);
+ nsec3->flags = uint8_consume_fromregion(&region);
+ nsec3->iterations = uint16_consume_fromregion(&region);
+
+ nsec3->salt_length = uint8_consume_fromregion(&region);
+ INSIST(nsec3->salt_length <= region.length);
+ nsec3->salt = mem_maybedup(mctx, region.base, nsec3->salt_length);
+ if (nsec3->salt == NULL) {
+ return (ISC_R_NOMEMORY);
+ }
+ isc_region_consume(&region, nsec3->salt_length);
+
+ nsec3->next_length = uint8_consume_fromregion(&region);
+ INSIST(nsec3->next_length <= region.length);
+ nsec3->next = mem_maybedup(mctx, region.base, nsec3->next_length);
+ if (nsec3->next == NULL) {
+ goto cleanup;
+ }
+ isc_region_consume(&region, nsec3->next_length);
+
+ nsec3->len = region.length;
+ nsec3->typebits = mem_maybedup(mctx, region.base, region.length);
+ if (nsec3->typebits == NULL) {
+ goto cleanup;
+ }
+
+ nsec3->mctx = mctx;
+ return (ISC_R_SUCCESS);
+
+cleanup:
+ if (nsec3->next != NULL) {
+ isc_mem_free(mctx, nsec3->next);
+ }
+ isc_mem_free(mctx, nsec3->salt);
+ return (ISC_R_NOMEMORY);
+}
+
+static void
+freestruct_nsec3(ARGS_FREESTRUCT) {
+ dns_rdata_nsec3_t *nsec3 = source;
+
+ REQUIRE(nsec3 != NULL);
+ REQUIRE(nsec3->common.rdtype == dns_rdatatype_nsec3);
+
+ if (nsec3->mctx == NULL) {
+ return;
+ }
+
+ if (nsec3->salt != NULL) {
+ isc_mem_free(nsec3->mctx, nsec3->salt);
+ }
+ if (nsec3->next != NULL) {
+ isc_mem_free(nsec3->mctx, nsec3->next);
+ }
+ if (nsec3->typebits != NULL) {
+ isc_mem_free(nsec3->mctx, nsec3->typebits);
+ }
+ nsec3->mctx = NULL;
+}
+
+static isc_result_t
+additionaldata_nsec3(ARGS_ADDLDATA) {
+ REQUIRE(rdata->type == dns_rdatatype_nsec3);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(add);
+ UNUSED(arg);
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+digest_nsec3(ARGS_DIGEST) {
+ isc_region_t r;
+
+ REQUIRE(rdata->type == dns_rdatatype_nsec3);
+
+ dns_rdata_toregion(rdata, &r);
+ return ((digest)(arg, &r));
+}
+
+static bool
+checkowner_nsec3(ARGS_CHECKOWNER) {
+ unsigned char owner[NSEC3_MAX_HASH_LENGTH];
+ isc_buffer_t buffer;
+ dns_label_t label;
+
+ REQUIRE(type == dns_rdatatype_nsec3);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ /*
+ * First label is a base32hex string without padding.
+ */
+ dns_name_getlabel(name, 0, &label);
+ isc_region_consume(&label, 1);
+ isc_buffer_init(&buffer, owner, sizeof(owner));
+ if (isc_base32hexnp_decoderegion(&label, &buffer) == ISC_R_SUCCESS) {
+ return (true);
+ }
+
+ return (false);
+}
+
+static bool
+checknames_nsec3(ARGS_CHECKNAMES) {
+ REQUIRE(rdata->type == dns_rdatatype_nsec3);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(bad);
+
+ return (true);
+}
+
+static int
+casecompare_nsec3(ARGS_COMPARE) {
+ return (compare_nsec3(rdata1, rdata2));
+}
+
+#endif /* RDATA_GENERIC_NSEC3_50_C */
diff --git a/lib/dns/rdata/generic/nsec3_50.h b/lib/dns/rdata/generic/nsec3_50.h
new file mode 100644
index 0000000..3152c85
--- /dev/null
+++ b/lib/dns/rdata/generic/nsec3_50.h
@@ -0,0 +1,109 @@
+/*
+ * 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
+
+/*!
+ * \brief Per RFC 5155 */
+
+#include <isc/iterated_hash.h>
+
+typedef struct dns_rdata_nsec3 {
+ dns_rdatacommon_t common;
+ isc_mem_t *mctx;
+ dns_hash_t hash;
+ unsigned char flags;
+ dns_iterations_t iterations;
+ unsigned char salt_length;
+ unsigned char next_length;
+ uint16_t len;
+ unsigned char *salt;
+ unsigned char *next;
+ unsigned char *typebits;
+} dns_rdata_nsec3_t;
+
+/*
+ * The corresponding NSEC3 interval is OPTOUT indicating possible
+ * insecure delegations.
+ */
+#define DNS_NSEC3FLAG_OPTOUT 0x01U
+
+/*%
+ * The following flags are used in the private-type record (implemented in
+ * lib/dns/private.c) which is used to store NSEC3PARAM data during the
+ * time when it is not legal to have an actual NSEC3PARAM record in the
+ * zone. They are defined here because the private-type record uses the
+ * same flags field for the OPTOUT flag above and for the private flags
+ * below. XXX: This should be considered for refactoring.
+ */
+
+/*%
+ * Non-standard, private type only.
+ *
+ * Create a corresponding NSEC3 chain.
+ * Once the NSEC3 chain is complete this flag will be removed to signal
+ * that there is a complete chain.
+ *
+ * This flag is automatically set when a NSEC3PARAM record is added to
+ * the zone via UPDATE.
+ *
+ * NSEC3PARAM records containing this flag should never be published,
+ * but if they are, they should be ignored by RFC 5155 compliant
+ * nameservers.
+ */
+#define DNS_NSEC3FLAG_CREATE 0x80U
+
+/*%
+ * Non-standard, private type only.
+ *
+ * The corresponding NSEC3 set is to be removed once the NSEC chain
+ * has been generated.
+ *
+ * This flag is automatically set when the last active NSEC3PARAM record
+ * is removed from the zone via UPDATE.
+ *
+ * NSEC3PARAM records containing this flag should never be published,
+ * but if they are, they should be ignored by RFC 5155 compliant
+ * nameservers.
+ */
+#define DNS_NSEC3FLAG_REMOVE 0x40U
+
+/*%
+ * Non-standard, private type only.
+ *
+ * When set with the CREATE flag, a corresponding NSEC3 chain will be
+ * created when the zone becomes capable of supporting one (i.e., when it
+ * has a DNSKEY RRset containing at least one NSEC3-capable algorithm).
+ * Without this flag, NSEC3 chain creation would be attempted immediately,
+ * fail, and the private type record would be removed. With it, the NSEC3
+ * parameters are stored until they can be used. When the zone has the
+ * necessary prerequisites for NSEC3, then the INITIAL flag can be cleared,
+ * and the record will be cleaned up normally.
+ *
+ * NSEC3PARAM records containing this flag should never be published, but
+ * if they are, they should be ignored by RFC 5155 compliant nameservers.
+ */
+#define DNS_NSEC3FLAG_INITIAL 0x20U
+
+/*%
+ * Non-standard, private type only.
+ *
+ * Prevent the creation of a NSEC chain before the last NSEC3 chain
+ * is removed. This will normally only be set when the zone is
+ * transitioning from secure with NSEC3 chains to insecure.
+ *
+ * NSEC3PARAM records containing this flag should never be published,
+ * but if they are, they should be ignored by RFC 5155 compliant
+ * nameservers.
+ */
+#define DNS_NSEC3FLAG_NONSEC 0x10U
diff --git a/lib/dns/rdata/generic/nsec3param_51.c b/lib/dns/rdata/generic/nsec3param_51.c
new file mode 100644
index 0000000..1690598
--- /dev/null
+++ b/lib/dns/rdata/generic/nsec3param_51.c
@@ -0,0 +1,322 @@
+/*
+ * 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.
+ */
+
+/*
+ * Copyright (C) 2004 Nominet, Ltd.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND NOMINET DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* RFC 5155 */
+
+#ifndef RDATA_GENERIC_NSEC3PARAM_51_C
+#define RDATA_GENERIC_NSEC3PARAM_51_C
+
+#include <isc/base32.h>
+#include <isc/iterated_hash.h>
+
+#define RRTYPE_NSEC3PARAM_ATTRIBUTES (DNS_RDATATYPEATTR_DNSSEC)
+
+static isc_result_t
+fromtext_nsec3param(ARGS_FROMTEXT) {
+ isc_token_t token;
+ unsigned int flags = 0;
+ unsigned char hashalg;
+
+ REQUIRE(type == dns_rdatatype_nsec3param);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(callbacks);
+ UNUSED(origin);
+ UNUSED(options);
+
+ /* Hash. */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ false));
+ RETTOK(dns_hashalg_fromtext(&hashalg, &token.value.as_textregion));
+ RETERR(uint8_tobuffer(hashalg, target));
+
+ /* Flags. */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
+ false));
+ flags = token.value.as_ulong;
+ if (flags > 255U) {
+ RETTOK(ISC_R_RANGE);
+ }
+ RETERR(uint8_tobuffer(flags, target));
+
+ /* Iterations. */
+ 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));
+
+ /* Salt. */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ false));
+ if (token.value.as_textregion.length > (255 * 2)) {
+ RETTOK(DNS_R_TEXTTOOLONG);
+ }
+ if (strcmp(DNS_AS_STR(token), "-") == 0) {
+ RETERR(uint8_tobuffer(0, target));
+ } else {
+ RETERR(uint8_tobuffer(strlen(DNS_AS_STR(token)) / 2, target));
+ RETERR(isc_hex_decodestring(DNS_AS_STR(token), target));
+ }
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+totext_nsec3param(ARGS_TOTEXT) {
+ isc_region_t sr;
+ unsigned int i, j;
+ unsigned char hash;
+ unsigned char flags;
+ char buf[sizeof("65535 ")];
+ uint32_t iterations;
+
+ REQUIRE(rdata->type == dns_rdatatype_nsec3param);
+ REQUIRE(rdata->length != 0);
+
+ UNUSED(tctx);
+
+ dns_rdata_toregion(rdata, &sr);
+
+ hash = uint8_fromregion(&sr);
+ isc_region_consume(&sr, 1);
+
+ flags = uint8_fromregion(&sr);
+ isc_region_consume(&sr, 1);
+
+ iterations = uint16_fromregion(&sr);
+ isc_region_consume(&sr, 2);
+
+ snprintf(buf, sizeof(buf), "%u ", hash);
+ RETERR(str_totext(buf, target));
+
+ snprintf(buf, sizeof(buf), "%u ", flags);
+ RETERR(str_totext(buf, target));
+
+ snprintf(buf, sizeof(buf), "%u ", iterations);
+ RETERR(str_totext(buf, target));
+
+ j = uint8_fromregion(&sr);
+ isc_region_consume(&sr, 1);
+ INSIST(j <= sr.length);
+
+ if (j != 0) {
+ i = sr.length;
+ sr.length = j;
+ RETERR(isc_hex_totext(&sr, 1, "", target));
+ sr.length = i - j;
+ } else {
+ RETERR(str_totext("-", target));
+ }
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+fromwire_nsec3param(ARGS_FROMWIRE) {
+ isc_region_t sr, rr;
+ unsigned int saltlen;
+
+ REQUIRE(type == dns_rdatatype_nsec3param);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(options);
+ UNUSED(dctx);
+
+ isc_buffer_activeregion(source, &sr);
+ rr = sr;
+
+ /* hash(1), flags(1), iterations(2), saltlen(1) */
+ if (sr.length < 5U) {
+ RETERR(DNS_R_FORMERR);
+ }
+ saltlen = sr.base[4];
+ isc_region_consume(&sr, 5);
+
+ if (sr.length != saltlen) {
+ RETERR(DNS_R_FORMERR);
+ }
+ isc_region_consume(&sr, saltlen);
+ RETERR(mem_tobuffer(target, rr.base, rr.length));
+ isc_buffer_forward(source, rr.length);
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+towire_nsec3param(ARGS_TOWIRE) {
+ isc_region_t sr;
+
+ REQUIRE(rdata->type == dns_rdatatype_nsec3param);
+ REQUIRE(rdata->length != 0);
+
+ UNUSED(cctx);
+
+ dns_rdata_toregion(rdata, &sr);
+ return (mem_tobuffer(target, sr.base, sr.length));
+}
+
+static int
+compare_nsec3param(ARGS_COMPARE) {
+ isc_region_t r1;
+ isc_region_t r2;
+
+ REQUIRE(rdata1->type == rdata2->type);
+ REQUIRE(rdata1->rdclass == rdata2->rdclass);
+ REQUIRE(rdata1->type == dns_rdatatype_nsec3param);
+ REQUIRE(rdata1->length != 0);
+ REQUIRE(rdata2->length != 0);
+
+ dns_rdata_toregion(rdata1, &r1);
+ dns_rdata_toregion(rdata2, &r2);
+ return (isc_region_compare(&r1, &r2));
+}
+
+static isc_result_t
+fromstruct_nsec3param(ARGS_FROMSTRUCT) {
+ dns_rdata_nsec3param_t *nsec3param = source;
+
+ REQUIRE(type == dns_rdatatype_nsec3param);
+ REQUIRE(nsec3param != NULL);
+ REQUIRE(nsec3param->common.rdtype == type);
+ REQUIRE(nsec3param->common.rdclass == rdclass);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ RETERR(uint8_tobuffer(nsec3param->hash, target));
+ RETERR(uint8_tobuffer(nsec3param->flags, target));
+ RETERR(uint16_tobuffer(nsec3param->iterations, target));
+ RETERR(uint8_tobuffer(nsec3param->salt_length, target));
+ RETERR(mem_tobuffer(target, nsec3param->salt, nsec3param->salt_length));
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+tostruct_nsec3param(ARGS_TOSTRUCT) {
+ isc_region_t region;
+ dns_rdata_nsec3param_t *nsec3param = target;
+
+ REQUIRE(rdata->type == dns_rdatatype_nsec3param);
+ REQUIRE(nsec3param != NULL);
+ REQUIRE(rdata->length != 0);
+
+ nsec3param->common.rdclass = rdata->rdclass;
+ nsec3param->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&nsec3param->common, link);
+
+ region.base = rdata->data;
+ region.length = rdata->length;
+ nsec3param->hash = uint8_consume_fromregion(&region);
+ nsec3param->flags = uint8_consume_fromregion(&region);
+ nsec3param->iterations = uint16_consume_fromregion(&region);
+
+ nsec3param->salt_length = uint8_consume_fromregion(&region);
+ INSIST(nsec3param->salt_length == region.length);
+ nsec3param->salt = mem_maybedup(mctx, region.base,
+ nsec3param->salt_length);
+ if (nsec3param->salt == NULL) {
+ return (ISC_R_NOMEMORY);
+ }
+ isc_region_consume(&region, nsec3param->salt_length);
+
+ nsec3param->mctx = mctx;
+ return (ISC_R_SUCCESS);
+}
+
+static void
+freestruct_nsec3param(ARGS_FREESTRUCT) {
+ dns_rdata_nsec3param_t *nsec3param = source;
+
+ REQUIRE(nsec3param != NULL);
+ REQUIRE(nsec3param->common.rdtype == dns_rdatatype_nsec3param);
+
+ if (nsec3param->mctx == NULL) {
+ return;
+ }
+
+ if (nsec3param->salt != NULL) {
+ isc_mem_free(nsec3param->mctx, nsec3param->salt);
+ }
+ nsec3param->mctx = NULL;
+}
+
+static isc_result_t
+additionaldata_nsec3param(ARGS_ADDLDATA) {
+ REQUIRE(rdata->type == dns_rdatatype_nsec3param);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(add);
+ UNUSED(arg);
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+digest_nsec3param(ARGS_DIGEST) {
+ isc_region_t r;
+
+ REQUIRE(rdata->type == dns_rdatatype_nsec3param);
+
+ dns_rdata_toregion(rdata, &r);
+ return ((digest)(arg, &r));
+}
+
+static bool
+checkowner_nsec3param(ARGS_CHECKOWNER) {
+ REQUIRE(type == dns_rdatatype_nsec3param);
+
+ UNUSED(name);
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (true);
+}
+
+static bool
+checknames_nsec3param(ARGS_CHECKNAMES) {
+ REQUIRE(rdata->type == dns_rdatatype_nsec3param);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(bad);
+
+ return (true);
+}
+
+static int
+casecompare_nsec3param(ARGS_COMPARE) {
+ return (compare_nsec3param(rdata1, rdata2));
+}
+
+#endif /* RDATA_GENERIC_NSEC3PARAM_51_C */
diff --git a/lib/dns/rdata/generic/nsec3param_51.h b/lib/dns/rdata/generic/nsec3param_51.h
new file mode 100644
index 0000000..9288a96
--- /dev/null
+++ b/lib/dns/rdata/generic/nsec3param_51.h
@@ -0,0 +1,29 @@
+/*
+ * 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
+
+/*!
+ * \brief Per RFC 5155 */
+
+#include <isc/iterated_hash.h>
+
+typedef struct dns_rdata_nsec3param {
+ dns_rdatacommon_t common;
+ isc_mem_t *mctx;
+ dns_hash_t hash;
+ unsigned char flags; /* DNS_NSEC3FLAG_* */
+ dns_iterations_t iterations;
+ unsigned char salt_length;
+ unsigned char *salt;
+} dns_rdata_nsec3param_t;
diff --git a/lib/dns/rdata/generic/nsec_47.c b/lib/dns/rdata/generic/nsec_47.c
new file mode 100644
index 0000000..77700be
--- /dev/null
+++ b/lib/dns/rdata/generic/nsec_47.c
@@ -0,0 +1,291 @@
+/*
+ * 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.
+ */
+
+/* RFC 3845 */
+
+#ifndef RDATA_GENERIC_NSEC_47_C
+#define RDATA_GENERIC_NSEC_47_C
+
+/*
+ * The attributes do not include DNS_RDATATYPEATTR_SINGLETON
+ * because we must be able to handle a parent/child NSEC pair.
+ */
+#define RRTYPE_NSEC_ATTRIBUTES \
+ (DNS_RDATATYPEATTR_DNSSEC | DNS_RDATATYPEATTR_ZONECUTAUTH | \
+ DNS_RDATATYPEATTR_ATCNAME)
+
+static isc_result_t
+fromtext_nsec(ARGS_FROMTEXT) {
+ isc_token_t token;
+ dns_name_t name;
+ isc_buffer_t buffer;
+
+ REQUIRE(type == dns_rdatatype_nsec);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(callbacks);
+
+ /*
+ * Next domain.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ false));
+ dns_name_init(&name, NULL);
+ buffer_fromregion(&buffer, &token.value.as_region);
+ if (origin == NULL) {
+ origin = dns_rootname;
+ }
+ RETTOK(dns_name_fromtext(&name, &buffer, origin, options, target));
+
+ return (typemap_fromtext(lexer, target, false));
+}
+
+static isc_result_t
+totext_nsec(ARGS_TOTEXT) {
+ isc_region_t sr;
+ dns_name_t name;
+
+ REQUIRE(rdata->type == dns_rdatatype_nsec);
+ REQUIRE(rdata->length != 0);
+
+ UNUSED(tctx);
+
+ dns_name_init(&name, NULL);
+ dns_rdata_toregion(rdata, &sr);
+ dns_name_fromregion(&name, &sr);
+ isc_region_consume(&sr, name_length(&name));
+ RETERR(dns_name_totext(&name, false, target));
+ /*
+ * Don't leave a trailing space when there's no typemap present.
+ */
+ if (sr.length > 0) {
+ RETERR(str_totext(" ", target));
+ }
+ return (typemap_totext(&sr, NULL, target));
+}
+
+static isc_result_t
+fromwire_nsec(ARGS_FROMWIRE) {
+ isc_region_t sr;
+ dns_name_t name;
+
+ REQUIRE(type == dns_rdatatype_nsec);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ dns_decompress_setmethods(dctx, DNS_COMPRESS_NONE);
+
+ dns_name_init(&name, NULL);
+ RETERR(dns_name_fromwire(&name, source, dctx, options, target));
+
+ isc_buffer_activeregion(source, &sr);
+ RETERR(typemap_test(&sr, false));
+ RETERR(mem_tobuffer(target, sr.base, sr.length));
+ isc_buffer_forward(source, sr.length);
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+towire_nsec(ARGS_TOWIRE) {
+ isc_region_t sr;
+ dns_name_t name;
+ dns_offsets_t offsets;
+
+ REQUIRE(rdata->type == dns_rdatatype_nsec);
+ REQUIRE(rdata->length != 0);
+
+ dns_compress_setmethods(cctx, DNS_COMPRESS_NONE);
+ dns_name_init(&name, offsets);
+ dns_rdata_toregion(rdata, &sr);
+ dns_name_fromregion(&name, &sr);
+ isc_region_consume(&sr, name_length(&name));
+ RETERR(dns_name_towire(&name, cctx, target));
+
+ return (mem_tobuffer(target, sr.base, sr.length));
+}
+
+static int
+compare_nsec(ARGS_COMPARE) {
+ isc_region_t r1;
+ isc_region_t r2;
+
+ REQUIRE(rdata1->type == rdata2->type);
+ REQUIRE(rdata1->rdclass == rdata2->rdclass);
+ REQUIRE(rdata1->type == dns_rdatatype_nsec);
+ REQUIRE(rdata1->length != 0);
+ REQUIRE(rdata2->length != 0);
+
+ dns_rdata_toregion(rdata1, &r1);
+ dns_rdata_toregion(rdata2, &r2);
+ return (isc_region_compare(&r1, &r2));
+}
+
+static isc_result_t
+fromstruct_nsec(ARGS_FROMSTRUCT) {
+ dns_rdata_nsec_t *nsec = source;
+ isc_region_t region;
+
+ REQUIRE(type == dns_rdatatype_nsec);
+ REQUIRE(nsec != NULL);
+ REQUIRE(nsec->common.rdtype == type);
+ REQUIRE(nsec->common.rdclass == rdclass);
+ REQUIRE(nsec->typebits != NULL || nsec->len == 0);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ dns_name_toregion(&nsec->next, &region);
+ RETERR(isc_buffer_copyregion(target, &region));
+
+ region.base = nsec->typebits;
+ region.length = nsec->len;
+ RETERR(typemap_test(&region, false));
+ return (mem_tobuffer(target, nsec->typebits, nsec->len));
+}
+
+static isc_result_t
+tostruct_nsec(ARGS_TOSTRUCT) {
+ isc_region_t region;
+ dns_rdata_nsec_t *nsec = target;
+ dns_name_t name;
+
+ REQUIRE(rdata->type == dns_rdatatype_nsec);
+ REQUIRE(nsec != NULL);
+ REQUIRE(rdata->length != 0);
+
+ nsec->common.rdclass = rdata->rdclass;
+ nsec->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&nsec->common, link);
+
+ dns_name_init(&name, NULL);
+ dns_rdata_toregion(rdata, &region);
+ dns_name_fromregion(&name, &region);
+ isc_region_consume(&region, name_length(&name));
+ dns_name_init(&nsec->next, NULL);
+ name_duporclone(&name, mctx, &nsec->next);
+
+ nsec->len = region.length;
+ nsec->typebits = mem_maybedup(mctx, region.base, region.length);
+ if (nsec->typebits == NULL) {
+ goto cleanup;
+ }
+
+ nsec->mctx = mctx;
+ return (ISC_R_SUCCESS);
+
+cleanup:
+ if (mctx != NULL) {
+ dns_name_free(&nsec->next, mctx);
+ }
+ return (ISC_R_NOMEMORY);
+}
+
+static void
+freestruct_nsec(ARGS_FREESTRUCT) {
+ dns_rdata_nsec_t *nsec = source;
+
+ REQUIRE(nsec != NULL);
+ REQUIRE(nsec->common.rdtype == dns_rdatatype_nsec);
+
+ if (nsec->mctx == NULL) {
+ return;
+ }
+
+ dns_name_free(&nsec->next, nsec->mctx);
+ if (nsec->typebits != NULL) {
+ isc_mem_free(nsec->mctx, nsec->typebits);
+ }
+ nsec->mctx = NULL;
+}
+
+static isc_result_t
+additionaldata_nsec(ARGS_ADDLDATA) {
+ REQUIRE(rdata->type == dns_rdatatype_nsec);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(add);
+ UNUSED(arg);
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+digest_nsec(ARGS_DIGEST) {
+ isc_region_t r;
+
+ REQUIRE(rdata->type == dns_rdatatype_nsec);
+
+ dns_rdata_toregion(rdata, &r);
+ return ((digest)(arg, &r));
+}
+
+static bool
+checkowner_nsec(ARGS_CHECKOWNER) {
+ REQUIRE(type == dns_rdatatype_nsec);
+
+ UNUSED(name);
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (true);
+}
+
+static bool
+checknames_nsec(ARGS_CHECKNAMES) {
+ REQUIRE(rdata->type == dns_rdatatype_nsec);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(bad);
+
+ return (true);
+}
+
+static int
+casecompare_nsec(ARGS_COMPARE) {
+ isc_region_t region1;
+ isc_region_t region2;
+ dns_name_t name1;
+ dns_name_t name2;
+ int order;
+
+ REQUIRE(rdata1->type == rdata2->type);
+ REQUIRE(rdata1->rdclass == rdata2->rdclass);
+ REQUIRE(rdata1->type == dns_rdatatype_nsec);
+ REQUIRE(rdata1->length != 0);
+ REQUIRE(rdata2->length != 0);
+
+ dns_name_init(&name1, NULL);
+ dns_name_init(&name2, NULL);
+
+ dns_rdata_toregion(rdata1, &region1);
+ dns_rdata_toregion(rdata2, &region2);
+
+ dns_name_fromregion(&name1, &region1);
+ dns_name_fromregion(&name2, &region2);
+
+ order = dns_name_rdatacompare(&name1, &name2);
+ if (order != 0) {
+ return (order);
+ }
+
+ isc_region_consume(&region1, name_length(&name1));
+ isc_region_consume(&region2, name_length(&name2));
+
+ return (isc_region_compare(&region1, &region2));
+}
+#endif /* RDATA_GENERIC_NSEC_47_C */
diff --git a/lib/dns/rdata/generic/nsec_47.h b/lib/dns/rdata/generic/nsec_47.h
new file mode 100644
index 0000000..eded7ac
--- /dev/null
+++ b/lib/dns/rdata/generic/nsec_47.h
@@ -0,0 +1,25 @@
+/*
+ * 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
+
+/*!
+ * \brief Per RFC 3845 */
+
+typedef struct dns_rdata_nsec {
+ dns_rdatacommon_t common;
+ isc_mem_t *mctx;
+ dns_name_t next;
+ unsigned char *typebits;
+ uint16_t len;
+} dns_rdata_nsec_t;
diff --git a/lib/dns/rdata/generic/null_10.c b/lib/dns/rdata/generic/null_10.c
new file mode 100644
index 0000000..4a019dd
--- /dev/null
+++ b/lib/dns/rdata/generic/null_10.c
@@ -0,0 +1,187 @@
+/*
+ * 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_NULL_10_C
+#define RDATA_GENERIC_NULL_10_C
+
+#define RRTYPE_NULL_ATTRIBUTES (0)
+
+static isc_result_t
+fromtext_null(ARGS_FROMTEXT) {
+ REQUIRE(type == dns_rdatatype_null);
+
+ UNUSED(rdclass);
+ UNUSED(type);
+ UNUSED(lexer);
+ UNUSED(origin);
+ UNUSED(options);
+ UNUSED(target);
+ UNUSED(callbacks);
+
+ return (DNS_R_SYNTAX);
+}
+
+static isc_result_t
+totext_null(ARGS_TOTEXT) {
+ REQUIRE(rdata->type == dns_rdatatype_null);
+
+ return (unknown_totext(rdata, tctx, target));
+}
+
+static isc_result_t
+fromwire_null(ARGS_FROMWIRE) {
+ isc_region_t sr;
+
+ REQUIRE(type == dns_rdatatype_null);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(dctx);
+ UNUSED(options);
+
+ isc_buffer_activeregion(source, &sr);
+ isc_buffer_forward(source, sr.length);
+ return (mem_tobuffer(target, sr.base, sr.length));
+}
+
+static isc_result_t
+towire_null(ARGS_TOWIRE) {
+ REQUIRE(rdata->type == dns_rdatatype_null);
+
+ UNUSED(cctx);
+
+ return (mem_tobuffer(target, rdata->data, rdata->length));
+}
+
+static int
+compare_null(ARGS_COMPARE) {
+ isc_region_t r1;
+ isc_region_t r2;
+
+ REQUIRE(rdata1->type == rdata2->type);
+ REQUIRE(rdata1->rdclass == rdata2->rdclass);
+ REQUIRE(rdata1->type == dns_rdatatype_null);
+
+ dns_rdata_toregion(rdata1, &r1);
+ dns_rdata_toregion(rdata2, &r2);
+ return (isc_region_compare(&r1, &r2));
+}
+
+static isc_result_t
+fromstruct_null(ARGS_FROMSTRUCT) {
+ dns_rdata_null_t *null = source;
+
+ REQUIRE(type == dns_rdatatype_null);
+ REQUIRE(null != NULL);
+ REQUIRE(null->common.rdtype == type);
+ REQUIRE(null->common.rdclass == rdclass);
+ REQUIRE(null->data != NULL || null->length == 0);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ return (mem_tobuffer(target, null->data, null->length));
+}
+
+static isc_result_t
+tostruct_null(ARGS_TOSTRUCT) {
+ dns_rdata_null_t *null = target;
+ isc_region_t r;
+
+ REQUIRE(rdata->type == dns_rdatatype_null);
+ REQUIRE(null != NULL);
+
+ null->common.rdclass = rdata->rdclass;
+ null->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&null->common, link);
+
+ dns_rdata_toregion(rdata, &r);
+ null->length = r.length;
+ null->data = mem_maybedup(mctx, r.base, r.length);
+ if (null->data == NULL) {
+ return (ISC_R_NOMEMORY);
+ }
+
+ null->mctx = mctx;
+ return (ISC_R_SUCCESS);
+}
+
+static void
+freestruct_null(ARGS_FREESTRUCT) {
+ dns_rdata_null_t *null = source;
+
+ REQUIRE(null != NULL);
+ REQUIRE(null->common.rdtype == dns_rdatatype_null);
+
+ if (null->mctx == NULL) {
+ return;
+ }
+
+ if (null->data != NULL) {
+ isc_mem_free(null->mctx, null->data);
+ }
+ null->mctx = NULL;
+}
+
+static isc_result_t
+additionaldata_null(ARGS_ADDLDATA) {
+ REQUIRE(rdata->type == dns_rdatatype_null);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(add);
+ UNUSED(arg);
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+digest_null(ARGS_DIGEST) {
+ isc_region_t r;
+
+ REQUIRE(rdata->type == dns_rdatatype_null);
+
+ dns_rdata_toregion(rdata, &r);
+
+ return ((digest)(arg, &r));
+}
+
+static bool
+checkowner_null(ARGS_CHECKOWNER) {
+ REQUIRE(type == dns_rdatatype_null);
+
+ UNUSED(name);
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (true);
+}
+
+static bool
+checknames_null(ARGS_CHECKNAMES) {
+ REQUIRE(rdata->type == dns_rdatatype_null);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(bad);
+
+ return (true);
+}
+
+static int
+casecompare_null(ARGS_COMPARE) {
+ return (compare_null(rdata1, rdata2));
+}
+
+#endif /* RDATA_GENERIC_NULL_10_C */
diff --git a/lib/dns/rdata/generic/null_10.h b/lib/dns/rdata/generic/null_10.h
new file mode 100644
index 0000000..d015b7d
--- /dev/null
+++ b/lib/dns/rdata/generic/null_10.h
@@ -0,0 +1,22 @@
+/*
+ * 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_null {
+ dns_rdatacommon_t common;
+ isc_mem_t *mctx;
+ uint16_t length;
+ unsigned char *data;
+} dns_rdata_null_t;
diff --git a/lib/dns/rdata/generic/nxt_30.c b/lib/dns/rdata/generic/nxt_30.c
new file mode 100644
index 0000000..93d2384
--- /dev/null
+++ b/lib/dns/rdata/generic/nxt_30.c
@@ -0,0 +1,351 @@
+/*
+ * 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.
+ */
+
+/* RFC2535 */
+
+#ifndef RDATA_GENERIC_NXT_30_C
+#define RDATA_GENERIC_NXT_30_C
+
+/*
+ * The attributes do not include DNS_RDATATYPEATTR_SINGLETON
+ * because we must be able to handle a parent/child NXT pair.
+ */
+#define RRTYPE_NXT_ATTRIBUTES (0)
+
+static isc_result_t
+fromtext_nxt(ARGS_FROMTEXT) {
+ isc_token_t token;
+ dns_name_t name;
+ isc_buffer_t buffer;
+ char *e;
+ unsigned char bm[8 * 1024]; /* 64k bits */
+ dns_rdatatype_t covered;
+ dns_rdatatype_t maxcovered = 0;
+ bool first = true;
+ long n;
+
+ REQUIRE(type == dns_rdatatype_nxt);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(callbacks);
+
+ /*
+ * Next domain.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ false));
+ dns_name_init(&name, NULL);
+ buffer_fromregion(&buffer, &token.value.as_region);
+ if (origin == NULL) {
+ origin = dns_rootname;
+ }
+ RETTOK(dns_name_fromtext(&name, &buffer, origin, options, target));
+
+ memset(bm, 0, sizeof(bm));
+ do {
+ RETERR(isc_lex_getmastertoken(lexer, &token,
+ isc_tokentype_string, true));
+ if (token.type != isc_tokentype_string) {
+ break;
+ }
+ n = strtol(DNS_AS_STR(token), &e, 10);
+ if (e != DNS_AS_STR(token) && *e == '\0') {
+ covered = (dns_rdatatype_t)n;
+ } else if (dns_rdatatype_fromtext(&covered,
+ &token.value.as_textregion) ==
+ DNS_R_UNKNOWN)
+ {
+ RETTOK(DNS_R_UNKNOWN);
+ }
+ /*
+ * NXT is only specified for types 1..127.
+ */
+ if (covered < 1 || covered > 127) {
+ return (ISC_R_RANGE);
+ }
+ if (first || covered > maxcovered) {
+ maxcovered = covered;
+ }
+ first = false;
+ bm[covered / 8] |= (0x80 >> (covered % 8));
+ } while (1);
+ isc_lex_ungettoken(lexer, &token);
+ if (first) {
+ return (ISC_R_SUCCESS);
+ }
+ n = (maxcovered + 8) / 8;
+ return (mem_tobuffer(target, bm, n));
+}
+
+static isc_result_t
+totext_nxt(ARGS_TOTEXT) {
+ isc_region_t sr;
+ unsigned int i, j;
+ dns_name_t name;
+ dns_name_t prefix;
+ bool sub;
+
+ REQUIRE(rdata->type == dns_rdatatype_nxt);
+ REQUIRE(rdata->length != 0);
+
+ dns_name_init(&name, NULL);
+ dns_name_init(&prefix, NULL);
+ dns_rdata_toregion(rdata, &sr);
+ dns_name_fromregion(&name, &sr);
+ isc_region_consume(&sr, name_length(&name));
+ sub = name_prefix(&name, tctx->origin, &prefix);
+ RETERR(dns_name_totext(&prefix, sub, target));
+
+ for (i = 0; i < sr.length; i++) {
+ if (sr.base[i] != 0) {
+ for (j = 0; j < 8; j++) {
+ if ((sr.base[i] & (0x80 >> j)) != 0) {
+ {
+ dns_rdatatype_t t = i * 8 + j;
+ RETERR(str_totext(" ", target));
+ if (dns_rdatatype_isknown(t)) {
+ RETERR(dns_rdatatype_totext(
+ t, target));
+ } else {
+ char buf[sizeof("6553"
+ "5")];
+ snprintf(buf,
+ sizeof(buf),
+ "%u", t);
+ RETERR(str_totext(
+ buf, target));
+ }
+ }
+ }
+ }
+ }
+ }
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+fromwire_nxt(ARGS_FROMWIRE) {
+ isc_region_t sr;
+ dns_name_t name;
+
+ REQUIRE(type == dns_rdatatype_nxt);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ dns_decompress_setmethods(dctx, DNS_COMPRESS_NONE);
+
+ dns_name_init(&name, NULL);
+ RETERR(dns_name_fromwire(&name, source, dctx, options, target));
+
+ isc_buffer_activeregion(source, &sr);
+ if (sr.length > 0 && ((sr.base[0] & 0x80) != 0 || sr.length > 16 ||
+ sr.base[sr.length - 1] == 0))
+ {
+ return (DNS_R_BADBITMAP);
+ }
+ RETERR(mem_tobuffer(target, sr.base, sr.length));
+ isc_buffer_forward(source, sr.length);
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+towire_nxt(ARGS_TOWIRE) {
+ isc_region_t sr;
+ dns_name_t name;
+ dns_offsets_t offsets;
+
+ REQUIRE(rdata->type == dns_rdatatype_nxt);
+ REQUIRE(rdata->length != 0);
+
+ dns_compress_setmethods(cctx, DNS_COMPRESS_NONE);
+ dns_name_init(&name, offsets);
+ dns_rdata_toregion(rdata, &sr);
+ dns_name_fromregion(&name, &sr);
+ isc_region_consume(&sr, name_length(&name));
+ RETERR(dns_name_towire(&name, cctx, target));
+
+ return (mem_tobuffer(target, sr.base, sr.length));
+}
+
+static int
+compare_nxt(ARGS_COMPARE) {
+ isc_region_t r1;
+ isc_region_t r2;
+ dns_name_t name1;
+ dns_name_t name2;
+ int order;
+
+ REQUIRE(rdata1->type == rdata2->type);
+ REQUIRE(rdata1->rdclass == rdata2->rdclass);
+ REQUIRE(rdata1->type == dns_rdatatype_nxt);
+ REQUIRE(rdata1->length != 0);
+ REQUIRE(rdata2->length != 0);
+
+ dns_name_init(&name1, NULL);
+ dns_name_init(&name2, NULL);
+ dns_rdata_toregion(rdata1, &r1);
+ dns_rdata_toregion(rdata2, &r2);
+ dns_name_fromregion(&name1, &r1);
+ dns_name_fromregion(&name2, &r2);
+ order = dns_name_rdatacompare(&name1, &name2);
+ if (order != 0) {
+ return (order);
+ }
+
+ isc_region_consume(&r1, name_length(&name1));
+ isc_region_consume(&r2, name_length(&name2));
+
+ return (isc_region_compare(&r1, &r2));
+}
+
+static isc_result_t
+fromstruct_nxt(ARGS_FROMSTRUCT) {
+ dns_rdata_nxt_t *nxt = source;
+ isc_region_t region;
+
+ REQUIRE(type == dns_rdatatype_nxt);
+ REQUIRE(nxt != NULL);
+ REQUIRE(nxt->common.rdtype == type);
+ REQUIRE(nxt->common.rdclass == rdclass);
+ REQUIRE(nxt->typebits != NULL || nxt->len == 0);
+ if (nxt->typebits != NULL && (nxt->typebits[0] & 0x80) == 0) {
+ REQUIRE(nxt->len <= 16);
+ REQUIRE(nxt->typebits[nxt->len - 1] != 0);
+ }
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ dns_name_toregion(&nxt->next, &region);
+ RETERR(isc_buffer_copyregion(target, &region));
+
+ return (mem_tobuffer(target, nxt->typebits, nxt->len));
+}
+
+static isc_result_t
+tostruct_nxt(ARGS_TOSTRUCT) {
+ isc_region_t region;
+ dns_rdata_nxt_t *nxt = target;
+ dns_name_t name;
+
+ REQUIRE(rdata->type == dns_rdatatype_nxt);
+ REQUIRE(nxt != NULL);
+ REQUIRE(rdata->length != 0);
+
+ nxt->common.rdclass = rdata->rdclass;
+ nxt->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&nxt->common, link);
+
+ dns_name_init(&name, NULL);
+ dns_rdata_toregion(rdata, &region);
+ dns_name_fromregion(&name, &region);
+ isc_region_consume(&region, name_length(&name));
+ dns_name_init(&nxt->next, NULL);
+ name_duporclone(&name, mctx, &nxt->next);
+
+ nxt->len = region.length;
+ nxt->typebits = mem_maybedup(mctx, region.base, region.length);
+ if (nxt->typebits == NULL) {
+ goto cleanup;
+ }
+
+ nxt->mctx = mctx;
+ return (ISC_R_SUCCESS);
+
+cleanup:
+ if (mctx != NULL) {
+ dns_name_free(&nxt->next, mctx);
+ }
+ return (ISC_R_NOMEMORY);
+}
+
+static void
+freestruct_nxt(ARGS_FREESTRUCT) {
+ dns_rdata_nxt_t *nxt = source;
+
+ REQUIRE(nxt != NULL);
+ REQUIRE(nxt->common.rdtype == dns_rdatatype_nxt);
+
+ if (nxt->mctx == NULL) {
+ return;
+ }
+
+ dns_name_free(&nxt->next, nxt->mctx);
+ if (nxt->typebits != NULL) {
+ isc_mem_free(nxt->mctx, nxt->typebits);
+ }
+ nxt->mctx = NULL;
+}
+
+static isc_result_t
+additionaldata_nxt(ARGS_ADDLDATA) {
+ REQUIRE(rdata->type == dns_rdatatype_nxt);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(add);
+ UNUSED(arg);
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+digest_nxt(ARGS_DIGEST) {
+ isc_region_t r;
+ dns_name_t name;
+ isc_result_t result;
+
+ REQUIRE(rdata->type == dns_rdatatype_nxt);
+
+ dns_rdata_toregion(rdata, &r);
+ dns_name_init(&name, NULL);
+ dns_name_fromregion(&name, &r);
+ result = dns_name_digest(&name, digest, arg);
+ if (result != ISC_R_SUCCESS) {
+ return (result);
+ }
+ isc_region_consume(&r, name_length(&name));
+
+ return ((digest)(arg, &r));
+}
+
+static bool
+checkowner_nxt(ARGS_CHECKOWNER) {
+ REQUIRE(type == dns_rdatatype_nxt);
+
+ UNUSED(name);
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (true);
+}
+
+static bool
+checknames_nxt(ARGS_CHECKNAMES) {
+ REQUIRE(rdata->type == dns_rdatatype_nxt);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(bad);
+
+ return (true);
+}
+
+static int
+casecompare_nxt(ARGS_COMPARE) {
+ return (compare_nxt(rdata1, rdata2));
+}
+#endif /* RDATA_GENERIC_NXT_30_C */
diff --git a/lib/dns/rdata/generic/nxt_30.h b/lib/dns/rdata/generic/nxt_30.h
new file mode 100644
index 0000000..fb3e8b2
--- /dev/null
+++ b/lib/dns/rdata/generic/nxt_30.h
@@ -0,0 +1,25 @@
+/*
+ * 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
+
+/*!
+ * \brief RFC2535 */
+
+typedef struct dns_rdata_nxt {
+ dns_rdatacommon_t common;
+ isc_mem_t *mctx;
+ dns_name_t next;
+ unsigned char *typebits;
+ uint16_t len;
+} dns_rdata_nxt_t;
diff --git a/lib/dns/rdata/generic/openpgpkey_61.c b/lib/dns/rdata/generic/openpgpkey_61.c
new file mode 100644
index 0000000..d4f9fa5
--- /dev/null
+++ b/lib/dns/rdata/generic/openpgpkey_61.c
@@ -0,0 +1,250 @@
+/*
+ * 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_OPENPGPKEY_61_C
+#define RDATA_GENERIC_OPENPGPKEY_61_C
+
+#define RRTYPE_OPENPGPKEY_ATTRIBUTES 0
+
+static isc_result_t
+fromtext_openpgpkey(ARGS_FROMTEXT) {
+ REQUIRE(type == dns_rdatatype_openpgpkey);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(callbacks);
+ UNUSED(options);
+ UNUSED(origin);
+
+ /*
+ * Keyring.
+ */
+ return (isc_base64_tobuffer(lexer, target, -2));
+}
+
+static isc_result_t
+totext_openpgpkey(ARGS_TOTEXT) {
+ isc_region_t sr;
+
+ REQUIRE(rdata->type == dns_rdatatype_openpgpkey);
+ REQUIRE(rdata->length != 0);
+
+ dns_rdata_toregion(rdata, &sr);
+
+ /*
+ * Keyring
+ */
+ if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) {
+ RETERR(str_totext("( ", target));
+ }
+
+ if ((tctx->flags & DNS_STYLEFLAG_NOCRYPTO) == 0) {
+ if (tctx->width == 0) { /* No splitting */
+ RETERR(isc_base64_totext(&sr, 60, "", target));
+ } else {
+ RETERR(isc_base64_totext(&sr, tctx->width - 2,
+ tctx->linebreak, target));
+ }
+ } else {
+ RETERR(str_totext("[omitted]", target));
+ }
+
+ if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) {
+ RETERR(str_totext(" )", target));
+ }
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+fromwire_openpgpkey(ARGS_FROMWIRE) {
+ isc_region_t sr;
+
+ REQUIRE(type == dns_rdatatype_openpgpkey);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(dctx);
+ UNUSED(options);
+
+ /*
+ * Keyring.
+ */
+ isc_buffer_activeregion(source, &sr);
+ if (sr.length < 1) {
+ return (ISC_R_UNEXPECTEDEND);
+ }
+ isc_buffer_forward(source, sr.length);
+ return (mem_tobuffer(target, sr.base, sr.length));
+}
+
+static isc_result_t
+towire_openpgpkey(ARGS_TOWIRE) {
+ isc_region_t sr;
+
+ REQUIRE(rdata->type == dns_rdatatype_openpgpkey);
+ REQUIRE(rdata->length != 0);
+
+ UNUSED(cctx);
+
+ dns_rdata_toregion(rdata, &sr);
+ return (mem_tobuffer(target, sr.base, sr.length));
+}
+
+static int
+compare_openpgpkey(ARGS_COMPARE) {
+ isc_region_t r1;
+ isc_region_t r2;
+
+ REQUIRE(rdata1->type == rdata2->type);
+ REQUIRE(rdata1->rdclass == rdata2->rdclass);
+ REQUIRE(rdata1->type == dns_rdatatype_openpgpkey);
+ REQUIRE(rdata1->length != 0);
+ REQUIRE(rdata2->length != 0);
+
+ dns_rdata_toregion(rdata1, &r1);
+ dns_rdata_toregion(rdata2, &r2);
+ return (isc_region_compare(&r1, &r2));
+}
+
+static isc_result_t
+fromstruct_openpgpkey(ARGS_FROMSTRUCT) {
+ dns_rdata_openpgpkey_t *sig = source;
+
+ REQUIRE(type == dns_rdatatype_openpgpkey);
+ REQUIRE(sig != NULL);
+ REQUIRE(sig->common.rdtype == type);
+ REQUIRE(sig->common.rdclass == rdclass);
+ REQUIRE(sig->keyring != NULL && sig->length != 0);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ /*
+ * Keyring.
+ */
+ return (mem_tobuffer(target, sig->keyring, sig->length));
+}
+
+static isc_result_t
+tostruct_openpgpkey(ARGS_TOSTRUCT) {
+ isc_region_t sr;
+ dns_rdata_openpgpkey_t *sig = target;
+
+ REQUIRE(rdata->type == dns_rdatatype_openpgpkey);
+ REQUIRE(sig != NULL);
+ REQUIRE(rdata->length != 0);
+
+ sig->common.rdclass = rdata->rdclass;
+ sig->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&sig->common, link);
+
+ dns_rdata_toregion(rdata, &sr);
+
+ /*
+ * Keyring.
+ */
+ sig->length = sr.length;
+ sig->keyring = mem_maybedup(mctx, sr.base, sig->length);
+ if (sig->keyring == NULL) {
+ goto cleanup;
+ }
+
+ sig->mctx = mctx;
+ return (ISC_R_SUCCESS);
+
+cleanup:
+ return (ISC_R_NOMEMORY);
+}
+
+static void
+freestruct_openpgpkey(ARGS_FREESTRUCT) {
+ dns_rdata_openpgpkey_t *sig = (dns_rdata_openpgpkey_t *)source;
+
+ REQUIRE(sig != NULL);
+ REQUIRE(sig->common.rdtype == dns_rdatatype_openpgpkey);
+
+ if (sig->mctx == NULL) {
+ return;
+ }
+
+ if (sig->keyring != NULL) {
+ isc_mem_free(sig->mctx, sig->keyring);
+ }
+ sig->mctx = NULL;
+}
+
+static isc_result_t
+additionaldata_openpgpkey(ARGS_ADDLDATA) {
+ REQUIRE(rdata->type == dns_rdatatype_openpgpkey);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(add);
+ UNUSED(arg);
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+digest_openpgpkey(ARGS_DIGEST) {
+ isc_region_t r;
+
+ REQUIRE(rdata->type == dns_rdatatype_openpgpkey);
+
+ dns_rdata_toregion(rdata, &r);
+
+ return ((digest)(arg, &r));
+}
+
+static bool
+checkowner_openpgpkey(ARGS_CHECKOWNER) {
+ REQUIRE(type == dns_rdatatype_openpgpkey);
+
+ UNUSED(name);
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (true);
+}
+
+static bool
+checknames_openpgpkey(ARGS_CHECKNAMES) {
+ REQUIRE(rdata->type == dns_rdatatype_openpgpkey);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(bad);
+
+ return (true);
+}
+
+static int
+casecompare_openpgpkey(ARGS_COMPARE) {
+ isc_region_t r1;
+ isc_region_t r2;
+
+ REQUIRE(rdata1->type == rdata2->type);
+ REQUIRE(rdata1->rdclass == rdata2->rdclass);
+ REQUIRE(rdata1->type == dns_rdatatype_openpgpkey);
+ REQUIRE(rdata1->length != 0);
+ REQUIRE(rdata2->length != 0);
+
+ dns_rdata_toregion(rdata1, &r1);
+ dns_rdata_toregion(rdata2, &r2);
+
+ return (isc_region_compare(&r1, &r2));
+}
+
+#endif /* RDATA_GENERIC_OPENPGPKEY_61_C */
diff --git a/lib/dns/rdata/generic/openpgpkey_61.h b/lib/dns/rdata/generic/openpgpkey_61.h
new file mode 100644
index 0000000..702d343
--- /dev/null
+++ b/lib/dns/rdata/generic/openpgpkey_61.h
@@ -0,0 +1,21 @@
+/*
+ * 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_openpgpkey {
+ dns_rdatacommon_t common;
+ isc_mem_t *mctx;
+ uint16_t length;
+ unsigned char *keyring;
+} dns_rdata_openpgpkey_t;
diff --git a/lib/dns/rdata/generic/opt_41.c b/lib/dns/rdata/generic/opt_41.c
new file mode 100644
index 0000000..e5e7168
--- /dev/null
+++ b/lib/dns/rdata/generic/opt_41.c
@@ -0,0 +1,473 @@
+/*
+ * 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.
+ */
+
+/* RFC2671 */
+
+#ifndef RDATA_GENERIC_OPT_41_C
+#define RDATA_GENERIC_OPT_41_C
+
+#define RRTYPE_OPT_ATTRIBUTES \
+ (DNS_RDATATYPEATTR_SINGLETON | DNS_RDATATYPEATTR_META | \
+ DNS_RDATATYPEATTR_NOTQUESTION)
+
+#include <isc/utf8.h>
+
+static isc_result_t
+fromtext_opt(ARGS_FROMTEXT) {
+ /*
+ * OPT records do not have a text format.
+ */
+
+ REQUIRE(type == dns_rdatatype_opt);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(lexer);
+ UNUSED(origin);
+ UNUSED(options);
+ UNUSED(target);
+ UNUSED(callbacks);
+
+ return (ISC_R_NOTIMPLEMENTED);
+}
+
+static isc_result_t
+totext_opt(ARGS_TOTEXT) {
+ isc_region_t r;
+ isc_region_t or ;
+ uint16_t option;
+ uint16_t length;
+ char buf[sizeof("64000 64000")];
+
+ /*
+ * OPT records do not have a text format.
+ */
+
+ REQUIRE(rdata->type == dns_rdatatype_opt);
+
+ dns_rdata_toregion(rdata, &r);
+ while (r.length > 0) {
+ option = uint16_fromregion(&r);
+ isc_region_consume(&r, 2);
+ length = uint16_fromregion(&r);
+ isc_region_consume(&r, 2);
+ snprintf(buf, sizeof(buf), "%u %u", option, length);
+ RETERR(str_totext(buf, target));
+ INSIST(r.length >= length);
+ if (length > 0) {
+ if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) {
+ RETERR(str_totext(" (", target));
+ }
+ RETERR(str_totext(tctx->linebreak, target));
+ or = r;
+ or.length = length;
+ if (tctx->width == 0) { /* No splitting */
+ RETERR(isc_base64_totext(& or, 60, "", target));
+ } else {
+ RETERR(isc_base64_totext(& or, tctx->width - 2,
+ tctx->linebreak,
+ target));
+ }
+ isc_region_consume(&r, length);
+ if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) {
+ RETERR(str_totext(" )", target));
+ }
+ }
+ if (r.length > 0) {
+ RETERR(str_totext(" ", target));
+ }
+ }
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+fromwire_opt(ARGS_FROMWIRE) {
+ isc_region_t sregion;
+ isc_region_t tregion;
+ uint16_t opt;
+ uint16_t length;
+ unsigned int total;
+
+ REQUIRE(type == dns_rdatatype_opt);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(dctx);
+ UNUSED(options);
+
+ isc_buffer_activeregion(source, &sregion);
+ if (sregion.length == 0) {
+ return (ISC_R_SUCCESS);
+ }
+ total = 0;
+ while (sregion.length != 0) {
+ if (sregion.length < 4) {
+ return (ISC_R_UNEXPECTEDEND);
+ }
+ opt = uint16_fromregion(&sregion);
+ isc_region_consume(&sregion, 2);
+ length = uint16_fromregion(&sregion);
+ isc_region_consume(&sregion, 2);
+ total += 4;
+ if (sregion.length < length) {
+ return (ISC_R_UNEXPECTEDEND);
+ }
+ switch (opt) {
+ case DNS_OPT_LLQ:
+ if (length != 18U) {
+ return (DNS_R_OPTERR);
+ }
+ isc_region_consume(&sregion, length);
+ break;
+ case DNS_OPT_CLIENT_SUBNET: {
+ uint16_t family;
+ uint8_t addrlen;
+ uint8_t scope;
+ uint8_t addrbytes;
+
+ if (length < 4) {
+ return (DNS_R_OPTERR);
+ }
+ family = uint16_fromregion(&sregion);
+ isc_region_consume(&sregion, 2);
+ addrlen = uint8_fromregion(&sregion);
+ isc_region_consume(&sregion, 1);
+ scope = uint8_fromregion(&sregion);
+ isc_region_consume(&sregion, 1);
+
+ switch (family) {
+ case 0:
+ /*
+ * XXXMUKS: In queries and replies, if
+ * FAMILY is set to 0, SOURCE
+ * PREFIX-LENGTH and SCOPE PREFIX-LENGTH
+ * must be 0 and ADDRESS should not be
+ * present as the address and prefix
+ * lengths don't make sense because the
+ * family is unknown.
+ */
+ if (addrlen != 0U || scope != 0U) {
+ return (DNS_R_OPTERR);
+ }
+ break;
+ case 1:
+ if (addrlen > 32U || scope > 32U) {
+ return (DNS_R_OPTERR);
+ }
+ break;
+ case 2:
+ if (addrlen > 128U || scope > 128U) {
+ return (DNS_R_OPTERR);
+ }
+ break;
+ default:
+ return (DNS_R_OPTERR);
+ }
+ addrbytes = (addrlen + 7) / 8;
+ if (addrbytes + 4 != length) {
+ return (DNS_R_OPTERR);
+ }
+
+ if (addrbytes != 0U && (addrlen % 8) != 0) {
+ uint8_t bits = ~0U << (8 - (addrlen % 8));
+ bits &= sregion.base[addrbytes - 1];
+ if (bits != sregion.base[addrbytes - 1]) {
+ return (DNS_R_OPTERR);
+ }
+ }
+ isc_region_consume(&sregion, addrbytes);
+ break;
+ }
+ case DNS_OPT_EXPIRE:
+ /*
+ * Request has zero length. Response is 32 bits.
+ */
+ if (length != 0 && length != 4) {
+ return (DNS_R_OPTERR);
+ }
+ isc_region_consume(&sregion, length);
+ break;
+ case DNS_OPT_COOKIE:
+ /*
+ * Client cookie alone has length 8.
+ * Client + server cookie is 8 + [8..32].
+ */
+ if (length != 8 && (length < 16 || length > 40)) {
+ return (DNS_R_OPTERR);
+ }
+ isc_region_consume(&sregion, length);
+ break;
+ case DNS_OPT_KEY_TAG:
+ if (length == 0 || (length % 2) != 0) {
+ return (DNS_R_OPTERR);
+ }
+ isc_region_consume(&sregion, length);
+ break;
+ case DNS_OPT_EDE:
+ if (length < 2) {
+ return (DNS_R_OPTERR);
+ }
+ /* UTF-8 Byte Order Mark is not permitted. RFC 5198 */
+ if (isc_utf8_bom(sregion.base + 2, length - 2)) {
+ return (DNS_R_OPTERR);
+ }
+ /*
+ * The EXTRA-TEXT field is specified as UTF-8, and
+ * therefore must be validated for correctness
+ * according to RFC 3269 security considerations.
+ */
+ if (!isc_utf8_valid(sregion.base + 2, length - 2)) {
+ return (DNS_R_OPTERR);
+ }
+ isc_region_consume(&sregion, length);
+ break;
+ case DNS_OPT_CLIENT_TAG:
+ FALLTHROUGH;
+ case DNS_OPT_SERVER_TAG:
+ if (length != 2) {
+ return (DNS_R_OPTERR);
+ }
+ isc_region_consume(&sregion, length);
+ break;
+ default:
+ isc_region_consume(&sregion, length);
+ break;
+ }
+ total += length;
+ }
+
+ isc_buffer_activeregion(source, &sregion);
+ isc_buffer_availableregion(target, &tregion);
+ if (tregion.length < total) {
+ return (ISC_R_NOSPACE);
+ }
+ memmove(tregion.base, sregion.base, total);
+ isc_buffer_forward(source, total);
+ isc_buffer_add(target, total);
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+towire_opt(ARGS_TOWIRE) {
+ REQUIRE(rdata->type == dns_rdatatype_opt);
+
+ UNUSED(cctx);
+
+ return (mem_tobuffer(target, rdata->data, rdata->length));
+}
+
+static int
+compare_opt(ARGS_COMPARE) {
+ isc_region_t r1;
+ isc_region_t r2;
+
+ REQUIRE(rdata1->type == rdata2->type);
+ REQUIRE(rdata1->rdclass == rdata2->rdclass);
+ REQUIRE(rdata1->type == dns_rdatatype_opt);
+
+ dns_rdata_toregion(rdata1, &r1);
+ dns_rdata_toregion(rdata2, &r2);
+ return (isc_region_compare(&r1, &r2));
+}
+
+static isc_result_t
+fromstruct_opt(ARGS_FROMSTRUCT) {
+ dns_rdata_opt_t *opt = source;
+ isc_region_t region;
+ uint16_t length;
+
+ REQUIRE(type == dns_rdatatype_opt);
+ REQUIRE(opt != NULL);
+ REQUIRE(opt->common.rdtype == type);
+ REQUIRE(opt->common.rdclass == rdclass);
+ REQUIRE(opt->options != NULL || opt->length == 0);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ region.base = opt->options;
+ region.length = opt->length;
+ while (region.length >= 4) {
+ isc_region_consume(&region, 2); /* opt */
+ length = uint16_fromregion(&region);
+ isc_region_consume(&region, 2);
+ if (region.length < length) {
+ return (ISC_R_UNEXPECTEDEND);
+ }
+ isc_region_consume(&region, length);
+ }
+ if (region.length != 0) {
+ return (ISC_R_UNEXPECTEDEND);
+ }
+
+ return (mem_tobuffer(target, opt->options, opt->length));
+}
+
+static isc_result_t
+tostruct_opt(ARGS_TOSTRUCT) {
+ dns_rdata_opt_t *opt = target;
+ isc_region_t r;
+
+ REQUIRE(rdata->type == dns_rdatatype_opt);
+ REQUIRE(opt != NULL);
+
+ opt->common.rdclass = rdata->rdclass;
+ opt->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&opt->common, link);
+
+ dns_rdata_toregion(rdata, &r);
+ opt->length = r.length;
+ opt->options = mem_maybedup(mctx, r.base, r.length);
+ if (opt->options == NULL) {
+ return (ISC_R_NOMEMORY);
+ }
+
+ opt->offset = 0;
+ opt->mctx = mctx;
+ return (ISC_R_SUCCESS);
+}
+
+static void
+freestruct_opt(ARGS_FREESTRUCT) {
+ dns_rdata_opt_t *opt = source;
+
+ REQUIRE(opt != NULL);
+ REQUIRE(opt->common.rdtype == dns_rdatatype_opt);
+
+ if (opt->mctx == NULL) {
+ return;
+ }
+
+ if (opt->options != NULL) {
+ isc_mem_free(opt->mctx, opt->options);
+ }
+ opt->mctx = NULL;
+}
+
+static isc_result_t
+additionaldata_opt(ARGS_ADDLDATA) {
+ REQUIRE(rdata->type == dns_rdatatype_opt);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(add);
+ UNUSED(arg);
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+digest_opt(ARGS_DIGEST) {
+ /*
+ * OPT records are not digested.
+ */
+
+ REQUIRE(rdata->type == dns_rdatatype_opt);
+
+ UNUSED(rdata);
+ UNUSED(digest);
+ UNUSED(arg);
+
+ return (ISC_R_NOTIMPLEMENTED);
+}
+
+static bool
+checkowner_opt(ARGS_CHECKOWNER) {
+ REQUIRE(type == dns_rdatatype_opt);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (dns_name_equal(name, dns_rootname));
+}
+
+static bool
+checknames_opt(ARGS_CHECKNAMES) {
+ REQUIRE(rdata->type == dns_rdatatype_opt);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(bad);
+
+ return (true);
+}
+
+static int
+casecompare_opt(ARGS_COMPARE) {
+ return (compare_opt(rdata1, rdata2));
+}
+
+isc_result_t
+dns_rdata_opt_first(dns_rdata_opt_t *opt) {
+ REQUIRE(opt != NULL);
+ REQUIRE(opt->common.rdtype == dns_rdatatype_opt);
+ REQUIRE(opt->options != NULL || opt->length == 0);
+
+ if (opt->length == 0) {
+ return (ISC_R_NOMORE);
+ }
+
+ opt->offset = 0;
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+dns_rdata_opt_next(dns_rdata_opt_t *opt) {
+ isc_region_t r;
+ uint16_t length;
+
+ REQUIRE(opt != NULL);
+ REQUIRE(opt->common.rdtype == dns_rdatatype_opt);
+ REQUIRE(opt->options != NULL && opt->length != 0);
+ REQUIRE(opt->offset < opt->length);
+
+ INSIST(opt->offset + 4 <= opt->length);
+ r.base = opt->options + opt->offset + 2;
+ r.length = opt->length - opt->offset - 2;
+ length = uint16_fromregion(&r);
+ INSIST(opt->offset + 4 + length <= opt->length);
+ opt->offset = opt->offset + 4 + length;
+ if (opt->offset == opt->length) {
+ return (ISC_R_NOMORE);
+ }
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+dns_rdata_opt_current(dns_rdata_opt_t *opt, dns_rdata_opt_opcode_t *opcode) {
+ isc_region_t r;
+
+ REQUIRE(opt != NULL);
+ REQUIRE(opcode != NULL);
+ REQUIRE(opt->common.rdtype == dns_rdatatype_opt);
+ REQUIRE(opt->options != NULL);
+ REQUIRE(opt->offset < opt->length);
+
+ INSIST(opt->offset + 4 <= opt->length);
+ r.base = opt->options + opt->offset;
+ r.length = opt->length - opt->offset;
+
+ opcode->opcode = uint16_fromregion(&r);
+ isc_region_consume(&r, 2);
+ opcode->length = uint16_fromregion(&r);
+ isc_region_consume(&r, 2);
+ opcode->data = r.base;
+ INSIST(opt->offset + 4 + opcode->length <= opt->length);
+
+ return (ISC_R_SUCCESS);
+}
+
+#endif /* RDATA_GENERIC_OPT_41_C */
diff --git a/lib/dns/rdata/generic/opt_41.h b/lib/dns/rdata/generic/opt_41.h
new file mode 100644
index 0000000..2198fde
--- /dev/null
+++ b/lib/dns/rdata/generic/opt_41.h
@@ -0,0 +1,46 @@
+/*
+ * 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
+
+/*!
+ * \brief Per RFC2671 */
+
+typedef struct dns_rdata_opt_opcode {
+ uint16_t opcode;
+ uint16_t length;
+ unsigned char *data;
+} dns_rdata_opt_opcode_t;
+
+typedef struct dns_rdata_opt {
+ dns_rdatacommon_t common;
+ isc_mem_t *mctx;
+ unsigned char *options;
+ uint16_t length;
+ /* private */
+ uint16_t offset;
+} dns_rdata_opt_t;
+
+/*
+ * ISC_LANG_BEGINDECLS and ISC_LANG_ENDDECLS are already done
+ * via rdatastructpre.h and rdatastructsuf.h.
+ */
+
+isc_result_t
+dns_rdata_opt_first(dns_rdata_opt_t *);
+
+isc_result_t
+dns_rdata_opt_next(dns_rdata_opt_t *);
+
+isc_result_t
+dns_rdata_opt_current(dns_rdata_opt_t *, dns_rdata_opt_opcode_t *);
diff --git a/lib/dns/rdata/generic/proforma.c b/lib/dns/rdata/generic/proforma.c
new file mode 100644
index 0000000..6315a6f
--- /dev/null
+++ b/lib/dns/rdata/generic/proforma.c
@@ -0,0 +1,165 @@
+/*
+ * 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_ #_ #_C
+#define RDATA_GENERIC_ #_ #_C
+
+#define RRTYPE_ #_ATTRIBUTES(0)
+
+static isc_result_t fromtext_ #(ARGS_FROMTEXT) {
+ isc_token_t token;
+
+ REQUIRE(type == dns_rdatatype_proforma.c #);
+ REQUIRE(rdclass == #);
+
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ false));
+
+ return (ISC_R_NOTIMPLEMENTED);
+}
+
+static isc_result_t totext_ #(ARGS_TOTEXT) {
+ REQUIRE(rdata->type == dns_rdatatype_proforma.c #);
+ REQUIRE(rdata->rdclass == #);
+ REQUIRE(rdata->length != 0); /* XXX */
+
+ return (ISC_R_NOTIMPLEMENTED);
+}
+
+static isc_result_t fromwire_ #(ARGS_FROMWIRE) {
+ REQUIRE(type == dns_rdatatype_proforma.c #);
+ REQUIRE(rdclass == #);
+
+ /* NONE or GLOBAL14 */
+ dns_decompress_setmethods(dctx, DNS_COMPRESS_NONE);
+
+ return (ISC_R_NOTIMPLEMENTED);
+}
+
+static isc_result_t towire_ #(ARGS_TOWIRE) {
+ REQUIRE(rdata->type == dns_rdatatype_proforma.c #);
+ REQUIRE(rdata->rdclass == #);
+ REQUIRE(rdata->length != 0); /* XXX */
+
+ /* NONE or GLOBAL14 */
+ dns_compress_setmethods(cctx, DNS_COMPRESS_NONE);
+
+ return (ISC_R_NOTIMPLEMENTED);
+}
+
+static int compare_ #(ARGS_COMPARE) {
+ isc_region_t r1;
+ isc_region_t r2;
+
+ REQUIRE(rdata1->type == dns_rdatatype_proforma.crdata2->type);
+ REQUIRE(rdata1->rdclass == rdata2->rdclass);
+ REQUIRE(rdata1->type == dns_rdatatype_proforma.c #);
+ REQUIRE(rdata1->rdclass == #);
+ REQUIRE(rdata1->length != 0); /* XXX */
+ REQUIRE(rdata2->length != 0); /* XXX */
+
+ dns_rdata_toregion(rdata1, &r1);
+ dns_rdata_toregion(rdata2, &r2);
+ return (isc_region_compare(&r1, &r2));
+}
+
+static isc_result_t fromstruct_ #(ARGS_FROMSTRUCT) {
+ dns_rdata_ #_t *# = source;
+
+ REQUIRE(type == dns_rdatatype_proforma.c #);
+ REQUIRE(rdclass == #);
+ REQUIRE(# != NULL);
+ REQUIRE(#->common.rdtype == dns_rdatatype_proforma.ctype);
+ REQUIRE(#->common.rdclass == rdclass);
+
+ return (ISC_R_NOTIMPLEMENTED);
+}
+
+static isc_result_t tostruct_ #(ARGS_TOSTRUCT) {
+ REQUIRE(rdata->type == dns_rdatatype_proforma.c #);
+ REQUIRE(rdata->rdclass == #);
+ REQUIRE(rdata->length != 0); /* XXX */
+
+ return (ISC_R_NOTIMPLEMENTED);
+}
+
+static void freestruct_ #(ARGS_FREESTRUCT) {
+ dns_rdata_ #_t *# = source;
+
+ REQUIRE(# != NULL);
+ REQUIRE(#->common.rdtype == dns_rdatatype_proforma.c #);
+ REQUIRE(#->common.rdclass == #);
+}
+
+static isc_result_t additionaldata_ #(ARGS_ADDLDATA) {
+ REQUIRE(rdata->type == dns_rdatatype_proforma.c #);
+ REQUIRE(rdata->rdclass == #);
+
+ UNUSED(owner);
+ UNUSED(add);
+ UNUSED(arg);
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t digest_ #(ARGS_DIGEST) {
+ isc_region_t r;
+
+ REQUIRE(rdata->type == dns_rdatatype_proforma.c #);
+ REQUIRE(rdata->rdclass == #);
+
+ dns_rdata_toregion(rdata, &r);
+
+ return ((digest)(arg, &r));
+}
+
+static bool checkowner_ #(ARGS_CHECKOWNER) {
+ REQUIRE(type == dns_rdatatype_proforma.c #);
+ REQUIRE(rdclass == #);
+
+ UNUSED(name);
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (true);
+}
+
+static bool checknames_ #(ARGS_CHECKNAMES) {
+ REQUIRE(rdata->type == dns_rdatatype_proforma.c #);
+ REQUIRE(rdata->rdclass == #);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(bad);
+
+ return (true);
+}
+
+static int casecompare_ #(ARGS_COMPARE) {
+ isc_region_t r1;
+ isc_region_t r2;
+
+ REQUIRE(rdata1->type == dns_rdatatype_proforma.crdata2->type);
+ REQUIRE(rdata1->rdclass == rdata2->rdclass);
+ REQUIRE(rdata1->type == dns_rdatatype_proforma.c #);
+ REQUIRE(rdata1->rdclass == #);
+ REQUIRE(rdata1->length != 0); /* XXX */
+ REQUIRE(rdata2->length != 0); /* XXX */
+
+ dns_rdata_toregion(rdata1, &r1);
+ dns_rdata_toregion(rdata2, &r2);
+ return (isc_region_compare(&r1, &r2));
+}
+
+#endif /* RDATA_GENERIC_#_#_C */
diff --git a/lib/dns/rdata/generic/proforma.h b/lib/dns/rdata/generic/proforma.h
new file mode 100644
index 0000000..03962d1
--- /dev/null
+++ b/lib/dns/rdata/generic/proforma.h
@@ -0,0 +1,22 @@
+/*
+ * 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_ #{
+ dns_rdatacommon_t common;
+ isc_mem_t *mctx; /* if required */
+ /* type & class specific elements */
+}
+dns_rdata_ #_t;
diff --git a/lib/dns/rdata/generic/ptr_12.c b/lib/dns/rdata/generic/ptr_12.c
new file mode 100644
index 0000000..41e2e8e
--- /dev/null
+++ b/lib/dns/rdata/generic/ptr_12.c
@@ -0,0 +1,279 @@
+/*
+ * 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_PTR_12_C
+#define RDATA_GENERIC_PTR_12_C
+
+#define RRTYPE_PTR_ATTRIBUTES (0)
+
+static isc_result_t
+fromtext_ptr(ARGS_FROMTEXT) {
+ isc_token_t token;
+ dns_name_t name;
+ isc_buffer_t buffer;
+
+ REQUIRE(type == dns_rdatatype_ptr);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(callbacks);
+
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ false));
+
+ dns_name_init(&name, NULL);
+ buffer_fromregion(&buffer, &token.value.as_region);
+ if (origin == NULL) {
+ origin = dns_rootname;
+ }
+ RETTOK(dns_name_fromtext(&name, &buffer, origin, options, target));
+ if (rdclass == dns_rdataclass_in &&
+ (options & DNS_RDATA_CHECKNAMES) != 0 &&
+ (options & DNS_RDATA_CHECKREVERSE) != 0)
+ {
+ bool ok;
+ 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_ptr(ARGS_TOTEXT) {
+ isc_region_t region;
+ dns_name_t name;
+ dns_name_t prefix;
+ bool sub;
+
+ REQUIRE(rdata->type == dns_rdatatype_ptr);
+ REQUIRE(rdata->length != 0);
+
+ dns_name_init(&name, NULL);
+ dns_name_init(&prefix, NULL);
+
+ dns_rdata_toregion(rdata, &region);
+ dns_name_fromregion(&name, &region);
+
+ sub = name_prefix(&name, tctx->origin, &prefix);
+
+ return (dns_name_totext(&prefix, sub, target));
+}
+
+static isc_result_t
+fromwire_ptr(ARGS_FROMWIRE) {
+ dns_name_t name;
+
+ REQUIRE(type == dns_rdatatype_ptr);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ dns_decompress_setmethods(dctx, DNS_COMPRESS_GLOBAL14);
+
+ dns_name_init(&name, NULL);
+ return (dns_name_fromwire(&name, source, dctx, options, target));
+}
+
+static isc_result_t
+towire_ptr(ARGS_TOWIRE) {
+ dns_name_t name;
+ dns_offsets_t offsets;
+ isc_region_t region;
+
+ REQUIRE(rdata->type == dns_rdatatype_ptr);
+ REQUIRE(rdata->length != 0);
+
+ dns_compress_setmethods(cctx, DNS_COMPRESS_GLOBAL14);
+
+ dns_name_init(&name, offsets);
+ dns_rdata_toregion(rdata, &region);
+ dns_name_fromregion(&name, &region);
+
+ return (dns_name_towire(&name, cctx, target));
+}
+
+static int
+compare_ptr(ARGS_COMPARE) {
+ dns_name_t name1;
+ dns_name_t name2;
+ isc_region_t region1;
+ isc_region_t region2;
+
+ REQUIRE(rdata1->type == rdata2->type);
+ REQUIRE(rdata1->rdclass == rdata2->rdclass);
+ REQUIRE(rdata1->type == dns_rdatatype_ptr);
+ REQUIRE(rdata1->length != 0);
+ REQUIRE(rdata2->length != 0);
+
+ dns_name_init(&name1, NULL);
+ dns_name_init(&name2, NULL);
+
+ dns_rdata_toregion(rdata1, &region1);
+ dns_rdata_toregion(rdata2, &region2);
+
+ dns_name_fromregion(&name1, &region1);
+ dns_name_fromregion(&name2, &region2);
+
+ return (dns_name_rdatacompare(&name1, &name2));
+}
+
+static isc_result_t
+fromstruct_ptr(ARGS_FROMSTRUCT) {
+ dns_rdata_ptr_t *ptr = source;
+ isc_region_t region;
+
+ REQUIRE(type == dns_rdatatype_ptr);
+ REQUIRE(ptr != NULL);
+ REQUIRE(ptr->common.rdtype == type);
+ REQUIRE(ptr->common.rdclass == rdclass);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ dns_name_toregion(&ptr->ptr, &region);
+ return (isc_buffer_copyregion(target, &region));
+}
+
+static isc_result_t
+tostruct_ptr(ARGS_TOSTRUCT) {
+ isc_region_t region;
+ dns_rdata_ptr_t *ptr = target;
+ dns_name_t name;
+
+ REQUIRE(rdata->type == dns_rdatatype_ptr);
+ REQUIRE(ptr != NULL);
+ REQUIRE(rdata->length != 0);
+
+ ptr->common.rdclass = rdata->rdclass;
+ ptr->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&ptr->common, link);
+
+ dns_name_init(&name, NULL);
+ dns_rdata_toregion(rdata, &region);
+ dns_name_fromregion(&name, &region);
+ dns_name_init(&ptr->ptr, NULL);
+ name_duporclone(&name, mctx, &ptr->ptr);
+ ptr->mctx = mctx;
+ return (ISC_R_SUCCESS);
+}
+
+static void
+freestruct_ptr(ARGS_FREESTRUCT) {
+ dns_rdata_ptr_t *ptr = source;
+
+ REQUIRE(ptr != NULL);
+ REQUIRE(ptr->common.rdtype == dns_rdatatype_ptr);
+
+ if (ptr->mctx == NULL) {
+ return;
+ }
+
+ dns_name_free(&ptr->ptr, ptr->mctx);
+ ptr->mctx = NULL;
+}
+
+static isc_result_t
+additionaldata_ptr(ARGS_ADDLDATA) {
+ REQUIRE(rdata->type == dns_rdatatype_ptr);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(add);
+ UNUSED(arg);
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+digest_ptr(ARGS_DIGEST) {
+ isc_region_t r;
+ dns_name_t name;
+
+ REQUIRE(rdata->type == dns_rdatatype_ptr);
+
+ dns_rdata_toregion(rdata, &r);
+ dns_name_init(&name, NULL);
+ dns_name_fromregion(&name, &r);
+
+ return (dns_name_digest(&name, digest, arg));
+}
+
+static bool
+checkowner_ptr(ARGS_CHECKOWNER) {
+ REQUIRE(type == dns_rdatatype_ptr);
+
+ UNUSED(name);
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (true);
+}
+
+static unsigned char ip6_arpa_data[] = "\003IP6\004ARPA";
+static unsigned char ip6_arpa_offsets[] = { 0, 4, 9 };
+static const dns_name_t ip6_arpa = DNS_NAME_INITABSOLUTE(ip6_arpa_data,
+ ip6_arpa_offsets);
+
+static unsigned char ip6_int_data[] = "\003IP6\003INT";
+static unsigned char ip6_int_offsets[] = { 0, 4, 8 };
+static const dns_name_t ip6_int = DNS_NAME_INITABSOLUTE(ip6_int_data,
+ ip6_int_offsets);
+
+static unsigned char in_addr_arpa_data[] = "\007IN-ADDR\004ARPA";
+static unsigned char in_addr_arpa_offsets[] = { 0, 8, 13 };
+static const dns_name_t in_addr_arpa =
+ DNS_NAME_INITABSOLUTE(in_addr_arpa_data, in_addr_arpa_offsets);
+
+static bool
+checknames_ptr(ARGS_CHECKNAMES) {
+ isc_region_t region;
+ dns_name_t name;
+
+ REQUIRE(rdata->type == dns_rdatatype_ptr);
+
+ if (rdata->rdclass != dns_rdataclass_in) {
+ return (true);
+ }
+
+ if (dns_name_isdnssd(owner)) {
+ return (true);
+ }
+
+ if (dns_name_issubdomain(owner, &in_addr_arpa) ||
+ dns_name_issubdomain(owner, &ip6_arpa) ||
+ dns_name_issubdomain(owner, &ip6_int))
+ {
+ dns_rdata_toregion(rdata, &region);
+ dns_name_init(&name, NULL);
+ dns_name_fromregion(&name, &region);
+ if (!dns_name_ishostname(&name, false)) {
+ if (bad != NULL) {
+ dns_name_clone(&name, bad);
+ }
+ return (false);
+ }
+ }
+ return (true);
+}
+
+static int
+casecompare_ptr(ARGS_COMPARE) {
+ return (compare_ptr(rdata1, rdata2));
+}
+#endif /* RDATA_GENERIC_PTR_12_C */
diff --git a/lib/dns/rdata/generic/ptr_12.h b/lib/dns/rdata/generic/ptr_12.h
new file mode 100644
index 0000000..8951eb3
--- /dev/null
+++ b/lib/dns/rdata/generic/ptr_12.h
@@ -0,0 +1,21 @@
+/*
+ * 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_ptr {
+ dns_rdatacommon_t common;
+ isc_mem_t *mctx;
+ dns_name_t ptr;
+} dns_rdata_ptr_t;
diff --git a/lib/dns/rdata/generic/rkey_57.c b/lib/dns/rdata/generic/rkey_57.c
new file mode 100644
index 0000000..20cd0f0
--- /dev/null
+++ b/lib/dns/rdata/generic/rkey_57.c
@@ -0,0 +1,161 @@
+/*
+ * 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_RKEY_57_C
+#define RDATA_GENERIC_RKEY_57_C
+
+#define RRTYPE_RKEY_ATTRIBUTES 0
+
+static isc_result_t
+fromtext_rkey(ARGS_FROMTEXT) {
+ REQUIRE(type == dns_rdatatype_rkey);
+
+ return (generic_fromtext_key(CALL_FROMTEXT));
+}
+
+static isc_result_t
+totext_rkey(ARGS_TOTEXT) {
+ REQUIRE(rdata != NULL);
+ REQUIRE(rdata->type == dns_rdatatype_rkey);
+
+ return (generic_totext_key(CALL_TOTEXT));
+}
+
+static isc_result_t
+fromwire_rkey(ARGS_FROMWIRE) {
+ REQUIRE(type == dns_rdatatype_rkey);
+
+ return (generic_fromwire_key(CALL_FROMWIRE));
+}
+
+static isc_result_t
+towire_rkey(ARGS_TOWIRE) {
+ isc_region_t sr;
+
+ REQUIRE(rdata != NULL);
+ REQUIRE(rdata->type == dns_rdatatype_rkey);
+ REQUIRE(rdata->length != 0);
+
+ UNUSED(cctx);
+
+ dns_rdata_toregion(rdata, &sr);
+ return (mem_tobuffer(target, sr.base, sr.length));
+}
+
+static int
+compare_rkey(ARGS_COMPARE) {
+ isc_region_t r1;
+ isc_region_t r2;
+
+ REQUIRE(rdata1 != NULL);
+ REQUIRE(rdata2 != NULL);
+ REQUIRE(rdata1->type == rdata2->type);
+ REQUIRE(rdata1->rdclass == rdata2->rdclass);
+ REQUIRE(rdata1->type == dns_rdatatype_rkey);
+ REQUIRE(rdata1->length != 0);
+ REQUIRE(rdata2->length != 0);
+
+ dns_rdata_toregion(rdata1, &r1);
+ dns_rdata_toregion(rdata2, &r2);
+ return (isc_region_compare(&r1, &r2));
+}
+
+static isc_result_t
+fromstruct_rkey(ARGS_FROMSTRUCT) {
+ REQUIRE(type == dns_rdatatype_rkey);
+
+ return (generic_fromstruct_key(CALL_FROMSTRUCT));
+}
+
+static isc_result_t
+tostruct_rkey(ARGS_TOSTRUCT) {
+ dns_rdata_rkey_t *rkey = target;
+
+ REQUIRE(rkey != NULL);
+ REQUIRE(rdata != NULL);
+ REQUIRE(rdata->type == dns_rdatatype_rkey);
+
+ rkey->common.rdclass = rdata->rdclass;
+ rkey->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&rkey->common, link);
+
+ return (generic_tostruct_key(CALL_TOSTRUCT));
+}
+
+static void
+freestruct_rkey(ARGS_FREESTRUCT) {
+ dns_rdata_rkey_t *rkey = (dns_rdata_rkey_t *)source;
+
+ REQUIRE(rkey != NULL);
+ REQUIRE(rkey->common.rdtype == dns_rdatatype_rkey);
+
+ generic_freestruct_key(source);
+}
+
+static isc_result_t
+additionaldata_rkey(ARGS_ADDLDATA) {
+ REQUIRE(rdata->type == dns_rdatatype_rkey);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(add);
+ UNUSED(arg);
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+digest_rkey(ARGS_DIGEST) {
+ isc_region_t r;
+
+ REQUIRE(rdata != NULL);
+ REQUIRE(rdata->type == dns_rdatatype_rkey);
+
+ dns_rdata_toregion(rdata, &r);
+
+ return ((digest)(arg, &r));
+}
+
+static bool
+checkowner_rkey(ARGS_CHECKOWNER) {
+ REQUIRE(type == dns_rdatatype_rkey);
+
+ UNUSED(name);
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (true);
+}
+
+static bool
+checknames_rkey(ARGS_CHECKNAMES) {
+ REQUIRE(rdata != NULL);
+ REQUIRE(rdata->type == dns_rdatatype_rkey);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(bad);
+
+ return (true);
+}
+
+static int
+casecompare_rkey(ARGS_COMPARE) {
+ /*
+ * Treat ALG 253 (private DNS) subtype name case sensitively.
+ */
+ return (compare_rkey(rdata1, rdata2));
+}
+
+#endif /* RDATA_GENERIC_RKEY_57_C */
diff --git a/lib/dns/rdata/generic/rkey_57.h b/lib/dns/rdata/generic/rkey_57.h
new file mode 100644
index 0000000..3538be0
--- /dev/null
+++ b/lib/dns/rdata/generic/rkey_57.h
@@ -0,0 +1,16 @@
+/*
+ * 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_key dns_rdata_rkey_t;
diff --git a/lib/dns/rdata/generic/rp_17.c b/lib/dns/rdata/generic/rp_17.c
new file mode 100644
index 0000000..62080c6
--- /dev/null
+++ b/lib/dns/rdata/generic/rp_17.c
@@ -0,0 +1,310 @@
+/*
+ * 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.
+ */
+
+/* RFC1183 */
+
+#ifndef RDATA_GENERIC_RP_17_C
+#define RDATA_GENERIC_RP_17_C
+
+#define RRTYPE_RP_ATTRIBUTES (0)
+
+static isc_result_t
+fromtext_rp(ARGS_FROMTEXT) {
+ isc_token_t token;
+ dns_name_t name;
+ isc_buffer_t buffer;
+ int i;
+ bool ok;
+
+ REQUIRE(type == dns_rdatatype_rp);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(callbacks);
+
+ if (origin == NULL) {
+ origin = dns_rootname;
+ }
+
+ for (i = 0; i < 2; i++) {
+ RETERR(isc_lex_getmastertoken(lexer, &token,
+ isc_tokentype_string, false));
+ dns_name_init(&name, NULL);
+ buffer_fromregion(&buffer, &token.value.as_region);
+ RETTOK(dns_name_fromtext(&name, &buffer, origin, options,
+ target));
+ ok = true;
+ if ((options & DNS_RDATA_CHECKNAMES) != 0 && i == 0) {
+ ok = dns_name_ismailbox(&name);
+ }
+ 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_rp(ARGS_TOTEXT) {
+ isc_region_t region;
+ dns_name_t rmail;
+ dns_name_t email;
+ dns_name_t prefix;
+ bool sub;
+
+ REQUIRE(rdata->type == dns_rdatatype_rp);
+ REQUIRE(rdata->length != 0);
+
+ dns_name_init(&rmail, NULL);
+ dns_name_init(&email, NULL);
+ dns_name_init(&prefix, NULL);
+
+ dns_rdata_toregion(rdata, &region);
+
+ dns_name_fromregion(&rmail, &region);
+ isc_region_consume(&region, rmail.length);
+
+ dns_name_fromregion(&email, &region);
+ isc_region_consume(&region, email.length);
+
+ sub = name_prefix(&rmail, tctx->origin, &prefix);
+ RETERR(dns_name_totext(&prefix, sub, target));
+
+ RETERR(str_totext(" ", target));
+
+ sub = name_prefix(&email, tctx->origin, &prefix);
+ return (dns_name_totext(&prefix, sub, target));
+}
+
+static isc_result_t
+fromwire_rp(ARGS_FROMWIRE) {
+ dns_name_t rmail;
+ dns_name_t email;
+
+ REQUIRE(type == dns_rdatatype_rp);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ dns_decompress_setmethods(dctx, DNS_COMPRESS_NONE);
+
+ dns_name_init(&rmail, NULL);
+ dns_name_init(&email, NULL);
+
+ RETERR(dns_name_fromwire(&rmail, source, dctx, options, target));
+ return (dns_name_fromwire(&email, source, dctx, options, target));
+}
+
+static isc_result_t
+towire_rp(ARGS_TOWIRE) {
+ isc_region_t region;
+ dns_name_t rmail;
+ dns_name_t email;
+ dns_offsets_t roffsets;
+ dns_offsets_t eoffsets;
+
+ REQUIRE(rdata->type == dns_rdatatype_rp);
+ REQUIRE(rdata->length != 0);
+
+ dns_compress_setmethods(cctx, DNS_COMPRESS_NONE);
+ dns_name_init(&rmail, roffsets);
+ dns_name_init(&email, eoffsets);
+
+ dns_rdata_toregion(rdata, &region);
+
+ dns_name_fromregion(&rmail, &region);
+ isc_region_consume(&region, rmail.length);
+
+ RETERR(dns_name_towire(&rmail, cctx, target));
+
+ dns_name_fromregion(&rmail, &region);
+ isc_region_consume(&region, rmail.length);
+
+ return (dns_name_towire(&rmail, cctx, target));
+}
+
+static int
+compare_rp(ARGS_COMPARE) {
+ isc_region_t region1;
+ isc_region_t region2;
+ dns_name_t name1;
+ dns_name_t name2;
+ int order;
+
+ REQUIRE(rdata1->type == rdata2->type);
+ REQUIRE(rdata1->rdclass == rdata2->rdclass);
+ REQUIRE(rdata1->type == dns_rdatatype_rp);
+ REQUIRE(rdata1->length != 0);
+ REQUIRE(rdata2->length != 0);
+
+ dns_name_init(&name1, NULL);
+ dns_name_init(&name2, NULL);
+
+ dns_rdata_toregion(rdata1, &region1);
+ dns_rdata_toregion(rdata2, &region2);
+
+ dns_name_fromregion(&name1, &region1);
+ dns_name_fromregion(&name2, &region2);
+
+ order = dns_name_rdatacompare(&name1, &name2);
+ if (order != 0) {
+ return (order);
+ }
+
+ isc_region_consume(&region1, name_length(&name1));
+ isc_region_consume(&region2, name_length(&name2));
+
+ dns_name_init(&name1, NULL);
+ dns_name_init(&name2, NULL);
+
+ dns_name_fromregion(&name1, &region1);
+ dns_name_fromregion(&name2, &region2);
+
+ return (dns_name_rdatacompare(&name1, &name2));
+}
+
+static isc_result_t
+fromstruct_rp(ARGS_FROMSTRUCT) {
+ dns_rdata_rp_t *rp = source;
+ isc_region_t region;
+
+ REQUIRE(type == dns_rdatatype_rp);
+ REQUIRE(rp != NULL);
+ REQUIRE(rp->common.rdtype == type);
+ REQUIRE(rp->common.rdclass == rdclass);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ dns_name_toregion(&rp->mail, &region);
+ RETERR(isc_buffer_copyregion(target, &region));
+ dns_name_toregion(&rp->text, &region);
+ return (isc_buffer_copyregion(target, &region));
+}
+
+static isc_result_t
+tostruct_rp(ARGS_TOSTRUCT) {
+ isc_region_t region;
+ dns_rdata_rp_t *rp = target;
+ dns_name_t name;
+
+ REQUIRE(rdata->type == dns_rdatatype_rp);
+ REQUIRE(rp != NULL);
+ REQUIRE(rdata->length != 0);
+
+ rp->common.rdclass = rdata->rdclass;
+ rp->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&rp->common, link);
+
+ dns_name_init(&name, NULL);
+ dns_rdata_toregion(rdata, &region);
+ dns_name_fromregion(&name, &region);
+ dns_name_init(&rp->mail, NULL);
+ name_duporclone(&name, mctx, &rp->mail);
+ isc_region_consume(&region, name_length(&name));
+ dns_name_fromregion(&name, &region);
+ dns_name_init(&rp->text, NULL);
+ name_duporclone(&name, mctx, &rp->text);
+ rp->mctx = mctx;
+ return (ISC_R_SUCCESS);
+}
+
+static void
+freestruct_rp(ARGS_FREESTRUCT) {
+ dns_rdata_rp_t *rp = source;
+
+ REQUIRE(rp != NULL);
+ REQUIRE(rp->common.rdtype == dns_rdatatype_rp);
+
+ if (rp->mctx == NULL) {
+ return;
+ }
+
+ dns_name_free(&rp->mail, rp->mctx);
+ dns_name_free(&rp->text, rp->mctx);
+ rp->mctx = NULL;
+}
+
+static isc_result_t
+additionaldata_rp(ARGS_ADDLDATA) {
+ REQUIRE(rdata->type == dns_rdatatype_rp);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(add);
+ UNUSED(arg);
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+digest_rp(ARGS_DIGEST) {
+ isc_region_t r;
+ dns_name_t name;
+
+ REQUIRE(rdata->type == dns_rdatatype_rp);
+
+ dns_rdata_toregion(rdata, &r);
+ dns_name_init(&name, NULL);
+
+ dns_name_fromregion(&name, &r);
+ RETERR(dns_name_digest(&name, digest, arg));
+ isc_region_consume(&r, name_length(&name));
+
+ dns_name_init(&name, NULL);
+ dns_name_fromregion(&name, &r);
+
+ return (dns_name_digest(&name, digest, arg));
+}
+
+static bool
+checkowner_rp(ARGS_CHECKOWNER) {
+ REQUIRE(type == dns_rdatatype_rp);
+
+ UNUSED(name);
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (true);
+}
+
+static bool
+checknames_rp(ARGS_CHECKNAMES) {
+ isc_region_t region;
+ dns_name_t name;
+
+ REQUIRE(rdata->type == dns_rdatatype_rp);
+
+ UNUSED(owner);
+
+ dns_rdata_toregion(rdata, &region);
+ dns_name_init(&name, NULL);
+ dns_name_fromregion(&name, &region);
+ if (!dns_name_ismailbox(&name)) {
+ if (bad != NULL) {
+ dns_name_clone(&name, bad);
+ }
+ return (false);
+ }
+ return (true);
+}
+
+static int
+casecompare_rp(ARGS_COMPARE) {
+ return (compare_rp(rdata1, rdata2));
+}
+#endif /* RDATA_GENERIC_RP_17_C */
diff --git a/lib/dns/rdata/generic/rp_17.h b/lib/dns/rdata/generic/rp_17.h
new file mode 100644
index 0000000..d27ffb9
--- /dev/null
+++ b/lib/dns/rdata/generic/rp_17.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
+
+/*!
+ * \brief Per RFC1183 */
+
+typedef struct dns_rdata_rp {
+ dns_rdatacommon_t common;
+ isc_mem_t *mctx;
+ dns_name_t mail;
+ dns_name_t text;
+} dns_rdata_rp_t;
diff --git a/lib/dns/rdata/generic/rrsig_46.c b/lib/dns/rdata/generic/rrsig_46.c
new file mode 100644
index 0000000..553c9cf
--- /dev/null
+++ b/lib/dns/rdata/generic/rrsig_46.c
@@ -0,0 +1,640 @@
+/*
+ * 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.
+ */
+
+/* RFC2535 */
+
+#ifndef RDATA_GENERIC_RRSIG_46_C
+#define RDATA_GENERIC_RRSIG_46_C
+
+#define RRTYPE_RRSIG_ATTRIBUTES \
+ (DNS_RDATATYPEATTR_DNSSEC | DNS_RDATATYPEATTR_ZONECUTAUTH | \
+ DNS_RDATATYPEATTR_ATCNAME)
+
+static isc_result_t
+fromtext_rrsig(ARGS_FROMTEXT) {
+ isc_token_t token;
+ unsigned char c;
+ long i;
+ dns_rdatatype_t covered;
+ char *e;
+ isc_result_t result;
+ dns_name_t name;
+ isc_buffer_t buffer;
+ uint32_t time_signed, time_expire;
+
+ REQUIRE(type == dns_rdatatype_rrsig);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(callbacks);
+
+ /*
+ * Type covered.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ false));
+ result = dns_rdatatype_fromtext(&covered, &token.value.as_textregion);
+ if (result != ISC_R_SUCCESS && result != ISC_R_NOTIMPLEMENTED) {
+ i = strtol(DNS_AS_STR(token), &e, 10);
+ if (i < 0 || i > 65535) {
+ RETTOK(ISC_R_RANGE);
+ }
+ if (*e != 0) {
+ RETTOK(result);
+ }
+ covered = (dns_rdatatype_t)i;
+ }
+ RETERR(uint16_tobuffer(covered, target));
+
+ /*
+ * Algorithm.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ false));
+ RETTOK(dns_secalg_fromtext(&c, &token.value.as_textregion));
+ RETERR(mem_tobuffer(target, &c, 1));
+
+ /*
+ * Labels.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
+ false));
+ if (token.value.as_ulong > 0xffU) {
+ RETTOK(ISC_R_RANGE);
+ }
+ c = (unsigned char)token.value.as_ulong;
+ RETERR(mem_tobuffer(target, &c, 1));
+
+ /*
+ * Original ttl.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
+ false));
+ RETERR(uint32_tobuffer(token.value.as_ulong, target));
+
+ /*
+ * Signature expiration.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ false));
+ if (strlen(DNS_AS_STR(token)) <= 10U && *DNS_AS_STR(token) != '-' &&
+ *DNS_AS_STR(token) != '+')
+ {
+ char *end;
+ unsigned long u;
+ uint64_t u64;
+
+ u64 = u = strtoul(DNS_AS_STR(token), &end, 10);
+ if (u == ULONG_MAX || *end != 0) {
+ RETTOK(DNS_R_SYNTAX);
+ }
+ if (u64 > 0xffffffffUL) {
+ RETTOK(ISC_R_RANGE);
+ }
+ time_expire = u;
+ } else {
+ RETTOK(dns_time32_fromtext(DNS_AS_STR(token), &time_expire));
+ }
+ RETERR(uint32_tobuffer(time_expire, target));
+
+ /*
+ * Time signed.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ false));
+ if (strlen(DNS_AS_STR(token)) <= 10U && *DNS_AS_STR(token) != '-' &&
+ *DNS_AS_STR(token) != '+')
+ {
+ char *end;
+ unsigned long u;
+ uint64_t u64;
+
+ u64 = u = strtoul(DNS_AS_STR(token), &end, 10);
+ if (u == ULONG_MAX || *end != 0) {
+ RETTOK(DNS_R_SYNTAX);
+ }
+ if (u64 > 0xffffffffUL) {
+ RETTOK(ISC_R_RANGE);
+ }
+ time_signed = u;
+ } else {
+ RETTOK(dns_time32_fromtext(DNS_AS_STR(token), &time_signed));
+ }
+ RETERR(uint32_tobuffer(time_signed, target));
+
+ /*
+ * Key footprint.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
+ false));
+ RETERR(uint16_tobuffer(token.value.as_ulong, target));
+
+ /*
+ * Signer.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ false));
+ dns_name_init(&name, NULL);
+ buffer_fromregion(&buffer, &token.value.as_region);
+ if (origin == NULL) {
+ origin = dns_rootname;
+ }
+ RETTOK(dns_name_fromtext(&name, &buffer, origin, options, target));
+
+ /*
+ * Sig.
+ */
+ return (isc_base64_tobuffer(lexer, target, -2));
+}
+
+static isc_result_t
+totext_rrsig(ARGS_TOTEXT) {
+ isc_region_t sr;
+ char buf[sizeof("4294967295")]; /* Also TYPE65000. */
+ dns_rdatatype_t covered;
+ unsigned long ttl;
+ unsigned long when;
+ unsigned long exp;
+ unsigned long foot;
+ dns_name_t name;
+
+ REQUIRE(rdata->type == dns_rdatatype_rrsig);
+ REQUIRE(rdata->length != 0);
+
+ dns_rdata_toregion(rdata, &sr);
+
+ /*
+ * Type covered.
+ */
+ covered = uint16_fromregion(&sr);
+ isc_region_consume(&sr, 2);
+ /*
+ * XXXAG We should have something like dns_rdatatype_isknown()
+ * that does the right thing with type 0.
+ */
+ if (dns_rdatatype_isknown(covered) && covered != 0) {
+ RETERR(dns_rdatatype_totext(covered, target));
+ } else {
+ snprintf(buf, sizeof(buf), "TYPE%u", covered);
+ RETERR(str_totext(buf, target));
+ }
+ RETERR(str_totext(" ", target));
+
+ /*
+ * Algorithm.
+ */
+ snprintf(buf, sizeof(buf), "%u", sr.base[0]);
+ isc_region_consume(&sr, 1);
+ RETERR(str_totext(buf, target));
+ RETERR(str_totext(" ", target));
+
+ /*
+ * Labels.
+ */
+ snprintf(buf, sizeof(buf), "%u", sr.base[0]);
+ isc_region_consume(&sr, 1);
+ RETERR(str_totext(buf, target));
+ RETERR(str_totext(" ", target));
+
+ /*
+ * Ttl.
+ */
+ ttl = uint32_fromregion(&sr);
+ isc_region_consume(&sr, 4);
+ snprintf(buf, sizeof(buf), "%lu", ttl);
+ RETERR(str_totext(buf, target));
+
+ if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) {
+ RETERR(str_totext(" (", target));
+ }
+ RETERR(str_totext(tctx->linebreak, target));
+
+ /*
+ * Sig exp.
+ */
+ exp = uint32_fromregion(&sr);
+ isc_region_consume(&sr, 4);
+ RETERR(dns_time32_totext(exp, target));
+ RETERR(str_totext(" ", target));
+
+ /*
+ * Time signed.
+ */
+ when = uint32_fromregion(&sr);
+ isc_region_consume(&sr, 4);
+ RETERR(dns_time32_totext(when, target));
+ RETERR(str_totext(" ", target));
+
+ /*
+ * Footprint.
+ */
+ foot = uint16_fromregion(&sr);
+ isc_region_consume(&sr, 2);
+ snprintf(buf, sizeof(buf), "%lu", foot);
+ RETERR(str_totext(buf, target));
+ RETERR(str_totext(" ", target));
+
+ /*
+ * Signer.
+ */
+ dns_name_init(&name, NULL);
+ dns_name_fromregion(&name, &sr);
+ isc_region_consume(&sr, name_length(&name));
+ RETERR(dns_name_totext(&name, false, target));
+
+ /*
+ * Sig.
+ */
+ RETERR(str_totext(tctx->linebreak, target));
+ if ((tctx->flags & DNS_STYLEFLAG_NOCRYPTO) == 0) {
+ if (tctx->width == 0) { /* No splitting */
+ RETERR(isc_base64_totext(&sr, 60, "", target));
+ } else {
+ RETERR(isc_base64_totext(&sr, tctx->width - 2,
+ tctx->linebreak, target));
+ }
+ } else {
+ RETERR(str_totext("[omitted]", target));
+ }
+
+ if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) {
+ RETERR(str_totext(" )", target));
+ }
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+fromwire_rrsig(ARGS_FROMWIRE) {
+ isc_region_t sr;
+ dns_name_t name;
+
+ REQUIRE(type == dns_rdatatype_rrsig);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ dns_decompress_setmethods(dctx, DNS_COMPRESS_NONE);
+
+ isc_buffer_activeregion(source, &sr);
+ /*
+ * type covered: 2
+ * algorithm: 1
+ * labels: 1
+ * original ttl: 4
+ * signature expiration: 4
+ * time signed: 4
+ * key footprint: 2
+ */
+ if (sr.length < 18) {
+ return (ISC_R_UNEXPECTEDEND);
+ }
+
+ isc_buffer_forward(source, 18);
+ RETERR(mem_tobuffer(target, sr.base, 18));
+
+ /*
+ * Signer.
+ */
+ dns_name_init(&name, NULL);
+ RETERR(dns_name_fromwire(&name, source, dctx, options, target));
+
+ /*
+ * Sig.
+ */
+ isc_buffer_activeregion(source, &sr);
+ if (sr.length < 1) {
+ return (DNS_R_FORMERR);
+ }
+ isc_buffer_forward(source, sr.length);
+ return (mem_tobuffer(target, sr.base, sr.length));
+}
+
+static isc_result_t
+towire_rrsig(ARGS_TOWIRE) {
+ isc_region_t sr;
+ dns_name_t name;
+ dns_offsets_t offsets;
+
+ REQUIRE(rdata->type == dns_rdatatype_rrsig);
+ REQUIRE(rdata->length != 0);
+
+ dns_compress_setmethods(cctx, DNS_COMPRESS_NONE);
+ dns_rdata_toregion(rdata, &sr);
+ /*
+ * type covered: 2
+ * algorithm: 1
+ * labels: 1
+ * original ttl: 4
+ * signature expiration: 4
+ * time signed: 4
+ * key footprint: 2
+ */
+ RETERR(mem_tobuffer(target, sr.base, 18));
+ isc_region_consume(&sr, 18);
+
+ /*
+ * Signer.
+ */
+ dns_name_init(&name, offsets);
+ dns_name_fromregion(&name, &sr);
+ isc_region_consume(&sr, name_length(&name));
+ RETERR(dns_name_towire(&name, cctx, target));
+
+ /*
+ * Signature.
+ */
+ return (mem_tobuffer(target, sr.base, sr.length));
+}
+
+static int
+compare_rrsig(ARGS_COMPARE) {
+ isc_region_t r1;
+ isc_region_t r2;
+
+ REQUIRE(rdata1->type == rdata2->type);
+ REQUIRE(rdata1->rdclass == rdata2->rdclass);
+ REQUIRE(rdata1->type == dns_rdatatype_rrsig);
+ REQUIRE(rdata1->length != 0);
+ REQUIRE(rdata2->length != 0);
+
+ dns_rdata_toregion(rdata1, &r1);
+ dns_rdata_toregion(rdata2, &r2);
+ return (isc_region_compare(&r1, &r2));
+}
+
+static isc_result_t
+fromstruct_rrsig(ARGS_FROMSTRUCT) {
+ dns_rdata_rrsig_t *sig = source;
+
+ REQUIRE(type == dns_rdatatype_rrsig);
+ REQUIRE(sig != NULL);
+ REQUIRE(sig->common.rdtype == type);
+ REQUIRE(sig->common.rdclass == rdclass);
+ REQUIRE(sig->signature != NULL || sig->siglen == 0);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ /*
+ * Type covered.
+ */
+ RETERR(uint16_tobuffer(sig->covered, target));
+
+ /*
+ * Algorithm.
+ */
+ RETERR(uint8_tobuffer(sig->algorithm, target));
+
+ /*
+ * Labels.
+ */
+ RETERR(uint8_tobuffer(sig->labels, target));
+
+ /*
+ * Original TTL.
+ */
+ RETERR(uint32_tobuffer(sig->originalttl, target));
+
+ /*
+ * Expire time.
+ */
+ RETERR(uint32_tobuffer(sig->timeexpire, target));
+
+ /*
+ * Time signed.
+ */
+ RETERR(uint32_tobuffer(sig->timesigned, target));
+
+ /*
+ * Key ID.
+ */
+ RETERR(uint16_tobuffer(sig->keyid, target));
+
+ /*
+ * Signer name.
+ */
+ RETERR(name_tobuffer(&sig->signer, target));
+
+ /*
+ * Signature.
+ */
+ return (mem_tobuffer(target, sig->signature, sig->siglen));
+}
+
+static isc_result_t
+tostruct_rrsig(ARGS_TOSTRUCT) {
+ isc_region_t sr;
+ dns_rdata_rrsig_t *sig = target;
+ dns_name_t signer;
+
+ REQUIRE(rdata->type == dns_rdatatype_rrsig);
+ REQUIRE(sig != NULL);
+ REQUIRE(rdata->length != 0);
+
+ sig->common.rdclass = rdata->rdclass;
+ sig->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&sig->common, link);
+
+ dns_rdata_toregion(rdata, &sr);
+
+ /*
+ * Type covered.
+ */
+ sig->covered = uint16_fromregion(&sr);
+ isc_region_consume(&sr, 2);
+
+ /*
+ * Algorithm.
+ */
+ sig->algorithm = uint8_fromregion(&sr);
+ isc_region_consume(&sr, 1);
+
+ /*
+ * Labels.
+ */
+ sig->labels = uint8_fromregion(&sr);
+ isc_region_consume(&sr, 1);
+
+ /*
+ * Original TTL.
+ */
+ sig->originalttl = uint32_fromregion(&sr);
+ isc_region_consume(&sr, 4);
+
+ /*
+ * Expire time.
+ */
+ sig->timeexpire = uint32_fromregion(&sr);
+ isc_region_consume(&sr, 4);
+
+ /*
+ * Time signed.
+ */
+ sig->timesigned = uint32_fromregion(&sr);
+ isc_region_consume(&sr, 4);
+
+ /*
+ * Key ID.
+ */
+ sig->keyid = uint16_fromregion(&sr);
+ isc_region_consume(&sr, 2);
+
+ dns_name_init(&signer, NULL);
+ dns_name_fromregion(&signer, &sr);
+ dns_name_init(&sig->signer, NULL);
+ name_duporclone(&signer, mctx, &sig->signer);
+ isc_region_consume(&sr, name_length(&sig->signer));
+
+ /*
+ * Signature.
+ */
+ sig->siglen = sr.length;
+ sig->signature = mem_maybedup(mctx, sr.base, sig->siglen);
+ if (sig->signature == NULL) {
+ goto cleanup;
+ }
+
+ sig->mctx = mctx;
+ return (ISC_R_SUCCESS);
+
+cleanup:
+ if (mctx != NULL) {
+ dns_name_free(&sig->signer, mctx);
+ }
+ return (ISC_R_NOMEMORY);
+}
+
+static void
+freestruct_rrsig(ARGS_FREESTRUCT) {
+ dns_rdata_rrsig_t *sig = (dns_rdata_rrsig_t *)source;
+
+ REQUIRE(sig != NULL);
+ REQUIRE(sig->common.rdtype == dns_rdatatype_rrsig);
+
+ if (sig->mctx == NULL) {
+ return;
+ }
+
+ dns_name_free(&sig->signer, sig->mctx);
+ if (sig->signature != NULL) {
+ isc_mem_free(sig->mctx, sig->signature);
+ }
+ sig->mctx = NULL;
+}
+
+static isc_result_t
+additionaldata_rrsig(ARGS_ADDLDATA) {
+ REQUIRE(rdata->type == dns_rdatatype_rrsig);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(add);
+ UNUSED(arg);
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+digest_rrsig(ARGS_DIGEST) {
+ REQUIRE(rdata->type == dns_rdatatype_rrsig);
+
+ UNUSED(rdata);
+ UNUSED(digest);
+ UNUSED(arg);
+
+ return (ISC_R_NOTIMPLEMENTED);
+}
+
+static dns_rdatatype_t
+covers_rrsig(dns_rdata_t *rdata) {
+ dns_rdatatype_t type;
+ isc_region_t r;
+
+ REQUIRE(rdata->type == dns_rdatatype_rrsig);
+
+ dns_rdata_toregion(rdata, &r);
+ type = uint16_fromregion(&r);
+
+ return (type);
+}
+
+static bool
+checkowner_rrsig(ARGS_CHECKOWNER) {
+ REQUIRE(type == dns_rdatatype_rrsig);
+
+ UNUSED(name);
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (true);
+}
+
+static bool
+checknames_rrsig(ARGS_CHECKNAMES) {
+ REQUIRE(rdata->type == dns_rdatatype_rrsig);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(bad);
+
+ return (true);
+}
+
+static int
+casecompare_rrsig(ARGS_COMPARE) {
+ isc_region_t r1;
+ isc_region_t r2;
+ dns_name_t name1;
+ dns_name_t name2;
+ int order;
+
+ REQUIRE(rdata1->type == rdata2->type);
+ REQUIRE(rdata1->rdclass == rdata2->rdclass);
+ REQUIRE(rdata1->type == dns_rdatatype_rrsig);
+ REQUIRE(rdata1->length != 0);
+ REQUIRE(rdata2->length != 0);
+
+ dns_rdata_toregion(rdata1, &r1);
+ dns_rdata_toregion(rdata2, &r2);
+
+ INSIST(r1.length > 18);
+ INSIST(r2.length > 18);
+ r1.length = 18;
+ r2.length = 18;
+ order = isc_region_compare(&r1, &r2);
+ if (order != 0) {
+ return (order);
+ }
+
+ dns_name_init(&name1, NULL);
+ dns_name_init(&name2, NULL);
+ dns_rdata_toregion(rdata1, &r1);
+ dns_rdata_toregion(rdata2, &r2);
+ isc_region_consume(&r1, 18);
+ isc_region_consume(&r2, 18);
+ dns_name_fromregion(&name1, &r1);
+ dns_name_fromregion(&name2, &r2);
+ order = dns_name_rdatacompare(&name1, &name2);
+ if (order != 0) {
+ return (order);
+ }
+
+ isc_region_consume(&r1, name_length(&name1));
+ isc_region_consume(&r2, name_length(&name2));
+
+ return (isc_region_compare(&r1, &r2));
+}
+
+#endif /* RDATA_GENERIC_RRSIG_46_C */
diff --git a/lib/dns/rdata/generic/rrsig_46.h b/lib/dns/rdata/generic/rrsig_46.h
new file mode 100644
index 0000000..0869c2d
--- /dev/null
+++ b/lib/dns/rdata/generic/rrsig_46.h
@@ -0,0 +1,31 @@
+/*
+ * 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
+
+/*!
+ * \brief Per RFC2535 */
+typedef struct dns_rdata_rrsig {
+ dns_rdatacommon_t common;
+ isc_mem_t *mctx;
+ dns_rdatatype_t covered;
+ dns_secalg_t algorithm;
+ uint8_t labels;
+ uint32_t originalttl;
+ uint32_t timeexpire;
+ uint32_t timesigned;
+ uint16_t keyid;
+ dns_name_t signer;
+ uint16_t siglen;
+ unsigned char *signature;
+} dns_rdata_rrsig_t;
diff --git a/lib/dns/rdata/generic/rt_21.c b/lib/dns/rdata/generic/rt_21.c
new file mode 100644
index 0000000..10a003f
--- /dev/null
+++ b/lib/dns/rdata/generic/rt_21.c
@@ -0,0 +1,324 @@
+/*
+ * 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.
+ */
+
+/* RFC1183 */
+
+#ifndef RDATA_GENERIC_RT_21_C
+#define RDATA_GENERIC_RT_21_C
+
+#define RRTYPE_RT_ATTRIBUTES (0)
+
+static isc_result_t
+fromtext_rt(ARGS_FROMTEXT) {
+ isc_token_t token;
+ dns_name_t name;
+ isc_buffer_t buffer;
+ bool ok;
+
+ REQUIRE(type == dns_rdatatype_rt);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(callbacks);
+
+ 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));
+
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ false));
+
+ dns_name_init(&name, NULL);
+ buffer_fromregion(&buffer, &token.value.as_region);
+ if (origin == NULL) {
+ origin = dns_rootname;
+ }
+ RETTOK(dns_name_fromtext(&name, &buffer, origin, options, target));
+ ok = true;
+ 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_rt(ARGS_TOTEXT) {
+ isc_region_t region;
+ dns_name_t name;
+ dns_name_t prefix;
+ bool sub;
+ char buf[sizeof("64000")];
+ unsigned short num;
+
+ REQUIRE(rdata->type == dns_rdatatype_rt);
+ REQUIRE(rdata->length != 0);
+
+ dns_name_init(&name, NULL);
+ dns_name_init(&prefix, NULL);
+
+ dns_rdata_toregion(rdata, &region);
+ num = uint16_fromregion(&region);
+ isc_region_consume(&region, 2);
+ snprintf(buf, sizeof(buf), "%u", num);
+ RETERR(str_totext(buf, target));
+ RETERR(str_totext(" ", target));
+ dns_name_fromregion(&name, &region);
+ sub = name_prefix(&name, tctx->origin, &prefix);
+ return (dns_name_totext(&prefix, sub, target));
+}
+
+static isc_result_t
+fromwire_rt(ARGS_FROMWIRE) {
+ dns_name_t name;
+ isc_region_t sregion;
+ isc_region_t tregion;
+
+ REQUIRE(type == dns_rdatatype_rt);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ dns_decompress_setmethods(dctx, DNS_COMPRESS_NONE);
+
+ dns_name_init(&name, NULL);
+
+ isc_buffer_activeregion(source, &sregion);
+ isc_buffer_availableregion(target, &tregion);
+ if (tregion.length < 2) {
+ return (ISC_R_NOSPACE);
+ }
+ if (sregion.length < 2) {
+ return (ISC_R_UNEXPECTEDEND);
+ }
+ memmove(tregion.base, sregion.base, 2);
+ isc_buffer_forward(source, 2);
+ isc_buffer_add(target, 2);
+ return (dns_name_fromwire(&name, source, dctx, options, target));
+}
+
+static isc_result_t
+towire_rt(ARGS_TOWIRE) {
+ dns_name_t name;
+ dns_offsets_t offsets;
+ isc_region_t region;
+ isc_region_t tr;
+
+ REQUIRE(rdata->type == dns_rdatatype_rt);
+ REQUIRE(rdata->length != 0);
+
+ dns_compress_setmethods(cctx, DNS_COMPRESS_NONE);
+ isc_buffer_availableregion(target, &tr);
+ dns_rdata_toregion(rdata, &region);
+ if (tr.length < 2) {
+ return (ISC_R_NOSPACE);
+ }
+ memmove(tr.base, region.base, 2);
+ isc_region_consume(&region, 2);
+ isc_buffer_add(target, 2);
+
+ dns_name_init(&name, offsets);
+ dns_name_fromregion(&name, &region);
+
+ return (dns_name_towire(&name, cctx, target));
+}
+
+static int
+compare_rt(ARGS_COMPARE) {
+ dns_name_t name1;
+ dns_name_t name2;
+ isc_region_t region1;
+ isc_region_t region2;
+ int order;
+
+ REQUIRE(rdata1->type == rdata2->type);
+ REQUIRE(rdata1->rdclass == rdata2->rdclass);
+ REQUIRE(rdata1->type == dns_rdatatype_rt);
+ REQUIRE(rdata1->length != 0);
+ REQUIRE(rdata2->length != 0);
+
+ order = memcmp(rdata1->data, rdata2->data, 2);
+ if (order != 0) {
+ return (order < 0 ? -1 : 1);
+ }
+
+ dns_name_init(&name1, NULL);
+ dns_name_init(&name2, NULL);
+
+ dns_rdata_toregion(rdata1, &region1);
+ dns_rdata_toregion(rdata2, &region2);
+
+ isc_region_consume(&region1, 2);
+ isc_region_consume(&region2, 2);
+
+ dns_name_fromregion(&name1, &region1);
+ dns_name_fromregion(&name2, &region2);
+
+ return (dns_name_rdatacompare(&name1, &name2));
+}
+
+static isc_result_t
+fromstruct_rt(ARGS_FROMSTRUCT) {
+ dns_rdata_rt_t *rt = source;
+ isc_region_t region;
+
+ REQUIRE(type == dns_rdatatype_rt);
+ REQUIRE(rt != NULL);
+ REQUIRE(rt->common.rdtype == type);
+ REQUIRE(rt->common.rdclass == rdclass);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ RETERR(uint16_tobuffer(rt->preference, target));
+ dns_name_toregion(&rt->host, &region);
+ return (isc_buffer_copyregion(target, &region));
+}
+
+static isc_result_t
+tostruct_rt(ARGS_TOSTRUCT) {
+ isc_region_t region;
+ dns_rdata_rt_t *rt = target;
+ dns_name_t name;
+
+ REQUIRE(rdata->type == dns_rdatatype_rt);
+ REQUIRE(rt != NULL);
+ REQUIRE(rdata->length != 0);
+
+ rt->common.rdclass = rdata->rdclass;
+ rt->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&rt->common, link);
+
+ dns_name_init(&name, NULL);
+ dns_rdata_toregion(rdata, &region);
+ rt->preference = uint16_fromregion(&region);
+ isc_region_consume(&region, 2);
+ dns_name_fromregion(&name, &region);
+ dns_name_init(&rt->host, NULL);
+ name_duporclone(&name, mctx, &rt->host);
+
+ rt->mctx = mctx;
+ return (ISC_R_SUCCESS);
+}
+
+static void
+freestruct_rt(ARGS_FREESTRUCT) {
+ dns_rdata_rt_t *rt = source;
+
+ REQUIRE(rt != NULL);
+ REQUIRE(rt->common.rdtype == dns_rdatatype_rt);
+
+ if (rt->mctx == NULL) {
+ return;
+ }
+
+ dns_name_free(&rt->host, rt->mctx);
+ rt->mctx = NULL;
+}
+
+static isc_result_t
+additionaldata_rt(ARGS_ADDLDATA) {
+ dns_name_t name;
+ dns_offsets_t offsets;
+ isc_region_t region;
+ isc_result_t result;
+
+ REQUIRE(rdata->type == dns_rdatatype_rt);
+
+ UNUSED(owner);
+
+ dns_name_init(&name, offsets);
+ dns_rdata_toregion(rdata, &region);
+ isc_region_consume(&region, 2);
+ dns_name_fromregion(&name, &region);
+
+ result = (add)(arg, &name, dns_rdatatype_x25, NULL);
+ if (result != ISC_R_SUCCESS) {
+ return (result);
+ }
+ result = (add)(arg, &name, dns_rdatatype_isdn, NULL);
+ if (result != ISC_R_SUCCESS) {
+ return (result);
+ }
+ return ((add)(arg, &name, dns_rdatatype_a, NULL));
+}
+
+static isc_result_t
+digest_rt(ARGS_DIGEST) {
+ isc_region_t r1, r2;
+ isc_result_t result;
+ dns_name_t name;
+
+ REQUIRE(rdata->type == dns_rdatatype_rt);
+
+ dns_rdata_toregion(rdata, &r1);
+ r2 = r1;
+ isc_region_consume(&r2, 2);
+ r1.length = 2;
+ result = (digest)(arg, &r1);
+ if (result != ISC_R_SUCCESS) {
+ return (result);
+ }
+ dns_name_init(&name, NULL);
+ dns_name_fromregion(&name, &r2);
+ return (dns_name_digest(&name, digest, arg));
+}
+
+static bool
+checkowner_rt(ARGS_CHECKOWNER) {
+ REQUIRE(type == dns_rdatatype_rt);
+
+ UNUSED(name);
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (true);
+}
+
+static bool
+checknames_rt(ARGS_CHECKNAMES) {
+ isc_region_t region;
+ dns_name_t name;
+
+ REQUIRE(rdata->type == dns_rdatatype_rt);
+
+ UNUSED(owner);
+
+ dns_rdata_toregion(rdata, &region);
+ isc_region_consume(&region, 2);
+ dns_name_init(&name, NULL);
+ dns_name_fromregion(&name, &region);
+ if (!dns_name_ishostname(&name, false)) {
+ if (bad != NULL) {
+ dns_name_clone(&name, bad);
+ }
+ return (false);
+ }
+ return (true);
+}
+
+static int
+casecompare_rt(ARGS_COMPARE) {
+ return (compare_rt(rdata1, rdata2));
+}
+
+#endif /* RDATA_GENERIC_RT_21_C */
diff --git a/lib/dns/rdata/generic/rt_21.h b/lib/dns/rdata/generic/rt_21.h
new file mode 100644
index 0000000..7df33d1
--- /dev/null
+++ b/lib/dns/rdata/generic/rt_21.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
+
+/*!
+ * \brief Per RFC1183 */
+
+typedef struct dns_rdata_rt {
+ dns_rdatacommon_t common;
+ isc_mem_t *mctx;
+ uint16_t preference;
+ dns_name_t host;
+} dns_rdata_rt_t;
diff --git a/lib/dns/rdata/generic/sig_24.c b/lib/dns/rdata/generic/sig_24.c
new file mode 100644
index 0000000..85075c3
--- /dev/null
+++ b/lib/dns/rdata/generic/sig_24.c
@@ -0,0 +1,591 @@
+/*
+ * 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.
+ */
+
+/* RFC2535 */
+
+#ifndef RDATA_GENERIC_SIG_24_C
+#define RDATA_GENERIC_SIG_24_C
+
+#define RRTYPE_SIG_ATTRIBUTES (0)
+
+static isc_result_t
+fromtext_sig(ARGS_FROMTEXT) {
+ isc_token_t token;
+ unsigned char c;
+ long i;
+ dns_rdatatype_t covered;
+ char *e;
+ isc_result_t result;
+ dns_name_t name;
+ isc_buffer_t buffer;
+ uint32_t time_signed, time_expire;
+
+ REQUIRE(type == dns_rdatatype_sig);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(callbacks);
+
+ /*
+ * Type covered.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ false));
+ result = dns_rdatatype_fromtext(&covered, &token.value.as_textregion);
+ if (result != ISC_R_SUCCESS && result != ISC_R_NOTIMPLEMENTED) {
+ i = strtol(DNS_AS_STR(token), &e, 10);
+ if (i < 0 || i > 65535) {
+ RETTOK(ISC_R_RANGE);
+ }
+ if (*e != 0) {
+ RETTOK(result);
+ }
+ covered = (dns_rdatatype_t)i;
+ }
+ RETERR(uint16_tobuffer(covered, target));
+
+ /*
+ * Algorithm.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ false));
+ RETTOK(dns_secalg_fromtext(&c, &token.value.as_textregion));
+ RETERR(mem_tobuffer(target, &c, 1));
+
+ /*
+ * Labels.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
+ false));
+ if (token.value.as_ulong > 0xffU) {
+ RETTOK(ISC_R_RANGE);
+ }
+ c = (unsigned char)token.value.as_ulong;
+ RETERR(mem_tobuffer(target, &c, 1));
+
+ /*
+ * Original ttl.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
+ false));
+ RETERR(uint32_tobuffer(token.value.as_ulong, target));
+
+ /*
+ * Signature expiration.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ false));
+ RETTOK(dns_time32_fromtext(DNS_AS_STR(token), &time_expire));
+ RETERR(uint32_tobuffer(time_expire, target));
+
+ /*
+ * Time signed.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ false));
+ RETTOK(dns_time32_fromtext(DNS_AS_STR(token), &time_signed));
+ RETERR(uint32_tobuffer(time_signed, target));
+
+ /*
+ * Key footprint.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
+ false));
+ RETERR(uint16_tobuffer(token.value.as_ulong, target));
+
+ /*
+ * Signer.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ false));
+ dns_name_init(&name, NULL);
+ buffer_fromregion(&buffer, &token.value.as_region);
+ if (origin == NULL) {
+ origin = dns_rootname;
+ }
+ RETTOK(dns_name_fromtext(&name, &buffer, origin, options, target));
+
+ /*
+ * Sig.
+ */
+ return (isc_base64_tobuffer(lexer, target, -2));
+}
+
+static isc_result_t
+totext_sig(ARGS_TOTEXT) {
+ isc_region_t sr;
+ char buf[sizeof("4294967295")];
+ dns_rdatatype_t covered;
+ unsigned long ttl;
+ unsigned long when;
+ unsigned long exp;
+ unsigned long foot;
+ dns_name_t name;
+ dns_name_t prefix;
+ bool sub;
+
+ REQUIRE(rdata->type == dns_rdatatype_sig);
+ REQUIRE(rdata->length != 0);
+
+ dns_rdata_toregion(rdata, &sr);
+
+ /*
+ * Type covered.
+ */
+ covered = uint16_fromregion(&sr);
+ isc_region_consume(&sr, 2);
+ /*
+ * XXXAG We should have something like dns_rdatatype_isknown()
+ * that does the right thing with type 0.
+ */
+ if (dns_rdatatype_isknown(covered) && covered != 0) {
+ RETERR(dns_rdatatype_totext(covered, target));
+ } else {
+ snprintf(buf, sizeof(buf), "%u", covered);
+ RETERR(str_totext(buf, target));
+ }
+ RETERR(str_totext(" ", target));
+
+ /*
+ * Algorithm.
+ */
+ snprintf(buf, sizeof(buf), "%u", sr.base[0]);
+ isc_region_consume(&sr, 1);
+ RETERR(str_totext(buf, target));
+ RETERR(str_totext(" ", target));
+
+ /*
+ * Labels.
+ */
+ snprintf(buf, sizeof(buf), "%u", sr.base[0]);
+ isc_region_consume(&sr, 1);
+ RETERR(str_totext(buf, target));
+ RETERR(str_totext(" ", target));
+
+ /*
+ * Ttl.
+ */
+ ttl = uint32_fromregion(&sr);
+ isc_region_consume(&sr, 4);
+ snprintf(buf, sizeof(buf), "%lu", ttl);
+ RETERR(str_totext(buf, target));
+ RETERR(str_totext(" ", target));
+
+ /*
+ * Sig exp.
+ */
+ exp = uint32_fromregion(&sr);
+ isc_region_consume(&sr, 4);
+ RETERR(dns_time32_totext(exp, target));
+
+ if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) {
+ RETERR(str_totext(" (", target));
+ }
+ RETERR(str_totext(tctx->linebreak, target));
+
+ /*
+ * Time signed.
+ */
+ when = uint32_fromregion(&sr);
+ isc_region_consume(&sr, 4);
+ RETERR(dns_time32_totext(when, target));
+ RETERR(str_totext(" ", target));
+
+ /*
+ * Footprint.
+ */
+ foot = uint16_fromregion(&sr);
+ isc_region_consume(&sr, 2);
+ snprintf(buf, sizeof(buf), "%lu", foot);
+ RETERR(str_totext(buf, target));
+ RETERR(str_totext(" ", target));
+
+ /*
+ * Signer.
+ */
+ dns_name_init(&name, NULL);
+ dns_name_init(&prefix, NULL);
+ dns_name_fromregion(&name, &sr);
+ isc_region_consume(&sr, name_length(&name));
+ sub = name_prefix(&name, tctx->origin, &prefix);
+ RETERR(dns_name_totext(&prefix, sub, target));
+
+ /*
+ * Sig.
+ */
+ RETERR(str_totext(tctx->linebreak, target));
+ if (tctx->width == 0) { /* No splitting */
+ RETERR(isc_base64_totext(&sr, 60, "", target));
+ } else {
+ RETERR(isc_base64_totext(&sr, tctx->width - 2, tctx->linebreak,
+ target));
+ }
+ if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) {
+ RETERR(str_totext(" )", target));
+ }
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+fromwire_sig(ARGS_FROMWIRE) {
+ isc_region_t sr;
+ dns_name_t name;
+
+ REQUIRE(type == dns_rdatatype_sig);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ dns_decompress_setmethods(dctx, DNS_COMPRESS_NONE);
+
+ isc_buffer_activeregion(source, &sr);
+ /*
+ * type covered: 2
+ * algorithm: 1
+ * labels: 1
+ * original ttl: 4
+ * signature expiration: 4
+ * time signed: 4
+ * key footprint: 2
+ */
+ if (sr.length < 18) {
+ return (ISC_R_UNEXPECTEDEND);
+ }
+
+ isc_buffer_forward(source, 18);
+ RETERR(mem_tobuffer(target, sr.base, 18));
+
+ /*
+ * Signer.
+ */
+ dns_name_init(&name, NULL);
+ RETERR(dns_name_fromwire(&name, source, dctx, options, target));
+
+ /*
+ * Sig.
+ */
+ isc_buffer_activeregion(source, &sr);
+ if (sr.length == 0) {
+ return (ISC_R_UNEXPECTEDEND);
+ }
+ isc_buffer_forward(source, sr.length);
+ return (mem_tobuffer(target, sr.base, sr.length));
+}
+
+static isc_result_t
+towire_sig(ARGS_TOWIRE) {
+ isc_region_t sr;
+ dns_name_t name;
+ dns_offsets_t offsets;
+
+ REQUIRE(rdata->type == dns_rdatatype_sig);
+ REQUIRE(rdata->length != 0);
+
+ dns_compress_setmethods(cctx, DNS_COMPRESS_NONE);
+ dns_rdata_toregion(rdata, &sr);
+ /*
+ * type covered: 2
+ * algorithm: 1
+ * labels: 1
+ * original ttl: 4
+ * signature expiration: 4
+ * time signed: 4
+ * key footprint: 2
+ */
+ RETERR(mem_tobuffer(target, sr.base, 18));
+ isc_region_consume(&sr, 18);
+
+ /*
+ * Signer.
+ */
+ dns_name_init(&name, offsets);
+ dns_name_fromregion(&name, &sr);
+ isc_region_consume(&sr, name_length(&name));
+ RETERR(dns_name_towire(&name, cctx, target));
+
+ /*
+ * Signature.
+ */
+ return (mem_tobuffer(target, sr.base, sr.length));
+}
+
+static int
+compare_sig(ARGS_COMPARE) {
+ isc_region_t r1;
+ isc_region_t r2;
+ dns_name_t name1;
+ dns_name_t name2;
+ int order;
+
+ REQUIRE(rdata1->type == rdata2->type);
+ REQUIRE(rdata1->rdclass == rdata2->rdclass);
+ REQUIRE(rdata1->type == dns_rdatatype_sig);
+ REQUIRE(rdata1->length != 0);
+ REQUIRE(rdata2->length != 0);
+
+ dns_rdata_toregion(rdata1, &r1);
+ dns_rdata_toregion(rdata2, &r2);
+
+ INSIST(r1.length > 18);
+ INSIST(r2.length > 18);
+ r1.length = 18;
+ r2.length = 18;
+ order = isc_region_compare(&r1, &r2);
+ if (order != 0) {
+ return (order);
+ }
+
+ dns_name_init(&name1, NULL);
+ dns_name_init(&name2, NULL);
+ dns_rdata_toregion(rdata1, &r1);
+ dns_rdata_toregion(rdata2, &r2);
+ isc_region_consume(&r1, 18);
+ isc_region_consume(&r2, 18);
+ dns_name_fromregion(&name1, &r1);
+ dns_name_fromregion(&name2, &r2);
+ order = dns_name_rdatacompare(&name1, &name2);
+ if (order != 0) {
+ return (order);
+ }
+
+ isc_region_consume(&r1, name_length(&name1));
+ isc_region_consume(&r2, name_length(&name2));
+
+ return (isc_region_compare(&r1, &r2));
+}
+
+static isc_result_t
+fromstruct_sig(ARGS_FROMSTRUCT) {
+ dns_rdata_sig_t *sig = source;
+
+ REQUIRE(type == dns_rdatatype_sig);
+ REQUIRE(sig != NULL);
+ REQUIRE(sig->common.rdtype == type);
+ REQUIRE(sig->common.rdclass == rdclass);
+ REQUIRE(sig->signature != NULL || sig->siglen == 0);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ /*
+ * Type covered.
+ */
+ RETERR(uint16_tobuffer(sig->covered, target));
+
+ /*
+ * Algorithm.
+ */
+ RETERR(uint8_tobuffer(sig->algorithm, target));
+
+ /*
+ * Labels.
+ */
+ RETERR(uint8_tobuffer(sig->labels, target));
+
+ /*
+ * Original TTL.
+ */
+ RETERR(uint32_tobuffer(sig->originalttl, target));
+
+ /*
+ * Expire time.
+ */
+ RETERR(uint32_tobuffer(sig->timeexpire, target));
+
+ /*
+ * Time signed.
+ */
+ RETERR(uint32_tobuffer(sig->timesigned, target));
+
+ /*
+ * Key ID.
+ */
+ RETERR(uint16_tobuffer(sig->keyid, target));
+
+ /*
+ * Signer name.
+ */
+ RETERR(name_tobuffer(&sig->signer, target));
+
+ /*
+ * Signature.
+ */
+ return (mem_tobuffer(target, sig->signature, sig->siglen));
+}
+
+static isc_result_t
+tostruct_sig(ARGS_TOSTRUCT) {
+ isc_region_t sr;
+ dns_rdata_sig_t *sig = target;
+ dns_name_t signer;
+
+ REQUIRE(rdata->type == dns_rdatatype_sig);
+ REQUIRE(sig != NULL);
+ REQUIRE(rdata->length != 0);
+
+ sig->common.rdclass = rdata->rdclass;
+ sig->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&sig->common, link);
+
+ dns_rdata_toregion(rdata, &sr);
+
+ /*
+ * Type covered.
+ */
+ sig->covered = uint16_fromregion(&sr);
+ isc_region_consume(&sr, 2);
+
+ /*
+ * Algorithm.
+ */
+ sig->algorithm = uint8_fromregion(&sr);
+ isc_region_consume(&sr, 1);
+
+ /*
+ * Labels.
+ */
+ sig->labels = uint8_fromregion(&sr);
+ isc_region_consume(&sr, 1);
+
+ /*
+ * Original TTL.
+ */
+ sig->originalttl = uint32_fromregion(&sr);
+ isc_region_consume(&sr, 4);
+
+ /*
+ * Expire time.
+ */
+ sig->timeexpire = uint32_fromregion(&sr);
+ isc_region_consume(&sr, 4);
+
+ /*
+ * Time signed.
+ */
+ sig->timesigned = uint32_fromregion(&sr);
+ isc_region_consume(&sr, 4);
+
+ /*
+ * Key ID.
+ */
+ sig->keyid = uint16_fromregion(&sr);
+ isc_region_consume(&sr, 2);
+
+ dns_name_init(&signer, NULL);
+ dns_name_fromregion(&signer, &sr);
+ dns_name_init(&sig->signer, NULL);
+ name_duporclone(&signer, mctx, &sig->signer);
+ isc_region_consume(&sr, name_length(&sig->signer));
+
+ /*
+ * Signature.
+ */
+ sig->siglen = sr.length;
+ sig->signature = mem_maybedup(mctx, sr.base, sig->siglen);
+ if (sig->signature == NULL) {
+ goto cleanup;
+ }
+
+ sig->mctx = mctx;
+ return (ISC_R_SUCCESS);
+
+cleanup:
+ if (mctx != NULL) {
+ dns_name_free(&sig->signer, mctx);
+ }
+ return (ISC_R_NOMEMORY);
+}
+
+static void
+freestruct_sig(ARGS_FREESTRUCT) {
+ dns_rdata_sig_t *sig = (dns_rdata_sig_t *)source;
+
+ REQUIRE(sig != NULL);
+ REQUIRE(sig->common.rdtype == dns_rdatatype_sig);
+
+ if (sig->mctx == NULL) {
+ return;
+ }
+
+ dns_name_free(&sig->signer, sig->mctx);
+ if (sig->signature != NULL) {
+ isc_mem_free(sig->mctx, sig->signature);
+ }
+ sig->mctx = NULL;
+}
+
+static isc_result_t
+additionaldata_sig(ARGS_ADDLDATA) {
+ REQUIRE(rdata->type == dns_rdatatype_sig);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(add);
+ UNUSED(arg);
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+digest_sig(ARGS_DIGEST) {
+ REQUIRE(rdata->type == dns_rdatatype_sig);
+
+ UNUSED(rdata);
+ UNUSED(digest);
+ UNUSED(arg);
+
+ return (ISC_R_NOTIMPLEMENTED);
+}
+
+static dns_rdatatype_t
+covers_sig(dns_rdata_t *rdata) {
+ dns_rdatatype_t type;
+ isc_region_t r;
+
+ REQUIRE(rdata->type == dns_rdatatype_sig);
+
+ dns_rdata_toregion(rdata, &r);
+ type = uint16_fromregion(&r);
+
+ return (type);
+}
+
+static bool
+checkowner_sig(ARGS_CHECKOWNER) {
+ REQUIRE(type == dns_rdatatype_sig);
+
+ UNUSED(name);
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (true);
+}
+
+static bool
+checknames_sig(ARGS_CHECKNAMES) {
+ REQUIRE(rdata->type == dns_rdatatype_sig);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(bad);
+
+ return (true);
+}
+
+static int
+casecompare_sig(ARGS_COMPARE) {
+ return (compare_sig(rdata1, rdata2));
+}
+#endif /* RDATA_GENERIC_SIG_24_C */
diff --git a/lib/dns/rdata/generic/sig_24.h b/lib/dns/rdata/generic/sig_24.h
new file mode 100644
index 0000000..40bad22
--- /dev/null
+++ b/lib/dns/rdata/generic/sig_24.h
@@ -0,0 +1,32 @@
+/*
+ * 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
+
+/*!
+ * \brief Per RFC2535 */
+
+typedef struct dns_rdata_sig_t {
+ dns_rdatacommon_t common;
+ isc_mem_t *mctx;
+ dns_rdatatype_t covered;
+ dns_secalg_t algorithm;
+ uint8_t labels;
+ uint32_t originalttl;
+ uint32_t timeexpire;
+ uint32_t timesigned;
+ uint16_t keyid;
+ dns_name_t signer;
+ uint16_t siglen;
+ unsigned char *signature;
+} dns_rdata_sig_t;
diff --git a/lib/dns/rdata/generic/sink_40.c b/lib/dns/rdata/generic/sink_40.c
new file mode 100644
index 0000000..8d76212
--- /dev/null
+++ b/lib/dns/rdata/generic/sink_40.c
@@ -0,0 +1,292 @@
+/*
+ * 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_SINK_40_C
+#define RDATA_GENERIC_SINK_40_C
+
+#include <dst/dst.h>
+
+#define RRTYPE_SINK_ATTRIBUTES (0)
+
+static isc_result_t
+fromtext_sink(ARGS_FROMTEXT) {
+ isc_token_t token;
+
+ REQUIRE(type == dns_rdatatype_sink);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(origin);
+ UNUSED(options);
+ UNUSED(callbacks);
+
+ /* meaning */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
+ false));
+ if (token.value.as_ulong > 0xffU) {
+ RETTOK(ISC_R_RANGE);
+ }
+ RETERR(uint8_tobuffer(token.value.as_ulong, target));
+
+ /* coding */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
+ false));
+ if (token.value.as_ulong > 0xffU) {
+ RETTOK(ISC_R_RANGE);
+ }
+ RETERR(uint8_tobuffer(token.value.as_ulong, target));
+
+ /* subcoding */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
+ false));
+ if (token.value.as_ulong > 0xffU) {
+ RETTOK(ISC_R_RANGE);
+ }
+ RETERR(uint8_tobuffer(token.value.as_ulong, target));
+
+ return (isc_base64_tobuffer(lexer, target, -1));
+}
+
+static isc_result_t
+totext_sink(ARGS_TOTEXT) {
+ isc_region_t sr;
+ char buf[sizeof("255 255 255")];
+ uint8_t meaning, coding, subcoding;
+
+ REQUIRE(rdata->type == dns_rdatatype_sink);
+ REQUIRE(rdata->length >= 3);
+
+ dns_rdata_toregion(rdata, &sr);
+
+ /* Meaning, Coding and Subcoding */
+ meaning = uint8_fromregion(&sr);
+ isc_region_consume(&sr, 1);
+ coding = uint8_fromregion(&sr);
+ isc_region_consume(&sr, 1);
+ subcoding = uint8_fromregion(&sr);
+ isc_region_consume(&sr, 1);
+ snprintf(buf, sizeof(buf), "%u %u %u", meaning, coding, subcoding);
+ RETERR(str_totext(buf, target));
+
+ if (sr.length == 0U) {
+ return (ISC_R_SUCCESS);
+ }
+
+ /* data */
+ if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) {
+ RETERR(str_totext(" (", target));
+ }
+
+ RETERR(str_totext(tctx->linebreak, target));
+
+ if (tctx->width == 0) { /* No splitting */
+ RETERR(isc_base64_totext(&sr, 60, "", target));
+ } else {
+ RETERR(isc_base64_totext(&sr, tctx->width - 2, tctx->linebreak,
+ target));
+ }
+
+ if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) {
+ RETERR(str_totext(" )", target));
+ }
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+fromwire_sink(ARGS_FROMWIRE) {
+ isc_region_t sr;
+
+ REQUIRE(type == dns_rdatatype_sink);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(dctx);
+ UNUSED(options);
+
+ isc_buffer_activeregion(source, &sr);
+ if (sr.length < 3) {
+ return (ISC_R_UNEXPECTEDEND);
+ }
+
+ RETERR(mem_tobuffer(target, sr.base, sr.length));
+ isc_buffer_forward(source, sr.length);
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+towire_sink(ARGS_TOWIRE) {
+ REQUIRE(rdata->type == dns_rdatatype_sink);
+ REQUIRE(rdata->length >= 3);
+
+ UNUSED(cctx);
+
+ return (mem_tobuffer(target, rdata->data, rdata->length));
+}
+
+static int
+compare_sink(ARGS_COMPARE) {
+ isc_region_t r1;
+ isc_region_t r2;
+
+ REQUIRE(rdata1->type == rdata2->type);
+ REQUIRE(rdata1->rdclass == rdata2->rdclass);
+ REQUIRE(rdata1->type == dns_rdatatype_sink);
+ REQUIRE(rdata1->length >= 3);
+ REQUIRE(rdata2->length >= 3);
+
+ dns_rdata_toregion(rdata1, &r1);
+ dns_rdata_toregion(rdata2, &r2);
+ return (isc_region_compare(&r1, &r2));
+}
+
+static isc_result_t
+fromstruct_sink(ARGS_FROMSTRUCT) {
+ dns_rdata_sink_t *sink = source;
+
+ REQUIRE(type == dns_rdatatype_sink);
+ REQUIRE(sink != NULL);
+ REQUIRE(sink->common.rdtype == type);
+ REQUIRE(sink->common.rdclass == rdclass);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ /* Meaning */
+ RETERR(uint8_tobuffer(sink->meaning, target));
+
+ /* Coding */
+ RETERR(uint8_tobuffer(sink->coding, target));
+
+ /* Subcoding */
+ RETERR(uint8_tobuffer(sink->subcoding, target));
+
+ /* Data */
+ return (mem_tobuffer(target, sink->data, sink->datalen));
+}
+
+static isc_result_t
+tostruct_sink(ARGS_TOSTRUCT) {
+ dns_rdata_sink_t *sink = target;
+ isc_region_t sr;
+
+ REQUIRE(rdata->type == dns_rdatatype_sink);
+ REQUIRE(sink != NULL);
+ REQUIRE(rdata->length >= 3);
+
+ sink->common.rdclass = rdata->rdclass;
+ sink->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&sink->common, link);
+
+ dns_rdata_toregion(rdata, &sr);
+
+ /* Meaning */
+ if (sr.length < 1) {
+ return (ISC_R_UNEXPECTEDEND);
+ }
+ sink->meaning = uint8_fromregion(&sr);
+ isc_region_consume(&sr, 1);
+
+ /* Coding */
+ if (sr.length < 1) {
+ return (ISC_R_UNEXPECTEDEND);
+ }
+ sink->coding = uint8_fromregion(&sr);
+ isc_region_consume(&sr, 1);
+
+ /* Subcoding */
+ if (sr.length < 1) {
+ return (ISC_R_UNEXPECTEDEND);
+ }
+ sink->subcoding = uint8_fromregion(&sr);
+ isc_region_consume(&sr, 1);
+
+ /* Data */
+ sink->datalen = sr.length;
+ sink->data = mem_maybedup(mctx, sr.base, sink->datalen);
+ if (sink->data == NULL) {
+ return (ISC_R_NOMEMORY);
+ }
+
+ sink->mctx = mctx;
+ return (ISC_R_SUCCESS);
+}
+
+static void
+freestruct_sink(ARGS_FREESTRUCT) {
+ dns_rdata_sink_t *sink = (dns_rdata_sink_t *)source;
+
+ REQUIRE(sink != NULL);
+ REQUIRE(sink->common.rdtype == dns_rdatatype_sink);
+
+ if (sink->mctx == NULL) {
+ return;
+ }
+
+ if (sink->data != NULL) {
+ isc_mem_free(sink->mctx, sink->data);
+ }
+ sink->mctx = NULL;
+}
+
+static isc_result_t
+additionaldata_sink(ARGS_ADDLDATA) {
+ REQUIRE(rdata->type == dns_rdatatype_sink);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(add);
+ UNUSED(arg);
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+digest_sink(ARGS_DIGEST) {
+ isc_region_t r;
+
+ REQUIRE(rdata->type == dns_rdatatype_sink);
+
+ dns_rdata_toregion(rdata, &r);
+
+ return ((digest)(arg, &r));
+}
+
+static bool
+checkowner_sink(ARGS_CHECKOWNER) {
+ REQUIRE(type == dns_rdatatype_sink);
+
+ UNUSED(name);
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (true);
+}
+
+static bool
+checknames_sink(ARGS_CHECKNAMES) {
+ REQUIRE(rdata->type == dns_rdatatype_sink);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(bad);
+
+ return (true);
+}
+
+static int
+casecompare_sink(ARGS_COMPARE) {
+ return (compare_sink(rdata1, rdata2));
+}
+#endif /* RDATA_GENERIC_SINK_40_C */
diff --git a/lib/dns/rdata/generic/sink_40.h b/lib/dns/rdata/generic/sink_40.h
new file mode 100644
index 0000000..e2615fd
--- /dev/null
+++ b/lib/dns/rdata/generic/sink_40.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_sink_t {
+ dns_rdatacommon_t common;
+ isc_mem_t *mctx;
+ uint8_t meaning;
+ uint8_t coding;
+ uint8_t subcoding;
+ uint16_t datalen;
+ unsigned char *data;
+} dns_rdata_sink_t;
diff --git a/lib/dns/rdata/generic/smimea_53.c b/lib/dns/rdata/generic/smimea_53.c
new file mode 100644
index 0000000..ce154a0
--- /dev/null
+++ b/lib/dns/rdata/generic/smimea_53.c
@@ -0,0 +1,153 @@
+/*
+ * 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_SMIMEA_53_C
+#define RDATA_GENERIC_SMIMEA_53_C
+
+#define RRTYPE_SMIMEA_ATTRIBUTES 0
+
+static isc_result_t
+fromtext_smimea(ARGS_FROMTEXT) {
+ REQUIRE(type == dns_rdatatype_smimea);
+
+ return (generic_fromtext_tlsa(CALL_FROMTEXT));
+}
+
+static isc_result_t
+totext_smimea(ARGS_TOTEXT) {
+ REQUIRE(rdata != NULL);
+ REQUIRE(rdata->type == dns_rdatatype_smimea);
+
+ return (generic_totext_tlsa(CALL_TOTEXT));
+}
+
+static isc_result_t
+fromwire_smimea(ARGS_FROMWIRE) {
+ REQUIRE(type == dns_rdatatype_smimea);
+
+ return (generic_fromwire_tlsa(CALL_FROMWIRE));
+}
+
+static isc_result_t
+towire_smimea(ARGS_TOWIRE) {
+ isc_region_t sr;
+
+ REQUIRE(rdata->type == dns_rdatatype_smimea);
+ REQUIRE(rdata->length != 0);
+
+ UNUSED(cctx);
+
+ dns_rdata_toregion(rdata, &sr);
+ return (mem_tobuffer(target, sr.base, sr.length));
+}
+
+static int
+compare_smimea(ARGS_COMPARE) {
+ isc_region_t r1;
+ isc_region_t r2;
+
+ REQUIRE(rdata1->type == rdata2->type);
+ REQUIRE(rdata1->rdclass == rdata2->rdclass);
+ REQUIRE(rdata1->type == dns_rdatatype_smimea);
+ REQUIRE(rdata1->length != 0);
+ REQUIRE(rdata2->length != 0);
+
+ dns_rdata_toregion(rdata1, &r1);
+ dns_rdata_toregion(rdata2, &r2);
+ return (isc_region_compare(&r1, &r2));
+}
+
+static isc_result_t
+fromstruct_smimea(ARGS_FROMSTRUCT) {
+ REQUIRE(type == dns_rdatatype_smimea);
+
+ return (generic_fromstruct_tlsa(CALL_FROMSTRUCT));
+}
+
+static isc_result_t
+tostruct_smimea(ARGS_TOSTRUCT) {
+ dns_rdata_smimea_t *smimea = target;
+
+ REQUIRE(rdata != NULL);
+ REQUIRE(rdata->type == dns_rdatatype_smimea);
+ REQUIRE(smimea != NULL);
+
+ smimea->common.rdclass = rdata->rdclass;
+ smimea->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&smimea->common, link);
+
+ return (generic_tostruct_tlsa(CALL_TOSTRUCT));
+}
+
+static void
+freestruct_smimea(ARGS_FREESTRUCT) {
+ dns_rdata_smimea_t *smimea = source;
+
+ REQUIRE(smimea != NULL);
+ REQUIRE(smimea->common.rdtype == dns_rdatatype_smimea);
+
+ generic_freestruct_tlsa(source);
+}
+
+static isc_result_t
+additionaldata_smimea(ARGS_ADDLDATA) {
+ REQUIRE(rdata->type == dns_rdatatype_smimea);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(add);
+ UNUSED(arg);
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+digest_smimea(ARGS_DIGEST) {
+ isc_region_t r;
+
+ REQUIRE(rdata->type == dns_rdatatype_smimea);
+
+ dns_rdata_toregion(rdata, &r);
+
+ return ((digest)(arg, &r));
+}
+
+static bool
+checkowner_smimea(ARGS_CHECKOWNER) {
+ REQUIRE(type == dns_rdatatype_smimea);
+
+ UNUSED(name);
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (true);
+}
+
+static bool
+checknames_smimea(ARGS_CHECKNAMES) {
+ REQUIRE(rdata->type == dns_rdatatype_smimea);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(bad);
+
+ return (true);
+}
+
+static int
+casecompare_smimea(ARGS_COMPARE) {
+ return (compare_smimea(rdata1, rdata2));
+}
+
+#endif /* RDATA_GENERIC_SMIMEA_53_C */
diff --git a/lib/dns/rdata/generic/smimea_53.h b/lib/dns/rdata/generic/smimea_53.h
new file mode 100644
index 0000000..108eb20
--- /dev/null
+++ b/lib/dns/rdata/generic/smimea_53.h
@@ -0,0 +1,16 @@
+/*
+ * 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_tlsa dns_rdata_smimea_t;
diff --git a/lib/dns/rdata/generic/soa_6.c b/lib/dns/rdata/generic/soa_6.c
new file mode 100644
index 0000000..24b5278
--- /dev/null
+++ b/lib/dns/rdata/generic/soa_6.c
@@ -0,0 +1,443 @@
+/*
+ * 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_SOA_6_C
+#define RDATA_GENERIC_SOA_6_C
+
+#define RRTYPE_SOA_ATTRIBUTES (DNS_RDATATYPEATTR_SINGLETON)
+
+static isc_result_t
+fromtext_soa(ARGS_FROMTEXT) {
+ isc_token_t token;
+ dns_name_t name;
+ isc_buffer_t buffer;
+ int i;
+ uint32_t n;
+ bool ok;
+
+ REQUIRE(type == dns_rdatatype_soa);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(callbacks);
+
+ if (origin == NULL) {
+ origin = dns_rootname;
+ }
+
+ for (i = 0; i < 2; i++) {
+ RETERR(isc_lex_getmastertoken(lexer, &token,
+ isc_tokentype_string, false));
+
+ dns_name_init(&name, NULL);
+ buffer_fromregion(&buffer, &token.value.as_region);
+ RETTOK(dns_name_fromtext(&name, &buffer, origin, options,
+ target));
+ ok = true;
+ if ((options & DNS_RDATA_CHECKNAMES) != 0) {
+ switch (i) {
+ case 0:
+ ok = dns_name_ishostname(&name, false);
+ break;
+ case 1:
+ ok = dns_name_ismailbox(&name);
+ break;
+ }
+ }
+ if (!ok && (options & DNS_RDATA_CHECKNAMESFAIL) != 0) {
+ RETTOK(DNS_R_BADNAME);
+ }
+ if (!ok && callbacks != NULL) {
+ warn_badname(&name, lexer, callbacks);
+ }
+ }
+
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
+ false));
+ RETERR(uint32_tobuffer(token.value.as_ulong, target));
+
+ for (i = 0; i < 4; i++) {
+ RETERR(isc_lex_getmastertoken(lexer, &token,
+ isc_tokentype_string, false));
+ RETTOK(dns_counter_fromtext(&token.value.as_textregion, &n));
+ RETERR(uint32_tobuffer(n, target));
+ }
+
+ return (ISC_R_SUCCESS);
+}
+
+static const char *soa_fieldnames[5] = { "serial", "refresh", "retry", "expire",
+ "minimum" };
+
+static isc_result_t
+totext_soa(ARGS_TOTEXT) {
+ isc_region_t dregion;
+ dns_name_t mname;
+ dns_name_t rname;
+ dns_name_t prefix;
+ bool sub;
+ int i;
+ bool multiline;
+ bool comm;
+
+ REQUIRE(rdata->type == dns_rdatatype_soa);
+ REQUIRE(rdata->length != 0);
+
+ multiline = ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0);
+ if (multiline) {
+ comm = ((tctx->flags & DNS_STYLEFLAG_RRCOMMENT) != 0);
+ } else {
+ comm = false;
+ }
+
+ dns_name_init(&mname, NULL);
+ dns_name_init(&rname, NULL);
+ dns_name_init(&prefix, NULL);
+
+ dns_rdata_toregion(rdata, &dregion);
+
+ dns_name_fromregion(&mname, &dregion);
+ isc_region_consume(&dregion, name_length(&mname));
+
+ dns_name_fromregion(&rname, &dregion);
+ isc_region_consume(&dregion, name_length(&rname));
+
+ sub = name_prefix(&mname, tctx->origin, &prefix);
+ RETERR(dns_name_totext(&prefix, sub, target));
+
+ RETERR(str_totext(" ", target));
+
+ sub = name_prefix(&rname, tctx->origin, &prefix);
+ RETERR(dns_name_totext(&prefix, sub, target));
+
+ if (multiline) {
+ RETERR(str_totext(" (", target));
+ }
+ RETERR(str_totext(tctx->linebreak, target));
+
+ for (i = 0; i < 5; i++) {
+ char buf[sizeof("0123456789 ; ")];
+ unsigned long num;
+ num = uint32_fromregion(&dregion);
+ isc_region_consume(&dregion, 4);
+ snprintf(buf, sizeof(buf), comm ? "%-10lu ; " : "%lu", num);
+ RETERR(str_totext(buf, target));
+ if (comm) {
+ RETERR(str_totext(soa_fieldnames[i], target));
+ /* Print times in week/day/hour/minute/second form */
+ if (i >= 1) {
+ RETERR(str_totext(" (", target));
+ RETERR(dns_ttl_totext(num, true, true, target));
+ RETERR(str_totext(")", target));
+ }
+ RETERR(str_totext(tctx->linebreak, target));
+ } else if (i < 4) {
+ RETERR(str_totext(tctx->linebreak, target));
+ }
+ }
+
+ if (multiline) {
+ RETERR(str_totext(")", target));
+ }
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+fromwire_soa(ARGS_FROMWIRE) {
+ dns_name_t mname;
+ dns_name_t rname;
+ isc_region_t sregion;
+ isc_region_t tregion;
+
+ REQUIRE(type == dns_rdatatype_soa);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ dns_decompress_setmethods(dctx, DNS_COMPRESS_GLOBAL14);
+
+ dns_name_init(&mname, NULL);
+ dns_name_init(&rname, NULL);
+
+ RETERR(dns_name_fromwire(&mname, source, dctx, options, target));
+ RETERR(dns_name_fromwire(&rname, source, dctx, options, target));
+
+ isc_buffer_activeregion(source, &sregion);
+ isc_buffer_availableregion(target, &tregion);
+
+ if (sregion.length < 20) {
+ return (ISC_R_UNEXPECTEDEND);
+ }
+ if (tregion.length < 20) {
+ return (ISC_R_NOSPACE);
+ }
+
+ memmove(tregion.base, sregion.base, 20);
+ isc_buffer_forward(source, 20);
+ isc_buffer_add(target, 20);
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+towire_soa(ARGS_TOWIRE) {
+ isc_region_t sregion;
+ isc_region_t tregion;
+ dns_name_t mname;
+ dns_name_t rname;
+ dns_offsets_t moffsets;
+ dns_offsets_t roffsets;
+
+ REQUIRE(rdata->type == dns_rdatatype_soa);
+ REQUIRE(rdata->length != 0);
+
+ dns_compress_setmethods(cctx, DNS_COMPRESS_GLOBAL14);
+
+ dns_name_init(&mname, moffsets);
+ dns_name_init(&rname, roffsets);
+
+ dns_rdata_toregion(rdata, &sregion);
+
+ dns_name_fromregion(&mname, &sregion);
+ isc_region_consume(&sregion, name_length(&mname));
+ RETERR(dns_name_towire(&mname, cctx, target));
+
+ dns_name_fromregion(&rname, &sregion);
+ isc_region_consume(&sregion, name_length(&rname));
+ RETERR(dns_name_towire(&rname, cctx, target));
+
+ isc_buffer_availableregion(target, &tregion);
+ if (tregion.length < 20) {
+ return (ISC_R_NOSPACE);
+ }
+
+ memmove(tregion.base, sregion.base, 20);
+ isc_buffer_add(target, 20);
+ return (ISC_R_SUCCESS);
+}
+
+static int
+compare_soa(ARGS_COMPARE) {
+ isc_region_t region1;
+ isc_region_t region2;
+ dns_name_t name1;
+ dns_name_t name2;
+ int order;
+
+ REQUIRE(rdata1->type == rdata2->type);
+ REQUIRE(rdata1->rdclass == rdata2->rdclass);
+ REQUIRE(rdata1->type == dns_rdatatype_soa);
+ REQUIRE(rdata1->length != 0);
+ REQUIRE(rdata2->length != 0);
+
+ dns_name_init(&name1, NULL);
+ dns_name_init(&name2, NULL);
+
+ dns_rdata_toregion(rdata1, &region1);
+ dns_rdata_toregion(rdata2, &region2);
+
+ dns_name_fromregion(&name1, &region1);
+ dns_name_fromregion(&name2, &region2);
+
+ order = dns_name_rdatacompare(&name1, &name2);
+ if (order != 0) {
+ return (order);
+ }
+
+ isc_region_consume(&region1, name_length(&name1));
+ isc_region_consume(&region2, name_length(&name2));
+
+ dns_name_init(&name1, NULL);
+ dns_name_init(&name2, NULL);
+
+ dns_name_fromregion(&name1, &region1);
+ dns_name_fromregion(&name2, &region2);
+
+ order = dns_name_rdatacompare(&name1, &name2);
+ if (order != 0) {
+ return (order);
+ }
+
+ isc_region_consume(&region1, name_length(&name1));
+ isc_region_consume(&region2, name_length(&name2));
+
+ return (isc_region_compare(&region1, &region2));
+}
+
+static isc_result_t
+fromstruct_soa(ARGS_FROMSTRUCT) {
+ dns_rdata_soa_t *soa = source;
+ isc_region_t region;
+
+ REQUIRE(type == dns_rdatatype_soa);
+ REQUIRE(soa != NULL);
+ REQUIRE(soa->common.rdtype == type);
+ REQUIRE(soa->common.rdclass == rdclass);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ dns_name_toregion(&soa->origin, &region);
+ RETERR(isc_buffer_copyregion(target, &region));
+ dns_name_toregion(&soa->contact, &region);
+ RETERR(isc_buffer_copyregion(target, &region));
+ RETERR(uint32_tobuffer(soa->serial, target));
+ RETERR(uint32_tobuffer(soa->refresh, target));
+ RETERR(uint32_tobuffer(soa->retry, target));
+ RETERR(uint32_tobuffer(soa->expire, target));
+ return (uint32_tobuffer(soa->minimum, target));
+}
+
+static isc_result_t
+tostruct_soa(ARGS_TOSTRUCT) {
+ isc_region_t region;
+ dns_rdata_soa_t *soa = target;
+ dns_name_t name;
+
+ REQUIRE(rdata->type == dns_rdatatype_soa);
+ REQUIRE(soa != NULL);
+ REQUIRE(rdata->length != 0);
+
+ soa->common.rdclass = rdata->rdclass;
+ soa->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&soa->common, link);
+
+ dns_rdata_toregion(rdata, &region);
+
+ dns_name_init(&name, NULL);
+ dns_name_fromregion(&name, &region);
+ isc_region_consume(&region, name_length(&name));
+ dns_name_init(&soa->origin, NULL);
+ name_duporclone(&name, mctx, &soa->origin);
+
+ dns_name_fromregion(&name, &region);
+ isc_region_consume(&region, name_length(&name));
+ dns_name_init(&soa->contact, NULL);
+ name_duporclone(&name, mctx, &soa->contact);
+
+ soa->serial = uint32_fromregion(&region);
+ isc_region_consume(&region, 4);
+
+ soa->refresh = uint32_fromregion(&region);
+ isc_region_consume(&region, 4);
+
+ soa->retry = uint32_fromregion(&region);
+ isc_region_consume(&region, 4);
+
+ soa->expire = uint32_fromregion(&region);
+ isc_region_consume(&region, 4);
+
+ soa->minimum = uint32_fromregion(&region);
+
+ soa->mctx = mctx;
+ return (ISC_R_SUCCESS);
+}
+
+static void
+freestruct_soa(ARGS_FREESTRUCT) {
+ dns_rdata_soa_t *soa = source;
+
+ REQUIRE(soa != NULL);
+ REQUIRE(soa->common.rdtype == dns_rdatatype_soa);
+
+ if (soa->mctx == NULL) {
+ return;
+ }
+
+ dns_name_free(&soa->origin, soa->mctx);
+ dns_name_free(&soa->contact, soa->mctx);
+ soa->mctx = NULL;
+}
+
+static isc_result_t
+additionaldata_soa(ARGS_ADDLDATA) {
+ REQUIRE(rdata->type == dns_rdatatype_soa);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(add);
+ UNUSED(arg);
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+digest_soa(ARGS_DIGEST) {
+ isc_region_t r;
+ dns_name_t name;
+
+ REQUIRE(rdata->type == dns_rdatatype_soa);
+
+ dns_rdata_toregion(rdata, &r);
+
+ dns_name_init(&name, NULL);
+ dns_name_fromregion(&name, &r);
+ RETERR(dns_name_digest(&name, digest, arg));
+ isc_region_consume(&r, name_length(&name));
+
+ dns_name_init(&name, NULL);
+ dns_name_fromregion(&name, &r);
+ RETERR(dns_name_digest(&name, digest, arg));
+ isc_region_consume(&r, name_length(&name));
+
+ return ((digest)(arg, &r));
+}
+
+static bool
+checkowner_soa(ARGS_CHECKOWNER) {
+ REQUIRE(type == dns_rdatatype_soa);
+
+ UNUSED(name);
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (true);
+}
+
+static bool
+checknames_soa(ARGS_CHECKNAMES) {
+ isc_region_t region;
+ dns_name_t name;
+
+ REQUIRE(rdata->type == dns_rdatatype_soa);
+
+ UNUSED(owner);
+
+ dns_rdata_toregion(rdata, &region);
+ dns_name_init(&name, NULL);
+ dns_name_fromregion(&name, &region);
+ if (!dns_name_ishostname(&name, false)) {
+ if (bad != NULL) {
+ dns_name_clone(&name, bad);
+ }
+ return (false);
+ }
+ isc_region_consume(&region, name_length(&name));
+ dns_name_fromregion(&name, &region);
+ if (!dns_name_ismailbox(&name)) {
+ if (bad != NULL) {
+ dns_name_clone(&name, bad);
+ }
+ return (false);
+ }
+ return (true);
+}
+
+static int
+casecompare_soa(ARGS_COMPARE) {
+ return (compare_soa(rdata1, rdata2));
+}
+
+#endif /* RDATA_GENERIC_SOA_6_C */
diff --git a/lib/dns/rdata/generic/soa_6.h b/lib/dns/rdata/generic/soa_6.h
new file mode 100644
index 0000000..c6071bc
--- /dev/null
+++ b/lib/dns/rdata/generic/soa_6.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
+
+typedef struct dns_rdata_soa {
+ dns_rdatacommon_t common;
+ isc_mem_t *mctx;
+ dns_name_t origin;
+ dns_name_t contact;
+ uint32_t serial; /*%< host order */
+ uint32_t refresh; /*%< host order */
+ uint32_t retry; /*%< host order */
+ uint32_t expire; /*%< host order */
+ uint32_t minimum; /*%< host order */
+} dns_rdata_soa_t;
diff --git a/lib/dns/rdata/generic/spf_99.c b/lib/dns/rdata/generic/spf_99.c
new file mode 100644
index 0000000..20f939b
--- /dev/null
+++ b/lib/dns/rdata/generic/spf_99.c
@@ -0,0 +1,146 @@
+/*
+ * 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_SPF_99_C
+#define RDATA_GENERIC_SPF_99_C
+
+#define RRTYPE_SPF_ATTRIBUTES (0)
+
+static isc_result_t
+fromtext_spf(ARGS_FROMTEXT) {
+ REQUIRE(type == dns_rdatatype_spf);
+
+ return (generic_fromtext_txt(CALL_FROMTEXT));
+}
+
+static isc_result_t
+totext_spf(ARGS_TOTEXT) {
+ REQUIRE(rdata != NULL);
+ REQUIRE(rdata->type == dns_rdatatype_spf);
+
+ return (generic_totext_txt(CALL_TOTEXT));
+}
+
+static isc_result_t
+fromwire_spf(ARGS_FROMWIRE) {
+ REQUIRE(type == dns_rdatatype_spf);
+
+ return (generic_fromwire_txt(CALL_FROMWIRE));
+}
+
+static isc_result_t
+towire_spf(ARGS_TOWIRE) {
+ REQUIRE(rdata->type == dns_rdatatype_spf);
+
+ UNUSED(cctx);
+
+ return (mem_tobuffer(target, rdata->data, rdata->length));
+}
+
+static int
+compare_spf(ARGS_COMPARE) {
+ isc_region_t r1;
+ isc_region_t r2;
+
+ REQUIRE(rdata1->type == rdata2->type);
+ REQUIRE(rdata1->rdclass == rdata2->rdclass);
+ REQUIRE(rdata1->type == dns_rdatatype_spf);
+
+ dns_rdata_toregion(rdata1, &r1);
+ dns_rdata_toregion(rdata2, &r2);
+ return (isc_region_compare(&r1, &r2));
+}
+
+static isc_result_t
+fromstruct_spf(ARGS_FROMSTRUCT) {
+ REQUIRE(type == dns_rdatatype_spf);
+
+ return (generic_fromstruct_txt(CALL_FROMSTRUCT));
+}
+
+static isc_result_t
+tostruct_spf(ARGS_TOSTRUCT) {
+ dns_rdata_spf_t *spf = target;
+
+ REQUIRE(spf != NULL);
+ REQUIRE(rdata != NULL);
+ REQUIRE(rdata->type == dns_rdatatype_spf);
+
+ spf->common.rdclass = rdata->rdclass;
+ spf->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&spf->common, link);
+
+ return (generic_tostruct_txt(CALL_TOSTRUCT));
+}
+
+static void
+freestruct_spf(ARGS_FREESTRUCT) {
+ dns_rdata_spf_t *spf = source;
+
+ REQUIRE(spf != NULL);
+ REQUIRE(spf->common.rdtype == dns_rdatatype_spf);
+
+ generic_freestruct_txt(source);
+}
+
+static isc_result_t
+additionaldata_spf(ARGS_ADDLDATA) {
+ REQUIRE(rdata->type == dns_rdatatype_spf);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(add);
+ UNUSED(arg);
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+digest_spf(ARGS_DIGEST) {
+ isc_region_t r;
+
+ REQUIRE(rdata->type == dns_rdatatype_spf);
+
+ dns_rdata_toregion(rdata, &r);
+
+ return ((digest)(arg, &r));
+}
+
+static bool
+checkowner_spf(ARGS_CHECKOWNER) {
+ REQUIRE(type == dns_rdatatype_spf);
+
+ UNUSED(name);
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (true);
+}
+
+static bool
+checknames_spf(ARGS_CHECKNAMES) {
+ REQUIRE(rdata->type == dns_rdatatype_spf);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(bad);
+
+ return (true);
+}
+
+static int
+casecompare_spf(ARGS_COMPARE) {
+ return (compare_spf(rdata1, rdata2));
+}
+#endif /* RDATA_GENERIC_SPF_99_C */
diff --git a/lib/dns/rdata/generic/spf_99.h b/lib/dns/rdata/generic/spf_99.h
new file mode 100644
index 0000000..f0963ed
--- /dev/null
+++ b/lib/dns/rdata/generic/spf_99.h
@@ -0,0 +1,33 @@
+/*
+ * 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_spf_string {
+ uint8_t length;
+ unsigned char *data;
+} dns_rdata_spf_string_t;
+
+typedef struct dns_rdata_spf {
+ dns_rdatacommon_t common;
+ isc_mem_t *mctx;
+ unsigned char *txt;
+ uint16_t txt_len;
+ /* private */
+ uint16_t offset;
+} dns_rdata_spf_t;
+
+/*
+ * ISC_LANG_BEGINDECLS and ISC_LANG_ENDDECLS are already done
+ * via rdatastructpre.h and rdatastructsuf.h.
+ */
diff --git a/lib/dns/rdata/generic/sshfp_44.c b/lib/dns/rdata/generic/sshfp_44.c
new file mode 100644
index 0000000..7f1060a
--- /dev/null
+++ b/lib/dns/rdata/generic/sshfp_44.c
@@ -0,0 +1,297 @@
+/*
+ * 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.
+ */
+
+/* RFC 4255 */
+
+#ifndef RDATA_GENERIC_SSHFP_44_C
+#define RDATA_GENERIC_SSHFP_44_C
+
+#define RRTYPE_SSHFP_ATTRIBUTES (0)
+
+static isc_result_t
+fromtext_sshfp(ARGS_FROMTEXT) {
+ isc_token_t token;
+ int len = -1;
+
+ REQUIRE(type == dns_rdatatype_sshfp);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(origin);
+ UNUSED(options);
+ UNUSED(callbacks);
+
+ /*
+ * Algorithm.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
+ false));
+ if (token.value.as_ulong > 0xffU) {
+ RETTOK(ISC_R_RANGE);
+ }
+ RETERR(uint8_tobuffer(token.value.as_ulong, target));
+
+ /*
+ * Digest type.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
+ false));
+ if (token.value.as_ulong > 0xffU) {
+ RETTOK(ISC_R_RANGE);
+ }
+ RETERR(uint8_tobuffer(token.value.as_ulong, target));
+
+ /*
+ * Enforce known digest lengths.
+ */
+ switch (token.value.as_ulong) {
+ case 1:
+ len = ISC_SHA1_DIGESTLENGTH;
+ break;
+ case 2:
+ len = ISC_SHA256_DIGESTLENGTH;
+ break;
+ default:
+ break;
+ }
+
+ /*
+ * Digest.
+ */
+ return (isc_hex_tobuffer(lexer, target, len));
+}
+
+static isc_result_t
+totext_sshfp(ARGS_TOTEXT) {
+ isc_region_t sr;
+ char buf[sizeof("64000 ")];
+ unsigned int n;
+
+ REQUIRE(rdata->type == dns_rdatatype_sshfp);
+ REQUIRE(rdata->length != 0);
+
+ UNUSED(tctx);
+
+ dns_rdata_toregion(rdata, &sr);
+
+ /*
+ * Algorithm.
+ */
+ n = uint8_fromregion(&sr);
+ isc_region_consume(&sr, 1);
+ snprintf(buf, sizeof(buf), "%u ", n);
+ RETERR(str_totext(buf, target));
+
+ /*
+ * Digest type.
+ */
+ n = uint8_fromregion(&sr);
+ isc_region_consume(&sr, 1);
+ snprintf(buf, sizeof(buf), "%u", n);
+ RETERR(str_totext(buf, target));
+
+ if (sr.length == 0U) {
+ return (ISC_R_SUCCESS);
+ }
+
+ /*
+ * Digest.
+ */
+ if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) {
+ RETERR(str_totext(" (", target));
+ }
+ RETERR(str_totext(tctx->linebreak, target));
+ if (tctx->width == 0) { /* No splitting */
+ RETERR(isc_hex_totext(&sr, 0, "", target));
+ } else {
+ RETERR(isc_hex_totext(&sr, tctx->width - 2, tctx->linebreak,
+ target));
+ }
+ if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) {
+ RETERR(str_totext(" )", target));
+ }
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+fromwire_sshfp(ARGS_FROMWIRE) {
+ isc_region_t sr;
+
+ REQUIRE(type == dns_rdatatype_sshfp);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(dctx);
+ UNUSED(options);
+
+ isc_buffer_activeregion(source, &sr);
+ if (sr.length < 2) {
+ return (ISC_R_UNEXPECTEDEND);
+ }
+
+ if ((sr.base[1] == 1 && sr.length != ISC_SHA1_DIGESTLENGTH + 2) ||
+ (sr.base[1] == 2 && sr.length != ISC_SHA256_DIGESTLENGTH + 2))
+ {
+ return (DNS_R_FORMERR);
+ }
+
+ isc_buffer_forward(source, sr.length);
+ return (mem_tobuffer(target, sr.base, sr.length));
+}
+
+static isc_result_t
+towire_sshfp(ARGS_TOWIRE) {
+ isc_region_t sr;
+
+ REQUIRE(rdata->type == dns_rdatatype_sshfp);
+ REQUIRE(rdata->length != 0);
+
+ UNUSED(cctx);
+
+ dns_rdata_toregion(rdata, &sr);
+ return (mem_tobuffer(target, sr.base, sr.length));
+}
+
+static int
+compare_sshfp(ARGS_COMPARE) {
+ isc_region_t r1;
+ isc_region_t r2;
+
+ REQUIRE(rdata1->type == rdata2->type);
+ REQUIRE(rdata1->rdclass == rdata2->rdclass);
+ REQUIRE(rdata1->type == dns_rdatatype_sshfp);
+ REQUIRE(rdata1->length != 0);
+ REQUIRE(rdata2->length != 0);
+
+ dns_rdata_toregion(rdata1, &r1);
+ dns_rdata_toregion(rdata2, &r2);
+ return (isc_region_compare(&r1, &r2));
+}
+
+static isc_result_t
+fromstruct_sshfp(ARGS_FROMSTRUCT) {
+ dns_rdata_sshfp_t *sshfp = source;
+
+ REQUIRE(type == dns_rdatatype_sshfp);
+ REQUIRE(sshfp != NULL);
+ REQUIRE(sshfp->common.rdtype == type);
+ REQUIRE(sshfp->common.rdclass == rdclass);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ RETERR(uint8_tobuffer(sshfp->algorithm, target));
+ RETERR(uint8_tobuffer(sshfp->digest_type, target));
+
+ return (mem_tobuffer(target, sshfp->digest, sshfp->length));
+}
+
+static isc_result_t
+tostruct_sshfp(ARGS_TOSTRUCT) {
+ dns_rdata_sshfp_t *sshfp = target;
+ isc_region_t region;
+
+ REQUIRE(rdata->type == dns_rdatatype_sshfp);
+ REQUIRE(sshfp != NULL);
+ REQUIRE(rdata->length != 0);
+
+ sshfp->common.rdclass = rdata->rdclass;
+ sshfp->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&sshfp->common, link);
+
+ dns_rdata_toregion(rdata, &region);
+
+ sshfp->algorithm = uint8_fromregion(&region);
+ isc_region_consume(&region, 1);
+ sshfp->digest_type = uint8_fromregion(&region);
+ isc_region_consume(&region, 1);
+ sshfp->length = region.length;
+
+ sshfp->digest = mem_maybedup(mctx, region.base, region.length);
+ if (sshfp->digest == NULL) {
+ return (ISC_R_NOMEMORY);
+ }
+
+ sshfp->mctx = mctx;
+ return (ISC_R_SUCCESS);
+}
+
+static void
+freestruct_sshfp(ARGS_FREESTRUCT) {
+ dns_rdata_sshfp_t *sshfp = source;
+
+ REQUIRE(sshfp != NULL);
+ REQUIRE(sshfp->common.rdtype == dns_rdatatype_sshfp);
+
+ if (sshfp->mctx == NULL) {
+ return;
+ }
+
+ if (sshfp->digest != NULL) {
+ isc_mem_free(sshfp->mctx, sshfp->digest);
+ }
+ sshfp->mctx = NULL;
+}
+
+static isc_result_t
+additionaldata_sshfp(ARGS_ADDLDATA) {
+ REQUIRE(rdata->type == dns_rdatatype_sshfp);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(add);
+ UNUSED(arg);
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+digest_sshfp(ARGS_DIGEST) {
+ isc_region_t r;
+
+ REQUIRE(rdata->type == dns_rdatatype_sshfp);
+
+ dns_rdata_toregion(rdata, &r);
+
+ return ((digest)(arg, &r));
+}
+
+static bool
+checkowner_sshfp(ARGS_CHECKOWNER) {
+ REQUIRE(type == dns_rdatatype_sshfp);
+
+ UNUSED(name);
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (true);
+}
+
+static bool
+checknames_sshfp(ARGS_CHECKNAMES) {
+ REQUIRE(rdata->type == dns_rdatatype_sshfp);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(bad);
+
+ return (true);
+}
+
+static int
+casecompare_sshfp(ARGS_COMPARE) {
+ return (compare_sshfp(rdata1, rdata2));
+}
+
+#endif /* RDATA_GENERIC_SSHFP_44_C */
diff --git a/lib/dns/rdata/generic/sshfp_44.h b/lib/dns/rdata/generic/sshfp_44.h
new file mode 100644
index 0000000..a19806f
--- /dev/null
+++ b/lib/dns/rdata/generic/sshfp_44.h
@@ -0,0 +1,26 @@
+/*
+ * 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.
+ */
+
+/*!
+ * \brief Per RFC 4255 */
+
+#pragma once
+
+typedef struct dns_rdata_sshfp {
+ dns_rdatacommon_t common;
+ isc_mem_t *mctx;
+ uint8_t algorithm;
+ uint8_t digest_type;
+ uint16_t length;
+ unsigned char *digest;
+} dns_rdata_sshfp_t;
diff --git a/lib/dns/rdata/generic/ta_32768.c b/lib/dns/rdata/generic/ta_32768.c
new file mode 100644
index 0000000..4a0688c
--- /dev/null
+++ b/lib/dns/rdata/generic/ta_32768.c
@@ -0,0 +1,163 @@
+/*
+ * 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.
+ */
+
+/* http://www.watson.org/~weiler/INI1999-19.pdf */
+
+#ifndef RDATA_GENERIC_TA_32768_C
+#define RDATA_GENERIC_TA_32768_C
+
+#define RRTYPE_TA_ATTRIBUTES 0
+
+static isc_result_t
+fromtext_ta(ARGS_FROMTEXT) {
+ REQUIRE(type == dns_rdatatype_ta);
+
+ return (generic_fromtext_ds(CALL_FROMTEXT));
+}
+
+static isc_result_t
+totext_ta(ARGS_TOTEXT) {
+ REQUIRE(rdata->type == dns_rdatatype_ta);
+
+ return (generic_totext_ds(CALL_TOTEXT));
+}
+
+static isc_result_t
+fromwire_ta(ARGS_FROMWIRE) {
+ REQUIRE(type == dns_rdatatype_ta);
+
+ return (generic_fromwire_ds(CALL_FROMWIRE));
+}
+
+static isc_result_t
+towire_ta(ARGS_TOWIRE) {
+ isc_region_t sr;
+
+ REQUIRE(rdata->type == dns_rdatatype_ta);
+ REQUIRE(rdata->length != 0);
+
+ UNUSED(cctx);
+
+ dns_rdata_toregion(rdata, &sr);
+ return (mem_tobuffer(target, sr.base, sr.length));
+}
+
+static int
+compare_ta(ARGS_COMPARE) {
+ isc_region_t r1;
+ isc_region_t r2;
+
+ REQUIRE(rdata1->type == rdata2->type);
+ REQUIRE(rdata1->rdclass == rdata2->rdclass);
+ REQUIRE(rdata1->type == dns_rdatatype_ta);
+ REQUIRE(rdata1->length != 0);
+ REQUIRE(rdata2->length != 0);
+
+ dns_rdata_toregion(rdata1, &r1);
+ dns_rdata_toregion(rdata2, &r2);
+ return (isc_region_compare(&r1, &r2));
+}
+
+static isc_result_t
+fromstruct_ta(ARGS_FROMSTRUCT) {
+ REQUIRE(type == dns_rdatatype_ta);
+
+ return (generic_fromstruct_ds(CALL_FROMSTRUCT));
+}
+
+static isc_result_t
+tostruct_ta(ARGS_TOSTRUCT) {
+ dns_rdata_ds_t *ds = target;
+
+ REQUIRE(rdata->type == dns_rdatatype_ta);
+ REQUIRE(ds != NULL);
+
+ /*
+ * Checked by generic_tostruct_ds().
+ */
+ ds->common.rdclass = rdata->rdclass;
+ ds->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&ds->common, link);
+
+ return (generic_tostruct_ds(CALL_TOSTRUCT));
+}
+
+static void
+freestruct_ta(ARGS_FREESTRUCT) {
+ dns_rdata_ta_t *ds = source;
+
+ REQUIRE(ds != NULL);
+ REQUIRE(ds->common.rdtype == dns_rdatatype_ta);
+
+ if (ds->mctx == NULL) {
+ return;
+ }
+
+ if (ds->digest != NULL) {
+ isc_mem_free(ds->mctx, ds->digest);
+ }
+ ds->mctx = NULL;
+}
+
+static isc_result_t
+additionaldata_ta(ARGS_ADDLDATA) {
+ REQUIRE(rdata->type == dns_rdatatype_ta);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(add);
+ UNUSED(arg);
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+digest_ta(ARGS_DIGEST) {
+ isc_region_t r;
+
+ REQUIRE(rdata->type == dns_rdatatype_ta);
+
+ dns_rdata_toregion(rdata, &r);
+
+ return ((digest)(arg, &r));
+}
+
+static bool
+checkowner_ta(ARGS_CHECKOWNER) {
+ REQUIRE(type == dns_rdatatype_ta);
+
+ UNUSED(name);
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (true);
+}
+
+static bool
+checknames_ta(ARGS_CHECKNAMES) {
+ REQUIRE(rdata->type == dns_rdatatype_ta);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(bad);
+
+ return (true);
+}
+
+static int
+casecompare_ta(ARGS_COMPARE) {
+ return (compare_ta(rdata1, rdata2));
+}
+
+#endif /* RDATA_GENERIC_TA_32768_C */
diff --git a/lib/dns/rdata/generic/ta_32768.h b/lib/dns/rdata/generic/ta_32768.h
new file mode 100644
index 0000000..e9111c5
--- /dev/null
+++ b/lib/dns/rdata/generic/ta_32768.h
@@ -0,0 +1,19 @@
+/*
+ * 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
+
+/*
+ * TA records are identical to DS records.
+ */
+typedef struct dns_rdata_ds dns_rdata_ta_t;
diff --git a/lib/dns/rdata/generic/talink_58.c b/lib/dns/rdata/generic/talink_58.c
new file mode 100644
index 0000000..49ad8df
--- /dev/null
+++ b/lib/dns/rdata/generic/talink_58.c
@@ -0,0 +1,258 @@
+/*
+ * 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_TALINK_58_C
+#define RDATA_GENERIC_TALINK_58_C
+
+#define RRTYPE_TALINK_ATTRIBUTES 0
+
+static isc_result_t
+fromtext_talink(ARGS_FROMTEXT) {
+ isc_token_t token;
+ dns_name_t name;
+ isc_buffer_t buffer;
+ int i;
+
+ REQUIRE(type == dns_rdatatype_talink);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(callbacks);
+
+ if (origin == NULL) {
+ origin = dns_rootname;
+ }
+
+ for (i = 0; i < 2; i++) {
+ RETERR(isc_lex_getmastertoken(lexer, &token,
+ isc_tokentype_string, false));
+
+ dns_name_init(&name, NULL);
+ buffer_fromregion(&buffer, &token.value.as_region);
+ RETTOK(dns_name_fromtext(&name, &buffer, origin, options,
+ target));
+ }
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+totext_talink(ARGS_TOTEXT) {
+ isc_region_t dregion;
+ dns_name_t prev;
+ dns_name_t next;
+ dns_name_t prefix;
+ bool sub;
+
+ REQUIRE(rdata->type == dns_rdatatype_talink);
+ REQUIRE(rdata->length != 0);
+
+ dns_name_init(&prev, NULL);
+ dns_name_init(&next, NULL);
+ dns_name_init(&prefix, NULL);
+
+ dns_rdata_toregion(rdata, &dregion);
+
+ dns_name_fromregion(&prev, &dregion);
+ isc_region_consume(&dregion, name_length(&prev));
+
+ dns_name_fromregion(&next, &dregion);
+ isc_region_consume(&dregion, name_length(&next));
+
+ sub = name_prefix(&prev, tctx->origin, &prefix);
+ RETERR(dns_name_totext(&prefix, sub, target));
+
+ RETERR(str_totext(" ", target));
+
+ sub = name_prefix(&next, tctx->origin, &prefix);
+ return (dns_name_totext(&prefix, sub, target));
+}
+
+static isc_result_t
+fromwire_talink(ARGS_FROMWIRE) {
+ dns_name_t prev;
+ dns_name_t next;
+
+ REQUIRE(type == dns_rdatatype_talink);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ dns_decompress_setmethods(dctx, DNS_COMPRESS_NONE);
+
+ dns_name_init(&prev, NULL);
+ dns_name_init(&next, NULL);
+
+ RETERR(dns_name_fromwire(&prev, source, dctx, options, target));
+ return (dns_name_fromwire(&next, source, dctx, options, target));
+}
+
+static isc_result_t
+towire_talink(ARGS_TOWIRE) {
+ isc_region_t sregion;
+ dns_name_t prev;
+ dns_name_t next;
+ dns_offsets_t moffsets;
+ dns_offsets_t roffsets;
+
+ REQUIRE(rdata->type == dns_rdatatype_talink);
+ REQUIRE(rdata->length != 0);
+
+ dns_compress_setmethods(cctx, DNS_COMPRESS_NONE);
+
+ dns_name_init(&prev, moffsets);
+ dns_name_init(&next, roffsets);
+
+ dns_rdata_toregion(rdata, &sregion);
+
+ dns_name_fromregion(&prev, &sregion);
+ isc_region_consume(&sregion, name_length(&prev));
+ RETERR(dns_name_towire(&prev, cctx, target));
+
+ dns_name_fromregion(&next, &sregion);
+ isc_region_consume(&sregion, name_length(&next));
+ return (dns_name_towire(&next, cctx, target));
+}
+
+static int
+compare_talink(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_talink);
+ REQUIRE(rdata1->length != 0);
+ REQUIRE(rdata2->length != 0);
+
+ dns_rdata_toregion(rdata1, &region1);
+ dns_rdata_toregion(rdata2, &region2);
+ return (isc_region_compare(&region1, &region2));
+}
+
+static isc_result_t
+fromstruct_talink(ARGS_FROMSTRUCT) {
+ dns_rdata_talink_t *talink = source;
+ isc_region_t region;
+
+ REQUIRE(type == dns_rdatatype_talink);
+ REQUIRE(talink != NULL);
+ REQUIRE(talink->common.rdtype == type);
+ REQUIRE(talink->common.rdclass == rdclass);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ dns_name_toregion(&talink->prev, &region);
+ RETERR(isc_buffer_copyregion(target, &region));
+ dns_name_toregion(&talink->next, &region);
+ return (isc_buffer_copyregion(target, &region));
+}
+
+static isc_result_t
+tostruct_talink(ARGS_TOSTRUCT) {
+ isc_region_t region;
+ dns_rdata_talink_t *talink = target;
+ dns_name_t name;
+
+ REQUIRE(rdata->type == dns_rdatatype_talink);
+ REQUIRE(talink != NULL);
+ REQUIRE(rdata->length != 0);
+
+ talink->common.rdclass = rdata->rdclass;
+ talink->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&talink->common, link);
+
+ dns_rdata_toregion(rdata, &region);
+
+ dns_name_init(&name, NULL);
+ dns_name_fromregion(&name, &region);
+ isc_region_consume(&region, name_length(&name));
+ dns_name_init(&talink->prev, NULL);
+ name_duporclone(&name, mctx, &talink->prev);
+
+ dns_name_fromregion(&name, &region);
+ isc_region_consume(&region, name_length(&name));
+ dns_name_init(&talink->next, NULL);
+ name_duporclone(&name, mctx, &talink->next);
+
+ talink->mctx = mctx;
+ return (ISC_R_SUCCESS);
+}
+
+static void
+freestruct_talink(ARGS_FREESTRUCT) {
+ dns_rdata_talink_t *talink = source;
+
+ REQUIRE(talink != NULL);
+ REQUIRE(talink->common.rdtype == dns_rdatatype_talink);
+
+ if (talink->mctx == NULL) {
+ return;
+ }
+
+ dns_name_free(&talink->prev, talink->mctx);
+ dns_name_free(&talink->next, talink->mctx);
+ talink->mctx = NULL;
+}
+
+static isc_result_t
+additionaldata_talink(ARGS_ADDLDATA) {
+ REQUIRE(rdata->type == dns_rdatatype_talink);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(add);
+ UNUSED(arg);
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+digest_talink(ARGS_DIGEST) {
+ isc_region_t r;
+
+ REQUIRE(rdata->type == dns_rdatatype_talink);
+
+ dns_rdata_toregion(rdata, &r);
+ return ((digest)(arg, &r));
+}
+
+static bool
+checkowner_talink(ARGS_CHECKOWNER) {
+ REQUIRE(type == dns_rdatatype_talink);
+
+ UNUSED(name);
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (true);
+}
+
+static bool
+checknames_talink(ARGS_CHECKNAMES) {
+ REQUIRE(rdata->type == dns_rdatatype_talink);
+
+ UNUSED(bad);
+ UNUSED(owner);
+
+ return (true);
+}
+
+static int
+casecompare_talink(ARGS_COMPARE) {
+ return (compare_talink(rdata1, rdata2));
+}
+
+#endif /* RDATA_GENERIC_TALINK_58_C */
diff --git a/lib/dns/rdata/generic/talink_58.h b/lib/dns/rdata/generic/talink_58.h
new file mode 100644
index 0000000..5a7f075
--- /dev/null
+++ b/lib/dns/rdata/generic/talink_58.h
@@ -0,0 +1,25 @@
+/*
+ * 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.
+ */
+
+/*
+ * http://www.iana.org/assignments/dns-parameters/TALINK/talink-completed-template
+ */
+
+#pragma once
+
+typedef struct dns_rdata_talink {
+ dns_rdatacommon_t common;
+ isc_mem_t *mctx;
+ dns_name_t prev;
+ dns_name_t next;
+} dns_rdata_talink_t;
diff --git a/lib/dns/rdata/generic/tkey_249.c b/lib/dns/rdata/generic/tkey_249.c
new file mode 100644
index 0000000..3605a34
--- /dev/null
+++ b/lib/dns/rdata/generic/tkey_249.c
@@ -0,0 +1,581 @@
+/*
+ * 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.
+ */
+
+/* draft-ietf-dnsext-tkey-01.txt */
+
+#ifndef RDATA_GENERIC_TKEY_249_C
+#define RDATA_GENERIC_TKEY_249_C
+
+#define RRTYPE_TKEY_ATTRIBUTES (DNS_RDATATYPEATTR_META)
+
+static isc_result_t
+fromtext_tkey(ARGS_FROMTEXT) {
+ isc_token_t token;
+ dns_rcode_t rcode;
+ dns_name_t name;
+ isc_buffer_t buffer;
+ long i;
+ char *e;
+
+ REQUIRE(type == dns_rdatatype_tkey);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(callbacks);
+
+ /*
+ * Algorithm.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ false));
+ dns_name_init(&name, NULL);
+ buffer_fromregion(&buffer, &token.value.as_region);
+ if (origin == NULL) {
+ origin = dns_rootname;
+ }
+ RETTOK(dns_name_fromtext(&name, &buffer, origin, options, target));
+
+ /*
+ * Inception.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
+ false));
+ RETERR(uint32_tobuffer(token.value.as_ulong, target));
+
+ /*
+ * Expiration.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
+ false));
+ RETERR(uint32_tobuffer(token.value.as_ulong, target));
+
+ /*
+ * Mode.
+ */
+ 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));
+
+ /*
+ * Error.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ false));
+ if (dns_tsigrcode_fromtext(&rcode, &token.value.as_textregion) !=
+ ISC_R_SUCCESS)
+ {
+ i = strtol(DNS_AS_STR(token), &e, 10);
+ if (*e != 0) {
+ RETTOK(DNS_R_UNKNOWN);
+ }
+ if (i < 0 || i > 0xffff) {
+ RETTOK(ISC_R_RANGE);
+ }
+ rcode = (dns_rcode_t)i;
+ }
+ RETERR(uint16_tobuffer(rcode, target));
+
+ /*
+ * Key Size.
+ */
+ 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));
+
+ /*
+ * Key Data.
+ */
+ RETERR(isc_base64_tobuffer(lexer, target, (int)token.value.as_ulong));
+
+ /*
+ * Other Size.
+ */
+ 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));
+
+ /*
+ * Other Data.
+ */
+ return (isc_base64_tobuffer(lexer, target, (int)token.value.as_ulong));
+}
+
+static isc_result_t
+totext_tkey(ARGS_TOTEXT) {
+ isc_region_t sr, dr;
+ char buf[sizeof("4294967295 ")];
+ unsigned long n;
+ dns_name_t name;
+ dns_name_t prefix;
+ bool sub;
+
+ REQUIRE(rdata->type == dns_rdatatype_tkey);
+ REQUIRE(rdata->length != 0);
+
+ dns_rdata_toregion(rdata, &sr);
+
+ /*
+ * Algorithm.
+ */
+ dns_name_init(&name, NULL);
+ dns_name_init(&prefix, NULL);
+ dns_name_fromregion(&name, &sr);
+ sub = name_prefix(&name, tctx->origin, &prefix);
+ RETERR(dns_name_totext(&prefix, sub, target));
+ RETERR(str_totext(" ", target));
+ isc_region_consume(&sr, name_length(&name));
+
+ /*
+ * Inception.
+ */
+ n = uint32_fromregion(&sr);
+ isc_region_consume(&sr, 4);
+ snprintf(buf, sizeof(buf), "%lu ", n);
+ RETERR(str_totext(buf, target));
+
+ /*
+ * Expiration.
+ */
+ n = uint32_fromregion(&sr);
+ isc_region_consume(&sr, 4);
+ snprintf(buf, sizeof(buf), "%lu ", n);
+ RETERR(str_totext(buf, target));
+
+ /*
+ * Mode.
+ */
+ n = uint16_fromregion(&sr);
+ isc_region_consume(&sr, 2);
+ snprintf(buf, sizeof(buf), "%lu ", n);
+ RETERR(str_totext(buf, target));
+
+ /*
+ * Error.
+ */
+ n = uint16_fromregion(&sr);
+ isc_region_consume(&sr, 2);
+ if (dns_tsigrcode_totext((dns_rcode_t)n, target) == ISC_R_SUCCESS) {
+ RETERR(str_totext(" ", target));
+ } else {
+ snprintf(buf, sizeof(buf), "%lu ", n);
+ RETERR(str_totext(buf, target));
+ }
+
+ /*
+ * Key Size.
+ */
+ n = uint16_fromregion(&sr);
+ isc_region_consume(&sr, 2);
+ snprintf(buf, sizeof(buf), "%lu", n);
+ RETERR(str_totext(buf, target));
+
+ /*
+ * Key Data.
+ */
+ REQUIRE(n <= sr.length);
+ dr = sr;
+ dr.length = n;
+ if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) {
+ RETERR(str_totext(" (", target));
+ }
+ RETERR(str_totext(tctx->linebreak, target));
+ if (tctx->width == 0) { /* No splitting */
+ RETERR(isc_base64_totext(&dr, 60, "", target));
+ } else {
+ RETERR(isc_base64_totext(&dr, tctx->width - 2, tctx->linebreak,
+ target));
+ }
+ if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) {
+ RETERR(str_totext(" ) ", target));
+ } else {
+ RETERR(str_totext(" ", target));
+ }
+ isc_region_consume(&sr, n);
+
+ /*
+ * Other Size.
+ */
+ n = uint16_fromregion(&sr);
+ isc_region_consume(&sr, 2);
+ snprintf(buf, sizeof(buf), "%lu", n);
+ RETERR(str_totext(buf, target));
+
+ /*
+ * Other Data.
+ */
+ REQUIRE(n <= sr.length);
+ if (n != 0U) {
+ dr = sr;
+ dr.length = n;
+ if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) {
+ RETERR(str_totext(" (", target));
+ }
+ RETERR(str_totext(tctx->linebreak, target));
+ if (tctx->width == 0) { /* No splitting */
+ RETERR(isc_base64_totext(&dr, 60, "", target));
+ } else {
+ RETERR(isc_base64_totext(&dr, tctx->width - 2,
+ tctx->linebreak, target));
+ }
+ if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) {
+ RETERR(str_totext(" )", target));
+ }
+ }
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+fromwire_tkey(ARGS_FROMWIRE) {
+ isc_region_t sr;
+ unsigned long n;
+ dns_name_t name;
+
+ REQUIRE(type == dns_rdatatype_tkey);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ dns_decompress_setmethods(dctx, DNS_COMPRESS_NONE);
+
+ /*
+ * Algorithm.
+ */
+ dns_name_init(&name, NULL);
+ RETERR(dns_name_fromwire(&name, source, dctx, options, target));
+
+ /*
+ * Inception: 4
+ * Expiration: 4
+ * Mode: 2
+ * Error: 2
+ */
+ isc_buffer_activeregion(source, &sr);
+ if (sr.length < 12) {
+ return (ISC_R_UNEXPECTEDEND);
+ }
+ RETERR(mem_tobuffer(target, sr.base, 12));
+ isc_region_consume(&sr, 12);
+ isc_buffer_forward(source, 12);
+
+ /*
+ * Key Length + Key Data.
+ */
+ if (sr.length < 2) {
+ return (ISC_R_UNEXPECTEDEND);
+ }
+ n = uint16_fromregion(&sr);
+ if (sr.length < n + 2) {
+ return (ISC_R_UNEXPECTEDEND);
+ }
+ RETERR(mem_tobuffer(target, sr.base, n + 2));
+ isc_region_consume(&sr, n + 2);
+ isc_buffer_forward(source, n + 2);
+
+ /*
+ * Other Length + Other Data.
+ */
+ if (sr.length < 2) {
+ return (ISC_R_UNEXPECTEDEND);
+ }
+ n = uint16_fromregion(&sr);
+ if (sr.length < n + 2) {
+ return (ISC_R_UNEXPECTEDEND);
+ }
+ isc_buffer_forward(source, n + 2);
+ return (mem_tobuffer(target, sr.base, n + 2));
+}
+
+static isc_result_t
+towire_tkey(ARGS_TOWIRE) {
+ isc_region_t sr;
+ dns_name_t name;
+ dns_offsets_t offsets;
+
+ REQUIRE(rdata->type == dns_rdatatype_tkey);
+ REQUIRE(rdata->length != 0);
+
+ dns_compress_setmethods(cctx, DNS_COMPRESS_NONE);
+ /*
+ * Algorithm.
+ */
+ dns_rdata_toregion(rdata, &sr);
+ dns_name_init(&name, offsets);
+ dns_name_fromregion(&name, &sr);
+ RETERR(dns_name_towire(&name, cctx, target));
+ isc_region_consume(&sr, name_length(&name));
+
+ return (mem_tobuffer(target, sr.base, sr.length));
+}
+
+static int
+compare_tkey(ARGS_COMPARE) {
+ isc_region_t r1;
+ isc_region_t r2;
+ dns_name_t name1;
+ dns_name_t name2;
+ int order;
+
+ REQUIRE(rdata1->type == rdata2->type);
+ REQUIRE(rdata1->rdclass == rdata2->rdclass);
+ REQUIRE(rdata1->type == dns_rdatatype_tkey);
+ REQUIRE(rdata1->length != 0);
+ REQUIRE(rdata2->length != 0);
+
+ /*
+ * Algorithm.
+ */
+ dns_rdata_toregion(rdata1, &r1);
+ dns_rdata_toregion(rdata2, &r2);
+ dns_name_init(&name1, NULL);
+ dns_name_init(&name2, NULL);
+ dns_name_fromregion(&name1, &r1);
+ dns_name_fromregion(&name2, &r2);
+ if ((order = dns_name_rdatacompare(&name1, &name2)) != 0) {
+ return (order);
+ }
+ isc_region_consume(&r1, name_length(&name1));
+ isc_region_consume(&r2, name_length(&name2));
+ return (isc_region_compare(&r1, &r2));
+}
+
+static isc_result_t
+fromstruct_tkey(ARGS_FROMSTRUCT) {
+ dns_rdata_tkey_t *tkey = source;
+
+ REQUIRE(type == dns_rdatatype_tkey);
+ REQUIRE(tkey != NULL);
+ REQUIRE(tkey->common.rdtype == type);
+ REQUIRE(tkey->common.rdclass == rdclass);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ /*
+ * Algorithm Name.
+ */
+ RETERR(name_tobuffer(&tkey->algorithm, target));
+
+ /*
+ * Inception: 32 bits.
+ */
+ RETERR(uint32_tobuffer(tkey->inception, target));
+
+ /*
+ * Expire: 32 bits.
+ */
+ RETERR(uint32_tobuffer(tkey->expire, target));
+
+ /*
+ * Mode: 16 bits.
+ */
+ RETERR(uint16_tobuffer(tkey->mode, target));
+
+ /*
+ * Error: 16 bits.
+ */
+ RETERR(uint16_tobuffer(tkey->error, target));
+
+ /*
+ * Key size: 16 bits.
+ */
+ RETERR(uint16_tobuffer(tkey->keylen, target));
+
+ /*
+ * Key.
+ */
+ RETERR(mem_tobuffer(target, tkey->key, tkey->keylen));
+
+ /*
+ * Other size: 16 bits.
+ */
+ RETERR(uint16_tobuffer(tkey->otherlen, target));
+
+ /*
+ * Other data.
+ */
+ return (mem_tobuffer(target, tkey->other, tkey->otherlen));
+}
+
+static isc_result_t
+tostruct_tkey(ARGS_TOSTRUCT) {
+ dns_rdata_tkey_t *tkey = target;
+ dns_name_t alg;
+ isc_region_t sr;
+
+ REQUIRE(rdata->type == dns_rdatatype_tkey);
+ REQUIRE(tkey != NULL);
+ REQUIRE(rdata->length != 0);
+
+ tkey->common.rdclass = rdata->rdclass;
+ tkey->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&tkey->common, link);
+
+ dns_rdata_toregion(rdata, &sr);
+
+ /*
+ * Algorithm Name.
+ */
+ dns_name_init(&alg, NULL);
+ dns_name_fromregion(&alg, &sr);
+ dns_name_init(&tkey->algorithm, NULL);
+ name_duporclone(&alg, mctx, &tkey->algorithm);
+ isc_region_consume(&sr, name_length(&tkey->algorithm));
+
+ /*
+ * Inception.
+ */
+ tkey->inception = uint32_fromregion(&sr);
+ isc_region_consume(&sr, 4);
+
+ /*
+ * Expire.
+ */
+ tkey->expire = uint32_fromregion(&sr);
+ isc_region_consume(&sr, 4);
+
+ /*
+ * Mode.
+ */
+ tkey->mode = uint16_fromregion(&sr);
+ isc_region_consume(&sr, 2);
+
+ /*
+ * Error.
+ */
+ tkey->error = uint16_fromregion(&sr);
+ isc_region_consume(&sr, 2);
+
+ /*
+ * Key size.
+ */
+ tkey->keylen = uint16_fromregion(&sr);
+ isc_region_consume(&sr, 2);
+
+ /*
+ * Key.
+ */
+ INSIST(tkey->keylen + 2U <= sr.length);
+ tkey->key = mem_maybedup(mctx, sr.base, tkey->keylen);
+ if (tkey->key == NULL) {
+ goto cleanup;
+ }
+ isc_region_consume(&sr, tkey->keylen);
+
+ /*
+ * Other size.
+ */
+ tkey->otherlen = uint16_fromregion(&sr);
+ isc_region_consume(&sr, 2);
+
+ /*
+ * Other.
+ */
+ INSIST(tkey->otherlen <= sr.length);
+ tkey->other = mem_maybedup(mctx, sr.base, tkey->otherlen);
+ if (tkey->other == NULL) {
+ goto cleanup;
+ }
+
+ tkey->mctx = mctx;
+ return (ISC_R_SUCCESS);
+
+cleanup:
+ if (mctx != NULL) {
+ dns_name_free(&tkey->algorithm, mctx);
+ }
+ if (mctx != NULL && tkey->key != NULL) {
+ isc_mem_free(mctx, tkey->key);
+ }
+ return (ISC_R_NOMEMORY);
+}
+
+static void
+freestruct_tkey(ARGS_FREESTRUCT) {
+ dns_rdata_tkey_t *tkey = (dns_rdata_tkey_t *)source;
+
+ REQUIRE(tkey != NULL);
+
+ if (tkey->mctx == NULL) {
+ return;
+ }
+
+ dns_name_free(&tkey->algorithm, tkey->mctx);
+ if (tkey->key != NULL) {
+ isc_mem_free(tkey->mctx, tkey->key);
+ }
+ if (tkey->other != NULL) {
+ isc_mem_free(tkey->mctx, tkey->other);
+ }
+ tkey->mctx = NULL;
+}
+
+static isc_result_t
+additionaldata_tkey(ARGS_ADDLDATA) {
+ REQUIRE(rdata->type == dns_rdatatype_tkey);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(add);
+ UNUSED(arg);
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+digest_tkey(ARGS_DIGEST) {
+ UNUSED(rdata);
+ UNUSED(digest);
+ UNUSED(arg);
+
+ REQUIRE(rdata->type == dns_rdatatype_tkey);
+
+ return (ISC_R_NOTIMPLEMENTED);
+}
+
+static bool
+checkowner_tkey(ARGS_CHECKOWNER) {
+ REQUIRE(type == dns_rdatatype_tkey);
+
+ UNUSED(name);
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (true);
+}
+
+static bool
+checknames_tkey(ARGS_CHECKNAMES) {
+ REQUIRE(rdata->type == dns_rdatatype_tkey);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(bad);
+
+ return (true);
+}
+
+static int
+casecompare_tkey(ARGS_COMPARE) {
+ return (compare_tkey(rdata1, rdata2));
+}
+#endif /* RDATA_GENERIC_TKEY_249_C */
diff --git a/lib/dns/rdata/generic/tkey_249.h b/lib/dns/rdata/generic/tkey_249.h
new file mode 100644
index 0000000..8edd074
--- /dev/null
+++ b/lib/dns/rdata/generic/tkey_249.h
@@ -0,0 +1,31 @@
+/*
+ * 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
+
+/*!
+ * \brief Per draft-ietf-dnsind-tkey-00.txt */
+
+typedef struct dns_rdata_tkey {
+ dns_rdatacommon_t common;
+ isc_mem_t *mctx;
+ dns_name_t algorithm;
+ uint32_t inception;
+ uint32_t expire;
+ uint16_t mode;
+ uint16_t error;
+ uint16_t keylen;
+ unsigned char *key;
+ uint16_t otherlen;
+ unsigned char *other;
+} dns_rdata_tkey_t;
diff --git a/lib/dns/rdata/generic/tlsa_52.c b/lib/dns/rdata/generic/tlsa_52.c
new file mode 100644
index 0000000..8489dd9
--- /dev/null
+++ b/lib/dns/rdata/generic/tlsa_52.c
@@ -0,0 +1,340 @@
+/*
+ * 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.
+ */
+
+/* rfc6698.txt */
+
+#ifndef RDATA_GENERIC_TLSA_52_C
+#define RDATA_GENERIC_TLSA_52_C
+
+#define RRTYPE_TLSA_ATTRIBUTES 0
+
+static isc_result_t
+generic_fromtext_tlsa(ARGS_FROMTEXT) {
+ isc_token_t token;
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(origin);
+ UNUSED(options);
+ UNUSED(callbacks);
+
+ /*
+ * Certificate Usage.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
+ false));
+ if (token.value.as_ulong > 0xffU) {
+ RETTOK(ISC_R_RANGE);
+ }
+ RETERR(uint8_tobuffer(token.value.as_ulong, target));
+
+ /*
+ * Selector.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
+ false));
+ if (token.value.as_ulong > 0xffU) {
+ RETTOK(ISC_R_RANGE);
+ }
+ RETERR(uint8_tobuffer(token.value.as_ulong, target));
+
+ /*
+ * Matching type.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
+ false));
+ if (token.value.as_ulong > 0xffU) {
+ RETTOK(ISC_R_RANGE);
+ }
+ RETERR(uint8_tobuffer(token.value.as_ulong, target));
+
+ /*
+ * Certificate Association Data.
+ */
+ return (isc_hex_tobuffer(lexer, target, -2));
+}
+
+static isc_result_t
+generic_totext_tlsa(ARGS_TOTEXT) {
+ isc_region_t sr;
+ char buf[sizeof("64000 ")];
+ unsigned int n;
+
+ REQUIRE(rdata->length != 0);
+
+ UNUSED(tctx);
+
+ dns_rdata_toregion(rdata, &sr);
+
+ /*
+ * Certificate Usage.
+ */
+ n = uint8_fromregion(&sr);
+ isc_region_consume(&sr, 1);
+ snprintf(buf, sizeof(buf), "%u ", n);
+ RETERR(str_totext(buf, target));
+
+ /*
+ * Selector.
+ */
+ n = uint8_fromregion(&sr);
+ isc_region_consume(&sr, 1);
+ snprintf(buf, sizeof(buf), "%u ", n);
+ RETERR(str_totext(buf, target));
+
+ /*
+ * Matching type.
+ */
+ n = uint8_fromregion(&sr);
+ isc_region_consume(&sr, 1);
+ snprintf(buf, sizeof(buf), "%u", n);
+ RETERR(str_totext(buf, target));
+
+ /*
+ * Certificate Association Data.
+ */
+ if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) {
+ RETERR(str_totext(" (", target));
+ }
+ RETERR(str_totext(tctx->linebreak, target));
+ if (tctx->width == 0) { /* No splitting */
+ RETERR(isc_hex_totext(&sr, 0, "", target));
+ } else {
+ RETERR(isc_hex_totext(&sr, tctx->width - 2, tctx->linebreak,
+ target));
+ }
+ if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) {
+ RETERR(str_totext(" )", target));
+ }
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+generic_fromwire_tlsa(ARGS_FROMWIRE) {
+ isc_region_t sr;
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(dctx);
+ UNUSED(options);
+
+ isc_buffer_activeregion(source, &sr);
+
+ /* Usage(1), Selector(1), Type(1), Data(1+) */
+ if (sr.length < 4) {
+ return (ISC_R_UNEXPECTEDEND);
+ }
+
+ isc_buffer_forward(source, sr.length);
+ return (mem_tobuffer(target, sr.base, sr.length));
+}
+
+static isc_result_t
+fromtext_tlsa(ARGS_FROMTEXT) {
+ REQUIRE(type == dns_rdatatype_tlsa);
+
+ return (generic_fromtext_tlsa(CALL_FROMTEXT));
+}
+
+static isc_result_t
+totext_tlsa(ARGS_TOTEXT) {
+ REQUIRE(rdata->type == dns_rdatatype_tlsa);
+
+ return (generic_totext_tlsa(CALL_TOTEXT));
+}
+
+static isc_result_t
+fromwire_tlsa(ARGS_FROMWIRE) {
+ REQUIRE(type == dns_rdatatype_tlsa);
+
+ return (generic_fromwire_tlsa(CALL_FROMWIRE));
+}
+
+static isc_result_t
+towire_tlsa(ARGS_TOWIRE) {
+ isc_region_t sr;
+
+ REQUIRE(rdata->type == dns_rdatatype_tlsa);
+ REQUIRE(rdata->length != 0);
+
+ UNUSED(cctx);
+
+ dns_rdata_toregion(rdata, &sr);
+ return (mem_tobuffer(target, sr.base, sr.length));
+}
+
+static int
+compare_tlsa(ARGS_COMPARE) {
+ isc_region_t r1;
+ isc_region_t r2;
+
+ REQUIRE(rdata1->type == rdata2->type);
+ REQUIRE(rdata1->rdclass == rdata2->rdclass);
+ REQUIRE(rdata1->type == dns_rdatatype_tlsa);
+ REQUIRE(rdata1->length != 0);
+ REQUIRE(rdata2->length != 0);
+
+ dns_rdata_toregion(rdata1, &r1);
+ dns_rdata_toregion(rdata2, &r2);
+ return (isc_region_compare(&r1, &r2));
+}
+
+static isc_result_t
+generic_fromstruct_tlsa(ARGS_FROMSTRUCT) {
+ dns_rdata_tlsa_t *tlsa = source;
+
+ REQUIRE(tlsa != NULL);
+ REQUIRE(tlsa->common.rdtype == type);
+ REQUIRE(tlsa->common.rdclass == rdclass);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ RETERR(uint8_tobuffer(tlsa->usage, target));
+ RETERR(uint8_tobuffer(tlsa->selector, target));
+ RETERR(uint8_tobuffer(tlsa->match, target));
+
+ return (mem_tobuffer(target, tlsa->data, tlsa->length));
+}
+
+static isc_result_t
+generic_tostruct_tlsa(ARGS_TOSTRUCT) {
+ dns_rdata_tlsa_t *tlsa = target;
+ isc_region_t region;
+
+ REQUIRE(tlsa != NULL);
+ REQUIRE(rdata->length != 0);
+
+ REQUIRE(tlsa != NULL);
+ REQUIRE(tlsa->common.rdclass == rdata->rdclass);
+ REQUIRE(tlsa->common.rdtype == rdata->type);
+ REQUIRE(!ISC_LINK_LINKED(&tlsa->common, link));
+
+ dns_rdata_toregion(rdata, &region);
+
+ tlsa->usage = uint8_fromregion(&region);
+ isc_region_consume(&region, 1);
+ tlsa->selector = uint8_fromregion(&region);
+ isc_region_consume(&region, 1);
+ tlsa->match = uint8_fromregion(&region);
+ isc_region_consume(&region, 1);
+ tlsa->length = region.length;
+
+ tlsa->data = mem_maybedup(mctx, region.base, region.length);
+ if (tlsa->data == NULL) {
+ return (ISC_R_NOMEMORY);
+ }
+
+ tlsa->mctx = mctx;
+ return (ISC_R_SUCCESS);
+}
+
+static void
+generic_freestruct_tlsa(ARGS_FREESTRUCT) {
+ dns_rdata_tlsa_t *tlsa = source;
+
+ REQUIRE(tlsa != NULL);
+
+ if (tlsa->mctx == NULL) {
+ return;
+ }
+
+ if (tlsa->data != NULL) {
+ isc_mem_free(tlsa->mctx, tlsa->data);
+ }
+ tlsa->mctx = NULL;
+}
+
+static isc_result_t
+fromstruct_tlsa(ARGS_FROMSTRUCT) {
+ REQUIRE(type == dns_rdatatype_tlsa);
+
+ return (generic_fromstruct_tlsa(CALL_FROMSTRUCT));
+}
+
+static isc_result_t
+tostruct_tlsa(ARGS_TOSTRUCT) {
+ dns_rdata_tlsa_t *tlsa = target;
+
+ REQUIRE(rdata->type == dns_rdatatype_tlsa);
+ REQUIRE(tlsa != NULL);
+
+ tlsa->common.rdclass = rdata->rdclass;
+ tlsa->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&tlsa->common, link);
+
+ return (generic_tostruct_tlsa(CALL_TOSTRUCT));
+}
+
+static void
+freestruct_tlsa(ARGS_FREESTRUCT) {
+ dns_rdata_tlsa_t *tlsa = source;
+
+ REQUIRE(tlsa != NULL);
+ REQUIRE(tlsa->common.rdtype == dns_rdatatype_tlsa);
+
+ generic_freestruct_tlsa(source);
+}
+
+static isc_result_t
+additionaldata_tlsa(ARGS_ADDLDATA) {
+ REQUIRE(rdata->type == dns_rdatatype_tlsa);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(add);
+ UNUSED(arg);
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+digest_tlsa(ARGS_DIGEST) {
+ isc_region_t r;
+
+ REQUIRE(rdata->type == dns_rdatatype_tlsa);
+
+ dns_rdata_toregion(rdata, &r);
+
+ return ((digest)(arg, &r));
+}
+
+static bool
+checkowner_tlsa(ARGS_CHECKOWNER) {
+ REQUIRE(type == dns_rdatatype_tlsa);
+
+ UNUSED(name);
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (true);
+}
+
+static bool
+checknames_tlsa(ARGS_CHECKNAMES) {
+ REQUIRE(rdata->type == dns_rdatatype_tlsa);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(bad);
+
+ return (true);
+}
+
+static int
+casecompare_tlsa(ARGS_COMPARE) {
+ return (compare_tlsa(rdata1, rdata2));
+}
+
+#endif /* RDATA_GENERIC_TLSA_52_C */
diff --git a/lib/dns/rdata/generic/tlsa_52.h b/lib/dns/rdata/generic/tlsa_52.h
new file mode 100644
index 0000000..fd75f95
--- /dev/null
+++ b/lib/dns/rdata/generic/tlsa_52.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
+
+/*!
+ * \brief per rfc6698.txt
+ */
+typedef struct dns_rdata_tlsa {
+ dns_rdatacommon_t common;
+ isc_mem_t *mctx;
+ uint8_t usage;
+ uint8_t selector;
+ uint8_t match;
+ uint16_t length;
+ unsigned char *data;
+} dns_rdata_tlsa_t;
diff --git a/lib/dns/rdata/generic/txt_16.c b/lib/dns/rdata/generic/txt_16.c
new file mode 100644
index 0000000..75f359e
--- /dev/null
+++ b/lib/dns/rdata/generic/txt_16.c
@@ -0,0 +1,360 @@
+/*
+ * 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_TXT_16_C
+#define RDATA_GENERIC_TXT_16_C
+
+#define RRTYPE_TXT_ATTRIBUTES (0)
+
+static isc_result_t
+generic_fromtext_txt(ARGS_FROMTEXT) {
+ isc_token_t token;
+ int strings;
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(origin);
+ UNUSED(options);
+ UNUSED(callbacks);
+
+ strings = 0;
+ if ((options & DNS_RDATA_UNKNOWNESCAPE) != 0) {
+ isc_textregion_t r;
+ DE_CONST("#", r.base);
+ r.length = 1;
+ RETERR(txt_fromtext(&r, target));
+ strings++;
+ }
+ for (;;) {
+ RETERR(isc_lex_getmastertoken(lexer, &token,
+ isc_tokentype_qstring, true));
+ if (token.type != isc_tokentype_qstring &&
+ token.type != isc_tokentype_string)
+ {
+ break;
+ }
+ RETTOK(txt_fromtext(&token.value.as_textregion, target));
+ strings++;
+ }
+ /* Let upper layer handle eol/eof. */
+ isc_lex_ungettoken(lexer, &token);
+ return (strings == 0 ? ISC_R_UNEXPECTEDEND : ISC_R_SUCCESS);
+}
+
+static isc_result_t
+generic_totext_txt(ARGS_TOTEXT) {
+ isc_region_t region;
+
+ UNUSED(tctx);
+
+ dns_rdata_toregion(rdata, &region);
+
+ while (region.length > 0) {
+ RETERR(txt_totext(&region, true, target));
+ if (region.length > 0) {
+ RETERR(str_totext(" ", target));
+ }
+ }
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+generic_fromwire_txt(ARGS_FROMWIRE) {
+ isc_result_t result;
+
+ UNUSED(type);
+ UNUSED(dctx);
+ UNUSED(rdclass);
+ UNUSED(options);
+
+ do {
+ result = txt_fromwire(source, target);
+ if (result != ISC_R_SUCCESS) {
+ return (result);
+ }
+ } while (!buffer_empty(source));
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+fromtext_txt(ARGS_FROMTEXT) {
+ REQUIRE(type == dns_rdatatype_txt);
+
+ return (generic_fromtext_txt(CALL_FROMTEXT));
+}
+
+static isc_result_t
+totext_txt(ARGS_TOTEXT) {
+ REQUIRE(rdata != NULL);
+ REQUIRE(rdata->type == dns_rdatatype_txt);
+
+ return (generic_totext_txt(CALL_TOTEXT));
+}
+
+static isc_result_t
+fromwire_txt(ARGS_FROMWIRE) {
+ REQUIRE(type == dns_rdatatype_txt);
+
+ return (generic_fromwire_txt(CALL_FROMWIRE));
+}
+
+static isc_result_t
+towire_txt(ARGS_TOWIRE) {
+ REQUIRE(rdata->type == dns_rdatatype_txt);
+
+ UNUSED(cctx);
+
+ return (mem_tobuffer(target, rdata->data, rdata->length));
+}
+
+static int
+compare_txt(ARGS_COMPARE) {
+ isc_region_t r1;
+ isc_region_t r2;
+
+ REQUIRE(rdata1->type == rdata2->type);
+ REQUIRE(rdata1->rdclass == rdata2->rdclass);
+ REQUIRE(rdata1->type == dns_rdatatype_txt);
+
+ dns_rdata_toregion(rdata1, &r1);
+ dns_rdata_toregion(rdata2, &r2);
+ return (isc_region_compare(&r1, &r2));
+}
+
+static isc_result_t
+generic_fromstruct_txt(ARGS_FROMSTRUCT) {
+ dns_rdata_txt_t *txt = source;
+ isc_region_t region;
+ uint8_t length;
+
+ REQUIRE(txt != NULL);
+ REQUIRE(txt->common.rdtype == type);
+ REQUIRE(txt->common.rdclass == rdclass);
+ REQUIRE(txt->txt != NULL && txt->txt_len != 0);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ region.base = txt->txt;
+ region.length = txt->txt_len;
+ while (region.length > 0) {
+ length = uint8_fromregion(&region);
+ isc_region_consume(&region, 1);
+ if (region.length < length) {
+ return (ISC_R_UNEXPECTEDEND);
+ }
+ isc_region_consume(&region, length);
+ }
+
+ return (mem_tobuffer(target, txt->txt, txt->txt_len));
+}
+
+static isc_result_t
+generic_tostruct_txt(ARGS_TOSTRUCT) {
+ dns_rdata_txt_t *txt = target;
+ isc_region_t r;
+
+ REQUIRE(txt != NULL);
+ REQUIRE(txt->common.rdclass == rdata->rdclass);
+ REQUIRE(txt->common.rdtype == rdata->type);
+ REQUIRE(!ISC_LINK_LINKED(&txt->common, link));
+
+ dns_rdata_toregion(rdata, &r);
+ txt->txt_len = r.length;
+ txt->txt = mem_maybedup(mctx, r.base, r.length);
+ if (txt->txt == NULL) {
+ return (ISC_R_NOMEMORY);
+ }
+
+ txt->offset = 0;
+ txt->mctx = mctx;
+ return (ISC_R_SUCCESS);
+}
+
+static void
+generic_freestruct_txt(ARGS_FREESTRUCT) {
+ dns_rdata_txt_t *txt = source;
+
+ REQUIRE(txt != NULL);
+
+ if (txt->mctx == NULL) {
+ return;
+ }
+
+ if (txt->txt != NULL) {
+ isc_mem_free(txt->mctx, txt->txt);
+ }
+ txt->mctx = NULL;
+}
+
+static isc_result_t
+fromstruct_txt(ARGS_FROMSTRUCT) {
+ REQUIRE(type == dns_rdatatype_txt);
+
+ return (generic_fromstruct_txt(CALL_FROMSTRUCT));
+}
+
+static isc_result_t
+tostruct_txt(ARGS_TOSTRUCT) {
+ dns_rdata_txt_t *txt = target;
+
+ REQUIRE(rdata->type == dns_rdatatype_txt);
+ REQUIRE(txt != NULL);
+
+ txt->common.rdclass = rdata->rdclass;
+ txt->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&txt->common, link);
+
+ return (generic_tostruct_txt(CALL_TOSTRUCT));
+}
+
+static void
+freestruct_txt(ARGS_FREESTRUCT) {
+ dns_rdata_txt_t *txt = source;
+
+ REQUIRE(txt != NULL);
+ REQUIRE(txt->common.rdtype == dns_rdatatype_txt);
+
+ generic_freestruct_txt(source);
+}
+
+static isc_result_t
+additionaldata_txt(ARGS_ADDLDATA) {
+ REQUIRE(rdata->type == dns_rdatatype_txt);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(add);
+ UNUSED(arg);
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+digest_txt(ARGS_DIGEST) {
+ isc_region_t r;
+
+ REQUIRE(rdata->type == dns_rdatatype_txt);
+
+ dns_rdata_toregion(rdata, &r);
+
+ return ((digest)(arg, &r));
+}
+
+static bool
+checkowner_txt(ARGS_CHECKOWNER) {
+ REQUIRE(type == dns_rdatatype_txt);
+
+ UNUSED(name);
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (true);
+}
+
+static bool
+checknames_txt(ARGS_CHECKNAMES) {
+ REQUIRE(rdata->type == dns_rdatatype_txt);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(bad);
+
+ return (true);
+}
+
+static int
+casecompare_txt(ARGS_COMPARE) {
+ return (compare_txt(rdata1, rdata2));
+}
+
+static isc_result_t
+generic_txt_first(dns_rdata_txt_t *txt) {
+ REQUIRE(txt != NULL);
+ REQUIRE(txt->txt != NULL || txt->txt_len == 0);
+
+ if (txt->txt_len == 0) {
+ return (ISC_R_NOMORE);
+ }
+
+ txt->offset = 0;
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+generic_txt_next(dns_rdata_txt_t *txt) {
+ isc_region_t r;
+ uint8_t length;
+
+ REQUIRE(txt != NULL);
+ REQUIRE(txt->txt != NULL && txt->txt_len != 0);
+
+ INSIST(txt->offset + 1 <= txt->txt_len);
+ r.base = txt->txt + txt->offset;
+ r.length = txt->txt_len - txt->offset;
+ length = uint8_fromregion(&r);
+ INSIST(txt->offset + 1 + length <= txt->txt_len);
+ txt->offset = txt->offset + 1 + length;
+ if (txt->offset == txt->txt_len) {
+ return (ISC_R_NOMORE);
+ }
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+generic_txt_current(dns_rdata_txt_t *txt, dns_rdata_txt_string_t *string) {
+ isc_region_t r;
+
+ REQUIRE(txt != NULL);
+ REQUIRE(string != NULL);
+ REQUIRE(txt->txt != NULL);
+ REQUIRE(txt->offset < txt->txt_len);
+
+ INSIST(txt->offset + 1 <= txt->txt_len);
+ r.base = txt->txt + txt->offset;
+ r.length = txt->txt_len - txt->offset;
+
+ string->length = uint8_fromregion(&r);
+ isc_region_consume(&r, 1);
+ string->data = r.base;
+ INSIST(txt->offset + 1 + string->length <= txt->txt_len);
+
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+dns_rdata_txt_first(dns_rdata_txt_t *txt) {
+ REQUIRE(txt != NULL);
+ REQUIRE(txt->common.rdtype == dns_rdatatype_txt);
+
+ return (generic_txt_first(txt));
+}
+
+isc_result_t
+dns_rdata_txt_next(dns_rdata_txt_t *txt) {
+ REQUIRE(txt != NULL);
+ REQUIRE(txt->common.rdtype == dns_rdatatype_txt);
+
+ return (generic_txt_next(txt));
+}
+
+isc_result_t
+dns_rdata_txt_current(dns_rdata_txt_t *txt, dns_rdata_txt_string_t *string) {
+ REQUIRE(txt != NULL);
+ REQUIRE(txt->common.rdtype == dns_rdatatype_txt);
+
+ return (generic_txt_current(txt, string));
+}
+#endif /* RDATA_GENERIC_TXT_16_C */
diff --git a/lib/dns/rdata/generic/txt_16.h b/lib/dns/rdata/generic/txt_16.h
new file mode 100644
index 0000000..3e4c58a
--- /dev/null
+++ b/lib/dns/rdata/generic/txt_16.h
@@ -0,0 +1,43 @@
+/*
+ * 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_txt_string {
+ uint8_t length;
+ unsigned char *data;
+} dns_rdata_txt_string_t;
+
+typedef struct dns_rdata_txt {
+ dns_rdatacommon_t common;
+ isc_mem_t *mctx;
+ unsigned char *txt;
+ uint16_t txt_len;
+ /* private */
+ uint16_t offset;
+} dns_rdata_txt_t;
+
+/*
+ * ISC_LANG_BEGINDECLS and ISC_LANG_ENDDECLS are already done
+ * via rdatastructpre.h and rdatastructsuf.h.
+ */
+
+isc_result_t
+dns_rdata_txt_first(dns_rdata_txt_t *);
+
+isc_result_t
+dns_rdata_txt_next(dns_rdata_txt_t *);
+
+isc_result_t
+dns_rdata_txt_current(dns_rdata_txt_t *, dns_rdata_txt_string_t *);
diff --git a/lib/dns/rdata/generic/uri_256.c b/lib/dns/rdata/generic/uri_256.c
new file mode 100644
index 0000000..4618823
--- /dev/null
+++ b/lib/dns/rdata/generic/uri_256.c
@@ -0,0 +1,319 @@
+/*
+ * 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 GENERIC_URI_256_C
+#define GENERIC_URI_256_C 1
+
+#define RRTYPE_URI_ATTRIBUTES (0)
+
+static isc_result_t
+fromtext_uri(ARGS_FROMTEXT) {
+ isc_token_t token;
+
+ REQUIRE(type == dns_rdatatype_uri);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(origin);
+ UNUSED(options);
+ UNUSED(callbacks);
+
+ /*
+ * Priority
+ */
+ 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));
+
+ /*
+ * Weight
+ */
+ 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 URI
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_qstring,
+ false));
+ if (token.type != isc_tokentype_qstring) {
+ RETTOK(DNS_R_SYNTAX);
+ }
+ RETTOK(multitxt_fromtext(&token.value.as_textregion, target));
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+totext_uri(ARGS_TOTEXT) {
+ isc_region_t region;
+ unsigned short priority, weight;
+ char buf[sizeof("65000 ")];
+
+ UNUSED(tctx);
+
+ REQUIRE(rdata->type == dns_rdatatype_uri);
+ REQUIRE(rdata->length != 0);
+
+ dns_rdata_toregion(rdata, &region);
+
+ /*
+ * Priority
+ */
+ priority = uint16_fromregion(&region);
+ isc_region_consume(&region, 2);
+ snprintf(buf, sizeof(buf), "%u ", priority);
+ RETERR(str_totext(buf, target));
+
+ /*
+ * Weight
+ */
+ weight = uint16_fromregion(&region);
+ isc_region_consume(&region, 2);
+ snprintf(buf, sizeof(buf), "%u ", weight);
+ RETERR(str_totext(buf, target));
+
+ /*
+ * Target URI
+ */
+ RETERR(multitxt_totext(&region, target));
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+fromwire_uri(ARGS_FROMWIRE) {
+ isc_region_t region;
+
+ REQUIRE(type == dns_rdatatype_uri);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(dctx);
+ UNUSED(options);
+
+ /*
+ * Priority, weight
+ */
+ isc_buffer_activeregion(source, &region);
+ if (region.length < 4) {
+ return (ISC_R_UNEXPECTEDEND);
+ }
+
+ /*
+ * Priority, weight and target URI
+ */
+ isc_buffer_forward(source, region.length);
+ return (mem_tobuffer(target, region.base, region.length));
+}
+
+static isc_result_t
+towire_uri(ARGS_TOWIRE) {
+ isc_region_t region;
+
+ REQUIRE(rdata->type == dns_rdatatype_uri);
+ REQUIRE(rdata->length != 0);
+
+ UNUSED(cctx);
+
+ dns_rdata_toregion(rdata, &region);
+ return (mem_tobuffer(target, region.base, region.length));
+}
+
+static int
+compare_uri(ARGS_COMPARE) {
+ isc_region_t r1;
+ isc_region_t r2;
+ int order;
+
+ REQUIRE(rdata1->type == rdata2->type);
+ REQUIRE(rdata1->rdclass == rdata2->rdclass);
+ REQUIRE(rdata1->type == dns_rdatatype_uri);
+ REQUIRE(rdata1->length != 0);
+ REQUIRE(rdata2->length != 0);
+
+ dns_rdata_toregion(rdata1, &r1);
+ dns_rdata_toregion(rdata2, &r2);
+
+ /*
+ * Priority
+ */
+ order = memcmp(r1.base, r2.base, 2);
+ if (order != 0) {
+ return (order < 0 ? -1 : 1);
+ }
+ isc_region_consume(&r1, 2);
+ isc_region_consume(&r2, 2);
+
+ /*
+ * Weight
+ */
+ order = memcmp(r1.base, r2.base, 2);
+ if (order != 0) {
+ return (order < 0 ? -1 : 1);
+ }
+ isc_region_consume(&r1, 2);
+ isc_region_consume(&r2, 2);
+
+ return (isc_region_compare(&r1, &r2));
+}
+
+static isc_result_t
+fromstruct_uri(ARGS_FROMSTRUCT) {
+ dns_rdata_uri_t *uri = source;
+
+ REQUIRE(type == dns_rdatatype_uri);
+ REQUIRE(uri != NULL);
+ REQUIRE(uri->common.rdtype == type);
+ REQUIRE(uri->common.rdclass == rdclass);
+ REQUIRE(uri->target != NULL && uri->tgt_len != 0);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ /*
+ * Priority
+ */
+ RETERR(uint16_tobuffer(uri->priority, target));
+
+ /*
+ * Weight
+ */
+ RETERR(uint16_tobuffer(uri->weight, target));
+
+ /*
+ * Target URI
+ */
+ return (mem_tobuffer(target, uri->target, uri->tgt_len));
+}
+
+static isc_result_t
+tostruct_uri(ARGS_TOSTRUCT) {
+ dns_rdata_uri_t *uri = target;
+ isc_region_t sr;
+
+ REQUIRE(rdata->type == dns_rdatatype_uri);
+ REQUIRE(uri != NULL);
+ REQUIRE(rdata->length != 0);
+
+ uri->common.rdclass = rdata->rdclass;
+ uri->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&uri->common, link);
+
+ dns_rdata_toregion(rdata, &sr);
+
+ /*
+ * Priority
+ */
+ if (sr.length < 2) {
+ return (ISC_R_UNEXPECTEDEND);
+ }
+ uri->priority = uint16_fromregion(&sr);
+ isc_region_consume(&sr, 2);
+
+ /*
+ * Weight
+ */
+ if (sr.length < 2) {
+ return (ISC_R_UNEXPECTEDEND);
+ }
+ uri->weight = uint16_fromregion(&sr);
+ isc_region_consume(&sr, 2);
+
+ /*
+ * Target URI
+ */
+ uri->tgt_len = sr.length;
+ uri->target = mem_maybedup(mctx, sr.base, sr.length);
+ if (uri->target == NULL) {
+ return (ISC_R_NOMEMORY);
+ }
+
+ uri->mctx = mctx;
+ return (ISC_R_SUCCESS);
+}
+
+static void
+freestruct_uri(ARGS_FREESTRUCT) {
+ dns_rdata_uri_t *uri = (dns_rdata_uri_t *)source;
+
+ REQUIRE(uri != NULL);
+ REQUIRE(uri->common.rdtype == dns_rdatatype_uri);
+
+ if (uri->mctx == NULL) {
+ return;
+ }
+
+ if (uri->target != NULL) {
+ isc_mem_free(uri->mctx, uri->target);
+ }
+ uri->mctx = NULL;
+}
+
+static isc_result_t
+additionaldata_uri(ARGS_ADDLDATA) {
+ REQUIRE(rdata->type == dns_rdatatype_uri);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(add);
+ UNUSED(arg);
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+digest_uri(ARGS_DIGEST) {
+ isc_region_t r;
+
+ REQUIRE(rdata->type == dns_rdatatype_uri);
+
+ dns_rdata_toregion(rdata, &r);
+
+ return ((digest)(arg, &r));
+}
+
+static bool
+checkowner_uri(ARGS_CHECKOWNER) {
+ REQUIRE(type == dns_rdatatype_uri);
+
+ UNUSED(name);
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (true);
+}
+
+static bool
+checknames_uri(ARGS_CHECKNAMES) {
+ REQUIRE(rdata->type == dns_rdatatype_uri);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(bad);
+
+ return (true);
+}
+
+static int
+casecompare_uri(ARGS_COMPARE) {
+ return (compare_uri(rdata1, rdata2));
+}
+
+#endif /* GENERIC_URI_256_C */
diff --git a/lib/dns/rdata/generic/uri_256.h b/lib/dns/rdata/generic/uri_256.h
new file mode 100644
index 0000000..be99e95
--- /dev/null
+++ b/lib/dns/rdata/generic/uri_256.h
@@ -0,0 +1,23 @@
+/*
+ * 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_uri {
+ dns_rdatacommon_t common;
+ isc_mem_t *mctx;
+ uint16_t priority;
+ uint16_t weight;
+ unsigned char *target;
+ uint16_t tgt_len;
+} dns_rdata_uri_t;
diff --git a/lib/dns/rdata/generic/x25_19.c b/lib/dns/rdata/generic/x25_19.c
new file mode 100644
index 0000000..a0fe705
--- /dev/null
+++ b/lib/dns/rdata/generic/x25_19.c
@@ -0,0 +1,233 @@
+/*
+ * 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.
+ */
+
+/* RFC1183 */
+
+#ifndef RDATA_GENERIC_X25_19_C
+#define RDATA_GENERIC_X25_19_C
+
+#define RRTYPE_X25_ATTRIBUTES (0)
+
+static isc_result_t
+fromtext_x25(ARGS_FROMTEXT) {
+ isc_token_t token;
+ unsigned int i;
+
+ REQUIRE(type == dns_rdatatype_x25);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(origin);
+ UNUSED(options);
+ UNUSED(callbacks);
+
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_qstring,
+ false));
+ if (token.value.as_textregion.length < 4) {
+ RETTOK(DNS_R_SYNTAX);
+ }
+ for (i = 0; i < token.value.as_textregion.length; i++) {
+ if (!isdigit((unsigned char)token.value.as_textregion.base[i]))
+ {
+ RETTOK(ISC_R_RANGE);
+ }
+ }
+ RETTOK(txt_fromtext(&token.value.as_textregion, target));
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+totext_x25(ARGS_TOTEXT) {
+ isc_region_t region;
+
+ UNUSED(tctx);
+
+ REQUIRE(rdata->type == dns_rdatatype_x25);
+ REQUIRE(rdata->length != 0);
+
+ dns_rdata_toregion(rdata, &region);
+ return (txt_totext(&region, true, target));
+}
+
+static isc_result_t
+fromwire_x25(ARGS_FROMWIRE) {
+ isc_region_t sr;
+ unsigned int i;
+
+ REQUIRE(type == dns_rdatatype_x25);
+
+ UNUSED(type);
+ UNUSED(dctx);
+ UNUSED(rdclass);
+ UNUSED(options);
+
+ isc_buffer_activeregion(source, &sr);
+ if (sr.length < 5 || sr.base[0] != (sr.length - 1)) {
+ return (DNS_R_FORMERR);
+ }
+ for (i = 1; i < sr.length; i++) {
+ if (sr.base[i] < 0x30 || sr.base[i] > 0x39) {
+ return (DNS_R_FORMERR);
+ }
+ }
+ return (txt_fromwire(source, target));
+}
+
+static isc_result_t
+towire_x25(ARGS_TOWIRE) {
+ UNUSED(cctx);
+
+ REQUIRE(rdata->type == dns_rdatatype_x25);
+ REQUIRE(rdata->length != 0);
+
+ return (mem_tobuffer(target, rdata->data, rdata->length));
+}
+
+static int
+compare_x25(ARGS_COMPARE) {
+ isc_region_t r1;
+ isc_region_t r2;
+
+ REQUIRE(rdata1->type == rdata2->type);
+ REQUIRE(rdata1->rdclass == rdata2->rdclass);
+ REQUIRE(rdata1->type == dns_rdatatype_x25);
+ REQUIRE(rdata1->length != 0);
+ REQUIRE(rdata2->length != 0);
+
+ dns_rdata_toregion(rdata1, &r1);
+ dns_rdata_toregion(rdata2, &r2);
+ return (isc_region_compare(&r1, &r2));
+}
+
+static isc_result_t
+fromstruct_x25(ARGS_FROMSTRUCT) {
+ dns_rdata_x25_t *x25 = source;
+ uint8_t i;
+
+ REQUIRE(type == dns_rdatatype_x25);
+ REQUIRE(x25 != NULL);
+ REQUIRE(x25->common.rdtype == type);
+ REQUIRE(x25->common.rdclass == rdclass);
+ REQUIRE(x25->x25 != NULL && x25->x25_len != 0);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ if (x25->x25_len < 4) {
+ return (ISC_R_RANGE);
+ }
+
+ for (i = 0; i < x25->x25_len; i++) {
+ if (!isdigit((unsigned char)x25->x25[i])) {
+ return (ISC_R_RANGE);
+ }
+ }
+
+ RETERR(uint8_tobuffer(x25->x25_len, target));
+ return (mem_tobuffer(target, x25->x25, x25->x25_len));
+}
+
+static isc_result_t
+tostruct_x25(ARGS_TOSTRUCT) {
+ dns_rdata_x25_t *x25 = target;
+ isc_region_t r;
+
+ REQUIRE(rdata->type == dns_rdatatype_x25);
+ REQUIRE(x25 != NULL);
+ REQUIRE(rdata->length != 0);
+
+ x25->common.rdclass = rdata->rdclass;
+ x25->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&x25->common, link);
+
+ dns_rdata_toregion(rdata, &r);
+ x25->x25_len = uint8_fromregion(&r);
+ isc_region_consume(&r, 1);
+ x25->x25 = mem_maybedup(mctx, r.base, x25->x25_len);
+ if (x25->x25 == NULL) {
+ return (ISC_R_NOMEMORY);
+ }
+
+ x25->mctx = mctx;
+ return (ISC_R_SUCCESS);
+}
+
+static void
+freestruct_x25(ARGS_FREESTRUCT) {
+ dns_rdata_x25_t *x25 = source;
+
+ REQUIRE(x25 != NULL);
+ REQUIRE(x25->common.rdtype == dns_rdatatype_x25);
+
+ if (x25->mctx == NULL) {
+ return;
+ }
+
+ if (x25->x25 != NULL) {
+ isc_mem_free(x25->mctx, x25->x25);
+ }
+ x25->mctx = NULL;
+}
+
+static isc_result_t
+additionaldata_x25(ARGS_ADDLDATA) {
+ REQUIRE(rdata->type == dns_rdatatype_x25);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(add);
+ UNUSED(arg);
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+digest_x25(ARGS_DIGEST) {
+ isc_region_t r;
+
+ REQUIRE(rdata->type == dns_rdatatype_x25);
+
+ dns_rdata_toregion(rdata, &r);
+
+ return ((digest)(arg, &r));
+}
+
+static bool
+checkowner_x25(ARGS_CHECKOWNER) {
+ REQUIRE(type == dns_rdatatype_x25);
+
+ UNUSED(name);
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (true);
+}
+
+static bool
+checknames_x25(ARGS_CHECKNAMES) {
+ REQUIRE(rdata->type == dns_rdatatype_x25);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(bad);
+
+ return (true);
+}
+
+static int
+casecompare_x25(ARGS_COMPARE) {
+ return (compare_x25(rdata1, rdata2));
+}
+
+#endif /* RDATA_GENERIC_X25_19_C */
diff --git a/lib/dns/rdata/generic/x25_19.h b/lib/dns/rdata/generic/x25_19.h
new file mode 100644
index 0000000..74a5ee1
--- /dev/null
+++ b/lib/dns/rdata/generic/x25_19.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
+
+/*!
+ * \brief Per RFC1183 */
+
+typedef struct dns_rdata_x25 {
+ dns_rdatacommon_t common;
+ isc_mem_t *mctx;
+ unsigned char *x25;
+ uint8_t x25_len;
+} dns_rdata_x25_t;
diff --git a/lib/dns/rdata/generic/zonemd_63.c b/lib/dns/rdata/generic/zonemd_63.c
new file mode 100644
index 0000000..1bf9573
--- /dev/null
+++ b/lib/dns/rdata/generic/zonemd_63.c
@@ -0,0 +1,351 @@
+/*
+ * 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.
+ */
+
+/* RFC 8976 */
+
+#ifndef RDATA_GENERIC_ZONEMD_63_C
+#define RDATA_GENERIC_ZONEMD_63_C
+
+#define RRTYPE_ZONEMD_ATTRIBUTES 0
+
+static isc_result_t
+fromtext_zonemd(ARGS_FROMTEXT) {
+ isc_token_t token;
+ int digest_type, length;
+ isc_buffer_t save;
+ isc_result_t result;
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(origin);
+ UNUSED(options);
+ UNUSED(callbacks);
+
+ /*
+ * Zone Serial.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
+ false));
+ RETERR(uint32_tobuffer(token.value.as_ulong, target));
+
+ /*
+ * Digest Scheme.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
+ false));
+ RETERR(uint8_tobuffer(token.value.as_ulong, target));
+
+ /*
+ * Digest Type.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
+ false));
+ digest_type = token.value.as_ulong;
+ RETERR(uint8_tobuffer(digest_type, target));
+
+ /*
+ * Digest.
+ */
+ switch (digest_type) {
+ case DNS_ZONEMD_DIGEST_SHA384:
+ length = ISC_SHA384_DIGESTLENGTH;
+ break;
+ case DNS_ZONEMD_DIGEST_SHA512:
+ length = ISC_SHA512_DIGESTLENGTH;
+ break;
+ default:
+ length = -2;
+ break;
+ }
+
+ save = *target;
+ result = isc_hex_tobuffer(lexer, target, length);
+ /* Minimum length of digest is 12 octets. */
+ if (isc_buffer_usedlength(target) - isc_buffer_usedlength(&save) < 12) {
+ return (ISC_R_UNEXPECTEDEND);
+ }
+ return (result);
+}
+
+static isc_result_t
+totext_zonemd(ARGS_TOTEXT) {
+ isc_region_t sr;
+ char buf[sizeof("0123456789")];
+ unsigned long num;
+
+ REQUIRE(rdata->length > 6);
+
+ UNUSED(tctx);
+
+ dns_rdata_toregion(rdata, &sr);
+
+ /*
+ * Zone Serial.
+ */
+ num = uint32_fromregion(&sr);
+ isc_region_consume(&sr, 4);
+ snprintf(buf, sizeof(buf), "%lu", num);
+ RETERR(str_totext(buf, target));
+
+ RETERR(str_totext(" ", target));
+
+ /*
+ * Digest scheme.
+ */
+ num = uint8_fromregion(&sr);
+ isc_region_consume(&sr, 1);
+ snprintf(buf, sizeof(buf), "%lu", num);
+ RETERR(str_totext(buf, target));
+
+ RETERR(str_totext(" ", target));
+
+ /*
+ * Digest type.
+ */
+ num = uint8_fromregion(&sr);
+ isc_region_consume(&sr, 1);
+ snprintf(buf, sizeof(buf), "%lu", num);
+ RETERR(str_totext(buf, target));
+
+ /*
+ * Digest.
+ */
+ if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) {
+ RETERR(str_totext(" (", target));
+ }
+ RETERR(str_totext(tctx->linebreak, target));
+ if ((tctx->flags & DNS_STYLEFLAG_NOCRYPTO) == 0) {
+ if (tctx->width == 0) { /* No splitting */
+ RETERR(isc_hex_totext(&sr, 0, "", target));
+ } else {
+ RETERR(isc_hex_totext(&sr, tctx->width - 2,
+ tctx->linebreak, target));
+ }
+ } else {
+ RETERR(str_totext("[omitted]", target));
+ }
+ if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) {
+ RETERR(str_totext(" )", target));
+ }
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+fromwire_zonemd(ARGS_FROMWIRE) {
+ isc_region_t sr;
+ size_t digestlen = 0;
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(dctx);
+ UNUSED(options);
+
+ isc_buffer_activeregion(source, &sr);
+
+ /*
+ * If we do not recognize the digest type, ensure that the digest
+ * meets minimum length (12).
+ *
+ * If we do recognize the digest type, ensure that the digest is of the
+ * correct length.
+ */
+ if (sr.length < 18) {
+ return (ISC_R_UNEXPECTEDEND);
+ }
+
+ switch (sr.base[5]) {
+ case DNS_ZONEMD_DIGEST_SHA384:
+ digestlen = ISC_SHA384_DIGESTLENGTH;
+ break;
+ case DNS_ZONEMD_DIGEST_SHA512:
+ digestlen = ISC_SHA512_DIGESTLENGTH;
+ break;
+ default:
+ break;
+ }
+
+ if (digestlen != 0 && sr.length < 6 + digestlen) {
+ return (ISC_R_UNEXPECTEDEND);
+ }
+
+ /*
+ * Only specify the number of octets to consume if we recognize the
+ * digest type.
+ *
+ * If there is extra data, dns_rdata_fromwire() will detect that.
+ */
+ if (digestlen != 0) {
+ sr.length = 6 + digestlen;
+ }
+
+ isc_buffer_forward(source, sr.length);
+ return (mem_tobuffer(target, sr.base, sr.length));
+}
+
+static isc_result_t
+towire_zonemd(ARGS_TOWIRE) {
+ isc_region_t sr;
+
+ REQUIRE(rdata->type == dns_rdatatype_zonemd);
+ REQUIRE(rdata->length != 0);
+
+ UNUSED(cctx);
+
+ dns_rdata_toregion(rdata, &sr);
+ return (mem_tobuffer(target, sr.base, sr.length));
+}
+
+static int
+compare_zonemd(ARGS_COMPARE) {
+ isc_region_t r1;
+ isc_region_t r2;
+
+ REQUIRE(rdata1->type == rdata2->type);
+ REQUIRE(rdata1->rdclass == rdata2->rdclass);
+ REQUIRE(rdata1->type == dns_rdatatype_zonemd);
+ REQUIRE(rdata1->length != 0);
+ REQUIRE(rdata2->length != 0);
+
+ dns_rdata_toregion(rdata1, &r1);
+ dns_rdata_toregion(rdata2, &r2);
+ return (isc_region_compare(&r1, &r2));
+}
+
+static isc_result_t
+fromstruct_zonemd(ARGS_FROMSTRUCT) {
+ dns_rdata_zonemd_t *zonemd = source;
+
+ REQUIRE(zonemd != NULL);
+ REQUIRE(zonemd->common.rdtype == type);
+ REQUIRE(zonemd->common.rdclass == rdclass);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ switch (zonemd->digest_type) {
+ case DNS_ZONEMD_DIGEST_SHA384:
+ REQUIRE(zonemd->length == ISC_SHA384_DIGESTLENGTH);
+ break;
+ case DNS_ZONEMD_DIGEST_SHA512:
+ REQUIRE(zonemd->length == ISC_SHA512_DIGESTLENGTH);
+ break;
+ }
+
+ RETERR(uint32_tobuffer(zonemd->serial, target));
+ RETERR(uint8_tobuffer(zonemd->scheme, target));
+ RETERR(uint8_tobuffer(zonemd->digest_type, target));
+
+ return (mem_tobuffer(target, zonemd->digest, zonemd->length));
+}
+
+static isc_result_t
+tostruct_zonemd(ARGS_TOSTRUCT) {
+ dns_rdata_zonemd_t *zonemd = target;
+ isc_region_t region;
+
+ REQUIRE(rdata->type == dns_rdatatype_zonemd);
+ REQUIRE(zonemd != NULL);
+ REQUIRE(rdata->length != 0);
+
+ zonemd->common.rdclass = rdata->rdclass;
+ zonemd->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&zonemd->common, link);
+
+ dns_rdata_toregion(rdata, &region);
+
+ zonemd->serial = uint32_fromregion(&region);
+ isc_region_consume(&region, 4);
+ zonemd->scheme = uint8_fromregion(&region);
+ isc_region_consume(&region, 1);
+ zonemd->digest_type = uint8_fromregion(&region);
+ isc_region_consume(&region, 1);
+ zonemd->length = region.length;
+
+ zonemd->digest = mem_maybedup(mctx, region.base, region.length);
+ if (zonemd->digest == NULL) {
+ return (ISC_R_NOMEMORY);
+ }
+
+ zonemd->mctx = mctx;
+ return (ISC_R_SUCCESS);
+}
+
+static void
+freestruct_zonemd(ARGS_FREESTRUCT) {
+ dns_rdata_zonemd_t *zonemd = source;
+
+ REQUIRE(zonemd != NULL);
+ REQUIRE(zonemd->common.rdtype == dns_rdatatype_zonemd);
+
+ if (zonemd->mctx == NULL) {
+ return;
+ }
+
+ if (zonemd->digest != NULL) {
+ isc_mem_free(zonemd->mctx, zonemd->digest);
+ }
+ zonemd->mctx = NULL;
+}
+
+static isc_result_t
+additionaldata_zonemd(ARGS_ADDLDATA) {
+ REQUIRE(rdata->type == dns_rdatatype_zonemd);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(add);
+ UNUSED(arg);
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+digest_zonemd(ARGS_DIGEST) {
+ isc_region_t r;
+
+ REQUIRE(rdata->type == dns_rdatatype_zonemd);
+
+ dns_rdata_toregion(rdata, &r);
+
+ return ((digest)(arg, &r));
+}
+
+static bool
+checkowner_zonemd(ARGS_CHECKOWNER) {
+ REQUIRE(type == dns_rdatatype_zonemd);
+
+ UNUSED(name);
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (true);
+}
+
+static bool
+checknames_zonemd(ARGS_CHECKNAMES) {
+ REQUIRE(rdata->type == dns_rdatatype_zonemd);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(bad);
+
+ return (true);
+}
+
+static int
+casecompare_zonemd(ARGS_COMPARE) {
+ return (compare_zonemd(rdata1, rdata2));
+}
+
+#endif /* RDATA_GENERIC_ZONEMD_63_C */
diff --git a/lib/dns/rdata/generic/zonemd_63.h b/lib/dns/rdata/generic/zonemd_63.h
new file mode 100644
index 0000000..5856b0d
--- /dev/null
+++ b/lib/dns/rdata/generic/zonemd_63.h
@@ -0,0 +1,31 @@
+/*
+ * 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
+
+/* Known digest type(s). */
+#define DNS_ZONEMD_DIGEST_SHA384 (1)
+#define DNS_ZONEMD_DIGEST_SHA512 (2)
+
+/*
+ * \brief per RFC 8976
+ */
+typedef struct dns_rdata_zonemd {
+ dns_rdatacommon_t common;
+ isc_mem_t *mctx;
+ uint32_t serial;
+ uint8_t scheme;
+ uint8_t digest_type;
+ unsigned char *digest;
+ uint16_t length;
+} dns_rdata_zonemd_t;