summaryrefslogtreecommitdiffstats
path: root/lib/dns/rdata/in_1
diff options
context:
space:
mode:
Diffstat (limited to 'lib/dns/rdata/in_1')
-rw-r--r--lib/dns/rdata/in_1/a6_38.c487
-rw-r--r--lib/dns/rdata/in_1/a6_38.h25
-rw-r--r--lib/dns/rdata/in_1/a_1.c279
-rw-r--r--lib/dns/rdata/in_1/a_1.h20
-rw-r--r--lib/dns/rdata/in_1/aaaa_28.c266
-rw-r--r--lib/dns/rdata/in_1/aaaa_28.h22
-rw-r--r--lib/dns/rdata/in_1/apl_42.c483
-rw-r--r--lib/dns/rdata/in_1/apl_42.h50
-rw-r--r--lib/dns/rdata/in_1/atma_34.c318
-rw-r--r--lib/dns/rdata/in_1/atma_34.h25
-rw-r--r--lib/dns/rdata/in_1/dhcid_49.c236
-rw-r--r--lib/dns/rdata/in_1/dhcid_49.h22
-rw-r--r--lib/dns/rdata/in_1/eid_31.c225
-rw-r--r--lib/dns/rdata/in_1/eid_31.h25
-rw-r--r--lib/dns/rdata/in_1/https_65.c183
-rw-r--r--lib/dns/rdata/in_1/https_65.h32
-rw-r--r--lib/dns/rdata/in_1/kx_36.c291
-rw-r--r--lib/dns/rdata/in_1/kx_36.h24
-rw-r--r--lib/dns/rdata/in_1/nimloc_32.c225
-rw-r--r--lib/dns/rdata/in_1/nimloc_32.h25
-rw-r--r--lib/dns/rdata/in_1/nsap-ptr_23.c244
-rw-r--r--lib/dns/rdata/in_1/nsap-ptr_23.h23
-rw-r--r--lib/dns/rdata/in_1/nsap_22.c260
-rw-r--r--lib/dns/rdata/in_1/nsap_22.h24
-rw-r--r--lib/dns/rdata/in_1/px_26.c372
-rw-r--r--lib/dns/rdata/in_1/px_26.h25
-rw-r--r--lib/dns/rdata/in_1/srv_33.c413
-rw-r--r--lib/dns/rdata/in_1/srv_33.h26
-rw-r--r--lib/dns/rdata/in_1/svcb_64.c1338
-rw-r--r--lib/dns/rdata/in_1/svcb_64.h37
-rw-r--r--lib/dns/rdata/in_1/wks_11.c404
-rw-r--r--lib/dns/rdata/in_1/wks_11.h23
32 files changed, 6452 insertions, 0 deletions
diff --git a/lib/dns/rdata/in_1/a6_38.c b/lib/dns/rdata/in_1/a6_38.c
new file mode 100644
index 0000000..80941d6
--- /dev/null
+++ b/lib/dns/rdata/in_1/a6_38.c
@@ -0,0 +1,487 @@
+/*
+ * 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.
+ */
+
+/* RFC2874 */
+
+#ifndef RDATA_IN_1_A6_28_C
+#define RDATA_IN_1_A6_28_C
+
+#include <isc/net.h>
+
+#define RRTYPE_A6_ATTRIBUTES (0)
+
+static isc_result_t
+fromtext_in_a6(ARGS_FROMTEXT) {
+ isc_token_t token;
+ unsigned char addr[16];
+ unsigned char prefixlen;
+ unsigned char octets;
+ unsigned char mask;
+ dns_name_t name;
+ isc_buffer_t buffer;
+ bool ok;
+
+ REQUIRE(type == dns_rdatatype_a6);
+ REQUIRE(rdclass == dns_rdataclass_in);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(callbacks);
+
+ /*
+ * Prefix length.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
+ false));
+ if (token.value.as_ulong > 128U) {
+ RETTOK(ISC_R_RANGE);
+ }
+
+ prefixlen = (unsigned char)token.value.as_ulong;
+ RETERR(mem_tobuffer(target, &prefixlen, 1));
+
+ /*
+ * Suffix.
+ */
+ if (prefixlen != 128) {
+ /*
+ * Prefix 0..127.
+ */
+ octets = prefixlen / 8;
+ /*
+ * Octets 0..15.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token,
+ isc_tokentype_string, false));
+ if (inet_pton(AF_INET6, DNS_AS_STR(token), addr) != 1) {
+ RETTOK(DNS_R_BADAAAA);
+ }
+ mask = 0xff >> (prefixlen % 8);
+ addr[octets] &= mask;
+ RETERR(mem_tobuffer(target, &addr[octets], 16 - octets));
+ }
+
+ if (prefixlen == 0) {
+ return (ISC_R_SUCCESS);
+ }
+
+ 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_in_a6(ARGS_TOTEXT) {
+ isc_region_t sr, ar;
+ unsigned char addr[16];
+ unsigned char prefixlen;
+ unsigned char octets;
+ unsigned char mask;
+ char buf[sizeof("128")];
+ dns_name_t name;
+ dns_name_t prefix;
+ bool sub;
+
+ REQUIRE(rdata->type == dns_rdatatype_a6);
+ REQUIRE(rdata->rdclass == dns_rdataclass_in);
+ REQUIRE(rdata->length != 0);
+
+ dns_rdata_toregion(rdata, &sr);
+ prefixlen = sr.base[0];
+ INSIST(prefixlen <= 128);
+ isc_region_consume(&sr, 1);
+ snprintf(buf, sizeof(buf), "%u", prefixlen);
+ RETERR(str_totext(buf, target));
+ RETERR(str_totext(" ", target));
+
+ if (prefixlen != 128) {
+ octets = prefixlen / 8;
+ memset(addr, 0, sizeof(addr));
+ memmove(&addr[octets], sr.base, 16 - octets);
+ mask = 0xff >> (prefixlen % 8);
+ addr[octets] &= mask;
+ ar.base = addr;
+ ar.length = sizeof(addr);
+ RETERR(inet_totext(AF_INET6, tctx->flags, &ar, target));
+ isc_region_consume(&sr, 16 - octets);
+ }
+
+ if (prefixlen == 0) {
+ return (ISC_R_SUCCESS);
+ }
+
+ RETERR(str_totext(" ", target));
+ dns_name_init(&name, NULL);
+ dns_name_init(&prefix, NULL);
+ dns_name_fromregion(&name, &sr);
+ sub = name_prefix(&name, tctx->origin, &prefix);
+ return (dns_name_totext(&prefix, sub, target));
+}
+
+static isc_result_t
+fromwire_in_a6(ARGS_FROMWIRE) {
+ isc_region_t sr;
+ unsigned char prefixlen;
+ unsigned char octets;
+ unsigned char mask;
+ dns_name_t name;
+
+ REQUIRE(type == dns_rdatatype_a6);
+ REQUIRE(rdclass == dns_rdataclass_in);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ dns_decompress_setmethods(dctx, DNS_COMPRESS_NONE);
+
+ isc_buffer_activeregion(source, &sr);
+ /*
+ * Prefix length.
+ */
+ if (sr.length < 1) {
+ return (ISC_R_UNEXPECTEDEND);
+ }
+ prefixlen = sr.base[0];
+ if (prefixlen > 128) {
+ return (ISC_R_RANGE);
+ }
+ isc_region_consume(&sr, 1);
+ RETERR(mem_tobuffer(target, &prefixlen, 1));
+ isc_buffer_forward(source, 1);
+
+ /*
+ * Suffix.
+ */
+ if (prefixlen != 128) {
+ octets = 16 - prefixlen / 8;
+ if (sr.length < octets) {
+ return (ISC_R_UNEXPECTEDEND);
+ }
+ mask = 0xff >> (prefixlen % 8);
+ if ((sr.base[0] & ~mask) != 0) {
+ return (DNS_R_FORMERR);
+ }
+ RETERR(mem_tobuffer(target, sr.base, octets));
+ isc_buffer_forward(source, octets);
+ }
+
+ if (prefixlen == 0) {
+ return (ISC_R_SUCCESS);
+ }
+
+ dns_name_init(&name, NULL);
+ return (dns_name_fromwire(&name, source, dctx, options, target));
+}
+
+static isc_result_t
+towire_in_a6(ARGS_TOWIRE) {
+ isc_region_t sr;
+ dns_name_t name;
+ dns_offsets_t offsets;
+ unsigned char prefixlen;
+ unsigned char octets;
+
+ REQUIRE(rdata->type == dns_rdatatype_a6);
+ REQUIRE(rdata->rdclass == dns_rdataclass_in);
+ REQUIRE(rdata->length != 0);
+
+ dns_compress_setmethods(cctx, DNS_COMPRESS_NONE);
+ dns_rdata_toregion(rdata, &sr);
+ prefixlen = sr.base[0];
+ INSIST(prefixlen <= 128);
+
+ octets = 1 + 16 - prefixlen / 8;
+ RETERR(mem_tobuffer(target, sr.base, octets));
+ isc_region_consume(&sr, octets);
+
+ if (prefixlen == 0) {
+ return (ISC_R_SUCCESS);
+ }
+
+ dns_name_init(&name, offsets);
+ dns_name_fromregion(&name, &sr);
+ return (dns_name_towire(&name, cctx, target));
+}
+
+static int
+compare_in_a6(ARGS_COMPARE) {
+ int order;
+ unsigned char prefixlen1, prefixlen2;
+ unsigned char octets;
+ 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_a6);
+ REQUIRE(rdata1->rdclass == dns_rdataclass_in);
+ REQUIRE(rdata1->length != 0);
+ REQUIRE(rdata2->length != 0);
+
+ dns_rdata_toregion(rdata1, &region1);
+ dns_rdata_toregion(rdata2, &region2);
+ prefixlen1 = region1.base[0];
+ prefixlen2 = region2.base[0];
+ isc_region_consume(&region1, 1);
+ isc_region_consume(&region2, 1);
+ if (prefixlen1 < prefixlen2) {
+ return (-1);
+ } else if (prefixlen1 > prefixlen2) {
+ return (1);
+ }
+ /*
+ * Prefix lengths are equal.
+ */
+ octets = 16 - prefixlen1 / 8;
+
+ if (octets > 0) {
+ order = memcmp(region1.base, region2.base, octets);
+ if (order < 0) {
+ return (-1);
+ } else if (order > 0) {
+ return (1);
+ }
+ /*
+ * Address suffixes are equal.
+ */
+ if (prefixlen1 == 0) {
+ return (order);
+ }
+ isc_region_consume(&region1, octets);
+ isc_region_consume(&region2, octets);
+ }
+
+ 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_in_a6(ARGS_FROMSTRUCT) {
+ dns_rdata_in_a6_t *a6 = source;
+ isc_region_t region;
+ int octets;
+ uint8_t bits;
+ uint8_t first;
+ uint8_t mask;
+
+ REQUIRE(type == dns_rdatatype_a6);
+ REQUIRE(rdclass == dns_rdataclass_in);
+ REQUIRE(a6 != NULL);
+ REQUIRE(a6->common.rdtype == type);
+ REQUIRE(a6->common.rdclass == rdclass);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ if (a6->prefixlen > 128) {
+ return (ISC_R_RANGE);
+ }
+
+ RETERR(uint8_tobuffer(a6->prefixlen, target));
+
+ /* Suffix */
+ if (a6->prefixlen != 128) {
+ octets = 16 - a6->prefixlen / 8;
+ bits = a6->prefixlen % 8;
+ if (bits != 0) {
+ mask = 0xffU >> bits;
+ first = a6->in6_addr.s6_addr[16 - octets] & mask;
+ RETERR(uint8_tobuffer(first, target));
+ octets--;
+ }
+ if (octets > 0) {
+ RETERR(mem_tobuffer(target,
+ a6->in6_addr.s6_addr + 16 - octets,
+ octets));
+ }
+ }
+
+ if (a6->prefixlen == 0) {
+ return (ISC_R_SUCCESS);
+ }
+ dns_name_toregion(&a6->prefix, &region);
+ return (isc_buffer_copyregion(target, &region));
+}
+
+static isc_result_t
+tostruct_in_a6(ARGS_TOSTRUCT) {
+ dns_rdata_in_a6_t *a6 = target;
+ unsigned char octets;
+ dns_name_t name;
+ isc_region_t r;
+
+ REQUIRE(rdata->type == dns_rdatatype_a6);
+ REQUIRE(rdata->rdclass == dns_rdataclass_in);
+ REQUIRE(a6 != NULL);
+ REQUIRE(rdata->length != 0);
+
+ a6->common.rdclass = rdata->rdclass;
+ a6->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&a6->common, link);
+
+ dns_rdata_toregion(rdata, &r);
+
+ a6->prefixlen = uint8_fromregion(&r);
+ isc_region_consume(&r, 1);
+ memset(a6->in6_addr.s6_addr, 0, sizeof(a6->in6_addr.s6_addr));
+
+ /*
+ * Suffix.
+ */
+ if (a6->prefixlen != 128) {
+ octets = 16 - a6->prefixlen / 8;
+ INSIST(r.length >= octets);
+ memmove(a6->in6_addr.s6_addr + 16 - octets, r.base, octets);
+ isc_region_consume(&r, octets);
+ }
+
+ /*
+ * Prefix.
+ */
+ dns_name_init(&a6->prefix, NULL);
+ if (a6->prefixlen != 0) {
+ dns_name_init(&name, NULL);
+ dns_name_fromregion(&name, &r);
+ name_duporclone(&name, mctx, &a6->prefix);
+ }
+ a6->mctx = mctx;
+ return (ISC_R_SUCCESS);
+}
+
+static void
+freestruct_in_a6(ARGS_FREESTRUCT) {
+ dns_rdata_in_a6_t *a6 = source;
+
+ REQUIRE(a6 != NULL);
+ REQUIRE(a6->common.rdclass == dns_rdataclass_in);
+ REQUIRE(a6->common.rdtype == dns_rdatatype_a6);
+
+ if (a6->mctx == NULL) {
+ return;
+ }
+
+ if (dns_name_dynamic(&a6->prefix)) {
+ dns_name_free(&a6->prefix, a6->mctx);
+ }
+ a6->mctx = NULL;
+}
+
+static isc_result_t
+additionaldata_in_a6(ARGS_ADDLDATA) {
+ REQUIRE(rdata->type == dns_rdatatype_a6);
+ REQUIRE(rdata->rdclass == dns_rdataclass_in);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(add);
+ UNUSED(arg);
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+digest_in_a6(ARGS_DIGEST) {
+ isc_region_t r1, r2;
+ unsigned char prefixlen, octets;
+ isc_result_t result;
+ dns_name_t name;
+
+ REQUIRE(rdata->type == dns_rdatatype_a6);
+ REQUIRE(rdata->rdclass == dns_rdataclass_in);
+
+ dns_rdata_toregion(rdata, &r1);
+ r2 = r1;
+ prefixlen = r1.base[0];
+ octets = 1 + 16 - prefixlen / 8;
+
+ r1.length = octets;
+ result = (digest)(arg, &r1);
+ if (result != ISC_R_SUCCESS) {
+ return (result);
+ }
+ if (prefixlen == 0) {
+ return (ISC_R_SUCCESS);
+ }
+
+ isc_region_consume(&r2, octets);
+ dns_name_init(&name, NULL);
+ dns_name_fromregion(&name, &r2);
+ return (dns_name_digest(&name, digest, arg));
+}
+
+static bool
+checkowner_in_a6(ARGS_CHECKOWNER) {
+ REQUIRE(type == dns_rdatatype_a6);
+ REQUIRE(rdclass == dns_rdataclass_in);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ return (dns_name_ishostname(name, wildcard));
+}
+
+static bool
+checknames_in_a6(ARGS_CHECKNAMES) {
+ isc_region_t region;
+ dns_name_t name;
+ unsigned int prefixlen;
+
+ REQUIRE(rdata->type == dns_rdatatype_a6);
+ REQUIRE(rdata->rdclass == dns_rdataclass_in);
+
+ UNUSED(owner);
+
+ dns_rdata_toregion(rdata, &region);
+ prefixlen = uint8_fromregion(&region);
+ if (prefixlen == 0) {
+ return (true);
+ }
+ isc_region_consume(&region, 1 + 16 - prefixlen / 8);
+ 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_in_a6(ARGS_COMPARE) {
+ return (compare_in_a6(rdata1, rdata2));
+}
+
+#endif /* RDATA_IN_1_A6_38_C */
diff --git a/lib/dns/rdata/in_1/a6_38.h b/lib/dns/rdata/in_1/a6_38.h
new file mode 100644
index 0000000..7c09cc5
--- /dev/null
+++ b/lib/dns/rdata/in_1/a6_38.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 RFC2874 */
+
+typedef struct dns_rdata_in_a6 {
+ dns_rdatacommon_t common;
+ isc_mem_t *mctx;
+ dns_name_t prefix;
+ uint8_t prefixlen;
+ struct in6_addr in6_addr;
+} dns_rdata_in_a6_t;
diff --git a/lib/dns/rdata/in_1/a_1.c b/lib/dns/rdata/in_1/a_1.c
new file mode 100644
index 0000000..cf5549d
--- /dev/null
+++ b/lib/dns/rdata/in_1/a_1.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_IN_1_A_1_C
+#define RDATA_IN_1_A_1_C
+
+#include <string.h>
+
+#include <isc/net.h>
+
+#define RRTYPE_A_ATTRIBUTES (0)
+
+static isc_result_t
+fromtext_in_a(ARGS_FROMTEXT) {
+ isc_token_t token;
+ struct in_addr addr;
+ isc_region_t region;
+
+ REQUIRE(type == dns_rdatatype_a);
+ REQUIRE(rdclass == dns_rdataclass_in);
+
+ UNUSED(type);
+ UNUSED(origin);
+ UNUSED(options);
+ UNUSED(rdclass);
+ UNUSED(callbacks);
+
+ 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_in_a(ARGS_TOTEXT) {
+ isc_region_t region;
+
+ REQUIRE(rdata->type == dns_rdatatype_a);
+ REQUIRE(rdata->rdclass == dns_rdataclass_in);
+ REQUIRE(rdata->length == 4);
+
+ UNUSED(tctx);
+
+ dns_rdata_toregion(rdata, &region);
+ return (inet_totext(AF_INET, tctx->flags, &region, target));
+}
+
+static isc_result_t
+fromwire_in_a(ARGS_FROMWIRE) {
+ isc_region_t sregion;
+ isc_region_t tregion;
+
+ REQUIRE(type == dns_rdatatype_a);
+ REQUIRE(rdclass == dns_rdataclass_in);
+
+ UNUSED(type);
+ UNUSED(dctx);
+ UNUSED(options);
+ UNUSED(rdclass);
+
+ isc_buffer_activeregion(source, &sregion);
+ isc_buffer_availableregion(target, &tregion);
+ if (sregion.length < 4) {
+ return (ISC_R_UNEXPECTEDEND);
+ }
+ if (tregion.length < 4) {
+ return (ISC_R_NOSPACE);
+ }
+
+ memmove(tregion.base, sregion.base, 4);
+ isc_buffer_forward(source, 4);
+ isc_buffer_add(target, 4);
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+towire_in_a(ARGS_TOWIRE) {
+ isc_region_t region;
+
+ REQUIRE(rdata->type == dns_rdatatype_a);
+ REQUIRE(rdata->rdclass == dns_rdataclass_in);
+ REQUIRE(rdata->length == 4);
+
+ UNUSED(cctx);
+
+ isc_buffer_availableregion(target, &region);
+ if (region.length < rdata->length) {
+ return (ISC_R_NOSPACE);
+ }
+ memmove(region.base, rdata->data, rdata->length);
+ isc_buffer_add(target, 4);
+ return (ISC_R_SUCCESS);
+}
+
+static int
+compare_in_a(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_a);
+ REQUIRE(rdata1->rdclass == dns_rdataclass_in);
+ REQUIRE(rdata1->length == 4);
+ REQUIRE(rdata2->length == 4);
+
+ dns_rdata_toregion(rdata1, &r1);
+ dns_rdata_toregion(rdata2, &r2);
+ return (isc_region_compare(&r1, &r2));
+}
+
+static isc_result_t
+fromstruct_in_a(ARGS_FROMSTRUCT) {
+ dns_rdata_in_a_t *a = source;
+ uint32_t n;
+
+ REQUIRE(type == dns_rdatatype_a);
+ REQUIRE(rdclass == dns_rdataclass_in);
+ REQUIRE(a != NULL);
+ REQUIRE(a->common.rdtype == type);
+ REQUIRE(a->common.rdclass == rdclass);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ n = ntohl(a->in_addr.s_addr);
+
+ return (uint32_tobuffer(n, target));
+}
+
+static isc_result_t
+tostruct_in_a(ARGS_TOSTRUCT) {
+ dns_rdata_in_a_t *a = target;
+ uint32_t n;
+ isc_region_t region;
+
+ REQUIRE(a != NULL);
+ REQUIRE(rdata->type == dns_rdatatype_a);
+ REQUIRE(rdata->rdclass == dns_rdataclass_in);
+ REQUIRE(rdata->length == 4);
+
+ UNUSED(mctx);
+
+ a->common.rdclass = rdata->rdclass;
+ a->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&a->common, link);
+
+ dns_rdata_toregion(rdata, &region);
+ n = uint32_fromregion(&region);
+ a->in_addr.s_addr = htonl(n);
+
+ return (ISC_R_SUCCESS);
+}
+
+static void
+freestruct_in_a(ARGS_FREESTRUCT) {
+ dns_rdata_in_a_t *a = source;
+
+ REQUIRE(a != NULL);
+ REQUIRE(a->common.rdtype == dns_rdatatype_a);
+ REQUIRE(a->common.rdclass == dns_rdataclass_in);
+
+ UNUSED(a);
+}
+
+static isc_result_t
+additionaldata_in_a(ARGS_ADDLDATA) {
+ REQUIRE(rdata->type == dns_rdatatype_a);
+ REQUIRE(rdata->rdclass == dns_rdataclass_in);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(add);
+ UNUSED(arg);
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+digest_in_a(ARGS_DIGEST) {
+ isc_region_t r;
+
+ REQUIRE(rdata->type == dns_rdatatype_a);
+ REQUIRE(rdata->rdclass == dns_rdataclass_in);
+
+ dns_rdata_toregion(rdata, &r);
+
+ return ((digest)(arg, &r));
+}
+
+static bool
+checkowner_in_a(ARGS_CHECKOWNER) {
+ dns_name_t prefix, suffix;
+ unsigned int labels, i;
+
+ REQUIRE(type == dns_rdatatype_a);
+ REQUIRE(rdclass == dns_rdataclass_in);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ labels = dns_name_countlabels(name);
+ if (labels > 2U) {
+ /*
+ * Handle Active Directory gc._msdcs.<forest> name.
+ */
+ dns_name_init(&prefix, NULL);
+ dns_name_init(&suffix, NULL);
+ dns_name_split(name, labels - 2, &prefix, &suffix);
+ if (dns_name_equal(&gc_msdcs, &prefix) &&
+ dns_name_ishostname(&suffix, false))
+ {
+ return (true);
+ }
+
+ /*
+ * Handle SPF exists targets when the seperating label is:
+ * - "_spf" RFC7208, section 5.7
+ * - "_spf_verify" RFC7208, Appendix D1
+ * - "_spf_rate" RFC7208, Appendix D1
+ */
+ for (i = 0; i < labels - 2; i++) {
+ dns_label_t label;
+ dns_name_getlabel(name, i, &label);
+ if ((label.length == 5 &&
+ strncasecmp((char *)label.base, "\x04_spf", 5) ==
+ 0) ||
+ (label.length == 12 &&
+ strncasecmp((char *)label.base, "\x0b_spf_verify",
+ 12) == 0) ||
+ (label.length == 10 &&
+ strncasecmp((char *)label.base, "\x09_spf_rate",
+ 10) == 0))
+ {
+ return (true);
+ }
+ }
+ }
+
+ return (dns_name_ishostname(name, wildcard));
+}
+
+static bool
+checknames_in_a(ARGS_CHECKNAMES) {
+ REQUIRE(rdata->type == dns_rdatatype_a);
+ REQUIRE(rdata->rdclass == dns_rdataclass_in);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(bad);
+
+ return (true);
+}
+
+static int
+casecompare_in_a(ARGS_COMPARE) {
+ return (compare_in_a(rdata1, rdata2));
+}
+
+#endif /* RDATA_IN_1_A_1_C */
diff --git a/lib/dns/rdata/in_1/a_1.h b/lib/dns/rdata/in_1/a_1.h
new file mode 100644
index 0000000..38ffd8f
--- /dev/null
+++ b/lib/dns/rdata/in_1/a_1.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_in_a {
+ dns_rdatacommon_t common;
+ struct in_addr in_addr;
+} dns_rdata_in_a_t;
diff --git a/lib/dns/rdata/in_1/aaaa_28.c b/lib/dns/rdata/in_1/aaaa_28.c
new file mode 100644
index 0000000..e23bd47
--- /dev/null
+++ b/lib/dns/rdata/in_1/aaaa_28.c
@@ -0,0 +1,266 @@
+/*
+ * 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.
+ */
+
+/* RFC1886 */
+
+#ifndef RDATA_IN_1_AAAA_28_C
+#define RDATA_IN_1_AAAA_28_C
+
+#include <isc/net.h>
+
+#define RRTYPE_AAAA_ATTRIBUTES (0)
+
+static isc_result_t
+fromtext_in_aaaa(ARGS_FROMTEXT) {
+ isc_token_t token;
+ unsigned char addr[16];
+ isc_region_t region;
+
+ REQUIRE(type == dns_rdatatype_aaaa);
+ REQUIRE(rdclass == dns_rdataclass_in);
+
+ UNUSED(type);
+ UNUSED(origin);
+ UNUSED(options);
+ UNUSED(rdclass);
+ UNUSED(callbacks);
+
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ false));
+
+ if (inet_pton(AF_INET6, DNS_AS_STR(token), addr) != 1) {
+ RETTOK(DNS_R_BADAAAA);
+ }
+ isc_buffer_availableregion(target, &region);
+ if (region.length < 16) {
+ return (ISC_R_NOSPACE);
+ }
+ memmove(region.base, addr, 16);
+ isc_buffer_add(target, 16);
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+totext_in_aaaa(ARGS_TOTEXT) {
+ isc_region_t region;
+
+ REQUIRE(rdata->type == dns_rdatatype_aaaa);
+ REQUIRE(rdata->rdclass == dns_rdataclass_in);
+ REQUIRE(rdata->length == 16);
+
+ if ((tctx->flags & DNS_STYLEFLAG_EXPANDAAAA) != 0) {
+ char buf[5 * 8];
+ const char *sep = "";
+ int i, n;
+ unsigned int len = 0;
+
+ for (i = 0; i < 16; i += 2) {
+ INSIST(len < sizeof(buf));
+ n = snprintf(buf + len, sizeof(buf) - len, "%s%02x%02x",
+ sep, rdata->data[i], rdata->data[i + 1]);
+ if (n < 0) {
+ return (ISC_R_FAILURE);
+ }
+ len += n;
+ sep = ":";
+ }
+ return (str_totext(buf, target));
+ }
+ dns_rdata_toregion(rdata, &region);
+ return (inet_totext(AF_INET6, tctx->flags, &region, target));
+}
+
+static isc_result_t
+fromwire_in_aaaa(ARGS_FROMWIRE) {
+ isc_region_t sregion;
+ isc_region_t tregion;
+
+ REQUIRE(type == dns_rdatatype_aaaa);
+ REQUIRE(rdclass == dns_rdataclass_in);
+
+ UNUSED(type);
+ UNUSED(dctx);
+ UNUSED(options);
+ UNUSED(rdclass);
+
+ isc_buffer_activeregion(source, &sregion);
+ isc_buffer_availableregion(target, &tregion);
+ if (sregion.length < 16) {
+ return (ISC_R_UNEXPECTEDEND);
+ }
+ if (tregion.length < 16) {
+ return (ISC_R_NOSPACE);
+ }
+
+ memmove(tregion.base, sregion.base, 16);
+ isc_buffer_forward(source, 16);
+ isc_buffer_add(target, 16);
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+towire_in_aaaa(ARGS_TOWIRE) {
+ isc_region_t region;
+
+ UNUSED(cctx);
+
+ REQUIRE(rdata->type == dns_rdatatype_aaaa);
+ REQUIRE(rdata->rdclass == dns_rdataclass_in);
+ REQUIRE(rdata->length == 16);
+
+ isc_buffer_availableregion(target, &region);
+ if (region.length < rdata->length) {
+ return (ISC_R_NOSPACE);
+ }
+ memmove(region.base, rdata->data, rdata->length);
+ isc_buffer_add(target, 16);
+ return (ISC_R_SUCCESS);
+}
+
+static int
+compare_in_aaaa(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_aaaa);
+ REQUIRE(rdata1->rdclass == dns_rdataclass_in);
+ REQUIRE(rdata1->length == 16);
+ REQUIRE(rdata2->length == 16);
+
+ dns_rdata_toregion(rdata1, &r1);
+ dns_rdata_toregion(rdata2, &r2);
+ return (isc_region_compare(&r1, &r2));
+}
+
+static isc_result_t
+fromstruct_in_aaaa(ARGS_FROMSTRUCT) {
+ dns_rdata_in_aaaa_t *aaaa = source;
+
+ REQUIRE(type == dns_rdatatype_aaaa);
+ REQUIRE(rdclass == dns_rdataclass_in);
+ REQUIRE(aaaa != NULL);
+ REQUIRE(aaaa->common.rdtype == type);
+ REQUIRE(aaaa->common.rdclass == rdclass);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ return (mem_tobuffer(target, aaaa->in6_addr.s6_addr, 16));
+}
+
+static isc_result_t
+tostruct_in_aaaa(ARGS_TOSTRUCT) {
+ dns_rdata_in_aaaa_t *aaaa = target;
+ isc_region_t r;
+
+ REQUIRE(rdata->type == dns_rdatatype_aaaa);
+ REQUIRE(rdata->rdclass == dns_rdataclass_in);
+ REQUIRE(aaaa != NULL);
+ REQUIRE(rdata->length == 16);
+
+ UNUSED(mctx);
+
+ aaaa->common.rdclass = rdata->rdclass;
+ aaaa->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&aaaa->common, link);
+
+ dns_rdata_toregion(rdata, &r);
+ INSIST(r.length == 16);
+ memmove(aaaa->in6_addr.s6_addr, r.base, 16);
+
+ return (ISC_R_SUCCESS);
+}
+
+static void
+freestruct_in_aaaa(ARGS_FREESTRUCT) {
+ dns_rdata_in_aaaa_t *aaaa = source;
+
+ REQUIRE(aaaa != NULL);
+ REQUIRE(aaaa->common.rdclass == dns_rdataclass_in);
+ REQUIRE(aaaa->common.rdtype == dns_rdatatype_aaaa);
+
+ UNUSED(aaaa);
+}
+
+static isc_result_t
+additionaldata_in_aaaa(ARGS_ADDLDATA) {
+ REQUIRE(rdata->type == dns_rdatatype_aaaa);
+ REQUIRE(rdata->rdclass == dns_rdataclass_in);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(add);
+ UNUSED(arg);
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+digest_in_aaaa(ARGS_DIGEST) {
+ isc_region_t r;
+
+ REQUIRE(rdata->type == dns_rdatatype_aaaa);
+ REQUIRE(rdata->rdclass == dns_rdataclass_in);
+
+ dns_rdata_toregion(rdata, &r);
+
+ return ((digest)(arg, &r));
+}
+
+static bool
+checkowner_in_aaaa(ARGS_CHECKOWNER) {
+ dns_name_t prefix, suffix;
+
+ REQUIRE(type == dns_rdatatype_aaaa);
+ REQUIRE(rdclass == dns_rdataclass_in);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ /*
+ * Handle Active Directory gc._msdcs.<forest> name.
+ */
+ if (dns_name_countlabels(name) > 2U) {
+ dns_name_init(&prefix, NULL);
+ dns_name_init(&suffix, NULL);
+ dns_name_split(name, dns_name_countlabels(name) - 2, &prefix,
+ &suffix);
+ if (dns_name_equal(&gc_msdcs, &prefix) &&
+ dns_name_ishostname(&suffix, false))
+ {
+ return (true);
+ }
+ }
+
+ return (dns_name_ishostname(name, wildcard));
+}
+
+static bool
+checknames_in_aaaa(ARGS_CHECKNAMES) {
+ REQUIRE(rdata->type == dns_rdatatype_aaaa);
+ REQUIRE(rdata->rdclass == dns_rdataclass_in);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(bad);
+
+ return (true);
+}
+
+static int
+casecompare_in_aaaa(ARGS_COMPARE) {
+ return (compare_in_aaaa(rdata1, rdata2));
+}
+#endif /* RDATA_IN_1_AAAA_28_C */
diff --git a/lib/dns/rdata/in_1/aaaa_28.h b/lib/dns/rdata/in_1/aaaa_28.h
new file mode 100644
index 0000000..915cc0f
--- /dev/null
+++ b/lib/dns/rdata/in_1/aaaa_28.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
+
+/*!
+ * \brief Per RFC1886 */
+
+typedef struct dns_rdata_in_aaaa {
+ dns_rdatacommon_t common;
+ struct in6_addr in6_addr;
+} dns_rdata_in_aaaa_t;
diff --git a/lib/dns/rdata/in_1/apl_42.c b/lib/dns/rdata/in_1/apl_42.c
new file mode 100644
index 0000000..03593ab
--- /dev/null
+++ b/lib/dns/rdata/in_1/apl_42.c
@@ -0,0 +1,483 @@
+/*
+ * 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.
+ */
+
+/* RFC3123 */
+
+#ifndef RDATA_IN_1_APL_42_C
+#define RDATA_IN_1_APL_42_C
+
+#define RRTYPE_APL_ATTRIBUTES (0)
+
+static isc_result_t
+fromtext_in_apl(ARGS_FROMTEXT) {
+ isc_token_t token;
+ unsigned char addr[16];
+ unsigned long afi;
+ uint8_t prefix;
+ uint8_t len;
+ bool neg;
+ char *cp, *ap, *slash;
+ int n;
+
+ REQUIRE(type == dns_rdatatype_apl);
+ REQUIRE(rdclass == dns_rdataclass_in);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(origin);
+ UNUSED(options);
+ UNUSED(callbacks);
+
+ do {
+ RETERR(isc_lex_getmastertoken(lexer, &token,
+ isc_tokentype_string, true));
+ if (token.type != isc_tokentype_string) {
+ break;
+ }
+
+ cp = DNS_AS_STR(token);
+ neg = (*cp == '!');
+ if (neg) {
+ cp++;
+ }
+ afi = strtoul(cp, &ap, 10);
+ if (*ap++ != ':' || cp == ap) {
+ RETTOK(DNS_R_SYNTAX);
+ }
+ if (afi > 0xffffU) {
+ RETTOK(ISC_R_RANGE);
+ }
+ slash = strchr(ap, '/');
+ if (slash == NULL || slash == ap) {
+ RETTOK(DNS_R_SYNTAX);
+ }
+ RETTOK(isc_parse_uint8(&prefix, slash + 1, 10));
+ switch (afi) {
+ case 1:
+ *slash = '\0';
+ n = inet_pton(AF_INET, ap, addr);
+ *slash = '/';
+ if (n != 1) {
+ RETTOK(DNS_R_BADDOTTEDQUAD);
+ }
+ if (prefix > 32) {
+ RETTOK(ISC_R_RANGE);
+ }
+ for (len = 4; len > 0; len--) {
+ if (addr[len - 1] != 0) {
+ break;
+ }
+ }
+ break;
+
+ case 2:
+ *slash = '\0';
+ n = inet_pton(AF_INET6, ap, addr);
+ *slash = '/';
+ if (n != 1) {
+ RETTOK(DNS_R_BADAAAA);
+ }
+ if (prefix > 128) {
+ RETTOK(ISC_R_RANGE);
+ }
+ for (len = 16; len > 0; len--) {
+ if (addr[len - 1] != 0) {
+ break;
+ }
+ }
+ break;
+
+ default:
+ RETTOK(ISC_R_NOTIMPLEMENTED);
+ }
+ RETERR(uint16_tobuffer(afi, target));
+ RETERR(uint8_tobuffer(prefix, target));
+ RETERR(uint8_tobuffer(len | ((neg) ? 0x80 : 0), target));
+ RETERR(mem_tobuffer(target, addr, len));
+ } while (1);
+
+ /*
+ * Let upper layer handle eol/eof.
+ */
+ isc_lex_ungettoken(lexer, &token);
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+totext_in_apl(ARGS_TOTEXT) {
+ isc_region_t sr;
+ isc_region_t ir;
+ uint16_t afi;
+ uint8_t prefix;
+ uint8_t len;
+ bool neg;
+ unsigned char buf[16];
+ char txt[sizeof(" !64000:")];
+ const char *sep = "";
+ int n;
+
+ REQUIRE(rdata->type == dns_rdatatype_apl);
+ REQUIRE(rdata->rdclass == dns_rdataclass_in);
+
+ UNUSED(tctx);
+
+ dns_rdata_toregion(rdata, &sr);
+ ir.base = buf;
+ ir.length = sizeof(buf);
+
+ while (sr.length > 0) {
+ INSIST(sr.length >= 4);
+ afi = uint16_fromregion(&sr);
+ isc_region_consume(&sr, 2);
+ prefix = *sr.base;
+ isc_region_consume(&sr, 1);
+ len = (*sr.base & 0x7f);
+ neg = (*sr.base & 0x80);
+ isc_region_consume(&sr, 1);
+ INSIST(len <= sr.length);
+ n = snprintf(txt, sizeof(txt), "%s%s%u:", sep, neg ? "!" : "",
+ afi);
+ INSIST(n < (int)sizeof(txt));
+ RETERR(str_totext(txt, target));
+ switch (afi) {
+ case 1:
+ INSIST(len <= 4);
+ INSIST(prefix <= 32);
+ memset(buf, 0, sizeof(buf));
+ memmove(buf, sr.base, len);
+ RETERR(inet_totext(AF_INET, tctx->flags, &ir, target));
+ break;
+
+ case 2:
+ INSIST(len <= 16);
+ INSIST(prefix <= 128);
+ memset(buf, 0, sizeof(buf));
+ memmove(buf, sr.base, len);
+ RETERR(inet_totext(AF_INET6, tctx->flags, &ir, target));
+ break;
+
+ default:
+ return (ISC_R_NOTIMPLEMENTED);
+ }
+ n = snprintf(txt, sizeof(txt), "/%u", prefix);
+ INSIST(n < (int)sizeof(txt));
+ RETERR(str_totext(txt, target));
+ isc_region_consume(&sr, len);
+ sep = " ";
+ }
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+fromwire_in_apl(ARGS_FROMWIRE) {
+ isc_region_t sr, sr2;
+ isc_region_t tr;
+ uint16_t afi;
+ uint8_t prefix;
+ uint8_t len;
+
+ REQUIRE(type == dns_rdatatype_apl);
+ REQUIRE(rdclass == dns_rdataclass_in);
+
+ UNUSED(type);
+ UNUSED(dctx);
+ UNUSED(rdclass);
+ UNUSED(options);
+
+ isc_buffer_activeregion(source, &sr);
+ isc_buffer_availableregion(target, &tr);
+ if (sr.length > tr.length) {
+ return (ISC_R_NOSPACE);
+ }
+ sr2 = sr;
+
+ /* Zero or more items */
+ while (sr.length > 0) {
+ if (sr.length < 4) {
+ return (ISC_R_UNEXPECTEDEND);
+ }
+ afi = uint16_fromregion(&sr);
+ isc_region_consume(&sr, 2);
+ prefix = *sr.base;
+ isc_region_consume(&sr, 1);
+ len = (*sr.base & 0x7f);
+ isc_region_consume(&sr, 1);
+ if (len > sr.length) {
+ return (ISC_R_UNEXPECTEDEND);
+ }
+ switch (afi) {
+ case 1:
+ if (prefix > 32 || len > 4) {
+ return (ISC_R_RANGE);
+ }
+ break;
+ case 2:
+ if (prefix > 128 || len > 16) {
+ return (ISC_R_RANGE);
+ }
+ }
+ if (len > 0 && sr.base[len - 1] == 0) {
+ return (DNS_R_FORMERR);
+ }
+ isc_region_consume(&sr, len);
+ }
+ isc_buffer_forward(source, sr2.length);
+ return (mem_tobuffer(target, sr2.base, sr2.length));
+}
+
+static isc_result_t
+towire_in_apl(ARGS_TOWIRE) {
+ UNUSED(cctx);
+
+ REQUIRE(rdata->type == dns_rdatatype_apl);
+ REQUIRE(rdata->rdclass == dns_rdataclass_in);
+
+ return (mem_tobuffer(target, rdata->data, rdata->length));
+}
+
+static int
+compare_in_apl(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_apl);
+ REQUIRE(rdata1->rdclass == dns_rdataclass_in);
+
+ dns_rdata_toregion(rdata1, &r1);
+ dns_rdata_toregion(rdata2, &r2);
+ return (isc_region_compare(&r1, &r2));
+}
+
+static isc_result_t
+fromstruct_in_apl(ARGS_FROMSTRUCT) {
+ dns_rdata_in_apl_t *apl = source;
+ isc_buffer_t b;
+
+ REQUIRE(type == dns_rdatatype_apl);
+ REQUIRE(rdclass == dns_rdataclass_in);
+ REQUIRE(apl != NULL);
+ REQUIRE(apl->common.rdtype == type);
+ REQUIRE(apl->common.rdclass == rdclass);
+ REQUIRE(apl->apl != NULL || apl->apl_len == 0);
+
+ isc_buffer_init(&b, apl->apl, apl->apl_len);
+ isc_buffer_add(&b, apl->apl_len);
+ isc_buffer_setactive(&b, apl->apl_len);
+ return (fromwire_in_apl(rdclass, type, &b, NULL, false, target));
+}
+
+static isc_result_t
+tostruct_in_apl(ARGS_TOSTRUCT) {
+ dns_rdata_in_apl_t *apl = target;
+ isc_region_t r;
+
+ REQUIRE(apl != NULL);
+ REQUIRE(rdata->type == dns_rdatatype_apl);
+ REQUIRE(rdata->rdclass == dns_rdataclass_in);
+
+ apl->common.rdclass = rdata->rdclass;
+ apl->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&apl->common, link);
+
+ dns_rdata_toregion(rdata, &r);
+ apl->apl_len = r.length;
+ apl->apl = mem_maybedup(mctx, r.base, r.length);
+ if (apl->apl == NULL) {
+ return (ISC_R_NOMEMORY);
+ }
+
+ apl->offset = 0;
+ apl->mctx = mctx;
+ return (ISC_R_SUCCESS);
+}
+
+static void
+freestruct_in_apl(ARGS_FREESTRUCT) {
+ dns_rdata_in_apl_t *apl = source;
+
+ REQUIRE(apl != NULL);
+ REQUIRE(apl->common.rdtype == dns_rdatatype_apl);
+ REQUIRE(apl->common.rdclass == dns_rdataclass_in);
+
+ if (apl->mctx == NULL) {
+ return;
+ }
+ if (apl->apl != NULL) {
+ isc_mem_free(apl->mctx, apl->apl);
+ }
+ apl->mctx = NULL;
+}
+
+isc_result_t
+dns_rdata_apl_first(dns_rdata_in_apl_t *apl) {
+ uint32_t length;
+
+ REQUIRE(apl != NULL);
+ REQUIRE(apl->common.rdtype == dns_rdatatype_apl);
+ REQUIRE(apl->common.rdclass == dns_rdataclass_in);
+ REQUIRE(apl->apl != NULL || apl->apl_len == 0);
+
+ /*
+ * If no APL return ISC_R_NOMORE.
+ */
+ if (apl->apl == NULL) {
+ return (ISC_R_NOMORE);
+ }
+
+ /*
+ * Sanity check data.
+ */
+ INSIST(apl->apl_len > 3U);
+ length = apl->apl[apl->offset + 3] & 0x7f;
+ INSIST(4 + length <= apl->apl_len);
+
+ apl->offset = 0;
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+dns_rdata_apl_next(dns_rdata_in_apl_t *apl) {
+ uint32_t length;
+
+ REQUIRE(apl != NULL);
+ REQUIRE(apl->common.rdtype == dns_rdatatype_apl);
+ REQUIRE(apl->common.rdclass == dns_rdataclass_in);
+ REQUIRE(apl->apl != NULL || apl->apl_len == 0);
+
+ /*
+ * No APL or have already reached the end return ISC_R_NOMORE.
+ */
+ if (apl->apl == NULL || apl->offset == apl->apl_len) {
+ return (ISC_R_NOMORE);
+ }
+
+ /*
+ * Sanity check data.
+ */
+ INSIST(apl->offset < apl->apl_len);
+ INSIST(apl->apl_len > 3U);
+ INSIST(apl->offset <= apl->apl_len - 4U);
+ length = apl->apl[apl->offset + 3] & 0x7f;
+ /*
+ * 16 to 32 bits promotion as 'length' is 32 bits so there is
+ * no overflow problems.
+ */
+ INSIST(4 + length + apl->offset <= apl->apl_len);
+
+ apl->offset += 4 + length;
+ return ((apl->offset < apl->apl_len) ? ISC_R_SUCCESS : ISC_R_NOMORE);
+}
+
+isc_result_t
+dns_rdata_apl_current(dns_rdata_in_apl_t *apl, dns_rdata_apl_ent_t *ent) {
+ uint32_t length;
+
+ REQUIRE(apl != NULL);
+ REQUIRE(apl->common.rdtype == dns_rdatatype_apl);
+ REQUIRE(apl->common.rdclass == dns_rdataclass_in);
+ REQUIRE(ent != NULL);
+ REQUIRE(apl->apl != NULL || apl->apl_len == 0);
+ REQUIRE(apl->offset <= apl->apl_len);
+
+ if (apl->offset == apl->apl_len) {
+ return (ISC_R_NOMORE);
+ }
+
+ /*
+ * Sanity check data.
+ */
+ INSIST(apl->apl_len > 3U);
+ INSIST(apl->offset <= apl->apl_len - 4U);
+ length = (apl->apl[apl->offset + 3] & 0x7f);
+ /*
+ * 16 to 32 bits promotion as 'length' is 32 bits so there is
+ * no overflow problems.
+ */
+ INSIST(4 + length + apl->offset <= apl->apl_len);
+
+ ent->family = (apl->apl[apl->offset] << 8) + apl->apl[apl->offset + 1];
+ ent->prefix = apl->apl[apl->offset + 2];
+ ent->length = length;
+ ent->negative = (apl->apl[apl->offset + 3] & 0x80);
+ if (ent->length != 0) {
+ ent->data = &apl->apl[apl->offset + 4];
+ } else {
+ ent->data = NULL;
+ }
+ return (ISC_R_SUCCESS);
+}
+
+unsigned int
+dns_rdata_apl_count(const dns_rdata_in_apl_t *apl) {
+ return (apl->apl_len);
+}
+
+static isc_result_t
+additionaldata_in_apl(ARGS_ADDLDATA) {
+ REQUIRE(rdata->type == dns_rdatatype_apl);
+ REQUIRE(rdata->rdclass == dns_rdataclass_in);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(add);
+ UNUSED(arg);
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+digest_in_apl(ARGS_DIGEST) {
+ isc_region_t r;
+
+ REQUIRE(rdata->type == dns_rdatatype_apl);
+ REQUIRE(rdata->rdclass == dns_rdataclass_in);
+
+ dns_rdata_toregion(rdata, &r);
+
+ return ((digest)(arg, &r));
+}
+
+static bool
+checkowner_in_apl(ARGS_CHECKOWNER) {
+ REQUIRE(type == dns_rdatatype_apl);
+ REQUIRE(rdclass == dns_rdataclass_in);
+
+ UNUSED(name);
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (true);
+}
+
+static bool
+checknames_in_apl(ARGS_CHECKNAMES) {
+ REQUIRE(rdata->type == dns_rdatatype_apl);
+ REQUIRE(rdata->rdclass == dns_rdataclass_in);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(bad);
+
+ return (true);
+}
+
+static int
+casecompare_in_apl(ARGS_COMPARE) {
+ return (compare_in_apl(rdata1, rdata2));
+}
+
+#endif /* RDATA_IN_1_APL_42_C */
diff --git a/lib/dns/rdata/in_1/apl_42.h b/lib/dns/rdata/in_1/apl_42.h
new file mode 100644
index 0000000..0a3f7ac
--- /dev/null
+++ b/lib/dns/rdata/in_1/apl_42.h
@@ -0,0 +1,50 @@
+/*
+ * 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_apl_ent {
+ bool negative;
+ uint16_t family;
+ uint8_t prefix;
+ uint8_t length;
+ unsigned char *data;
+} dns_rdata_apl_ent_t;
+
+typedef struct dns_rdata_in_apl {
+ dns_rdatacommon_t common;
+ isc_mem_t *mctx;
+ /* type & class specific elements */
+ unsigned char *apl;
+ uint16_t apl_len;
+ /* private */
+ uint16_t offset;
+} dns_rdata_in_apl_t;
+
+/*
+ * ISC_LANG_BEGINDECLS and ISC_LANG_ENDDECLS are already done
+ * via rdatastructpre.h and rdatastructsuf.h.
+ */
+
+isc_result_t
+dns_rdata_apl_first(dns_rdata_in_apl_t *);
+
+isc_result_t
+dns_rdata_apl_next(dns_rdata_in_apl_t *);
+
+isc_result_t
+dns_rdata_apl_current(dns_rdata_in_apl_t *, dns_rdata_apl_ent_t *);
+
+unsigned int
+dns_rdata_apl_count(const dns_rdata_in_apl_t *apl);
diff --git a/lib/dns/rdata/in_1/atma_34.c b/lib/dns/rdata/in_1/atma_34.c
new file mode 100644
index 0000000..b1a207a
--- /dev/null
+++ b/lib/dns/rdata/in_1/atma_34.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.
+ */
+
+/* http://www.broadband-forum.org/ftp/pub/approved-specs/af-dans-0152.000.pdf */
+
+#ifndef RDATA_IN_1_ATMA_22_C
+#define RDATA_IN_1_ATMA_22_C
+
+#define RRTYPE_ATMA_ATTRIBUTES (0)
+
+static isc_result_t
+fromtext_in_atma(ARGS_FROMTEXT) {
+ isc_token_t token;
+ isc_textregion_t *sr;
+ int n;
+ bool valid = false;
+ bool lastwasperiod = true; /* leading periods not allowed */
+ int digits = 0;
+ unsigned char c = 0;
+
+ REQUIRE(type == dns_rdatatype_atma);
+ REQUIRE(rdclass == dns_rdataclass_in);
+
+ UNUSED(type);
+ UNUSED(origin);
+ UNUSED(options);
+ UNUSED(rdclass);
+ UNUSED(callbacks);
+
+ /* ATM End System Address (AESA) format or E.164 */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ false));
+ sr = &token.value.as_textregion;
+ if (sr->length < 1) {
+ RETTOK(ISC_R_UNEXPECTEDEND);
+ }
+
+ if (sr->base[0] != '+') {
+ /*
+ * Format 0: ATM End System Address (AESA) format.
+ */
+ c = 0;
+ RETERR(mem_tobuffer(target, &c, 1));
+ while (sr->length > 0) {
+ if (sr->base[0] == '.') {
+ if (lastwasperiod) {
+ RETTOK(DNS_R_SYNTAX);
+ }
+ isc_textregion_consume(sr, 1);
+ lastwasperiod = true;
+ continue;
+ }
+ if ((n = hexvalue(sr->base[0])) == -1) {
+ RETTOK(DNS_R_SYNTAX);
+ }
+ c <<= 4;
+ c += n;
+ if (++digits == 2) {
+ RETERR(mem_tobuffer(target, &c, 1));
+ valid = true;
+ digits = 0;
+ c = 0;
+ }
+ isc_textregion_consume(sr, 1);
+ lastwasperiod = false;
+ }
+ if (digits != 0 || !valid || lastwasperiod) {
+ RETTOK(ISC_R_UNEXPECTEDEND);
+ }
+ } else {
+ /*
+ * Format 1: E.164.
+ */
+ c = 1;
+ RETERR(mem_tobuffer(target, &c, 1));
+ isc_textregion_consume(sr, 1);
+ while (sr->length > 0) {
+ if (sr->base[0] == '.') {
+ if (lastwasperiod) {
+ RETTOK(DNS_R_SYNTAX);
+ }
+ isc_textregion_consume(sr, 1);
+ lastwasperiod = true;
+ continue;
+ }
+ if (!isdigit((unsigned char)sr->base[0])) {
+ RETTOK(DNS_R_SYNTAX);
+ }
+ RETERR(mem_tobuffer(target, sr->base, 1));
+ isc_textregion_consume(sr, 1);
+ lastwasperiod = false;
+ }
+ if (lastwasperiod) {
+ RETTOK(ISC_R_UNEXPECTEDEND);
+ }
+ }
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+totext_in_atma(ARGS_TOTEXT) {
+ isc_region_t region;
+ char buf[sizeof("xx")];
+
+ REQUIRE(rdata->type == dns_rdatatype_atma);
+ REQUIRE(rdata->rdclass == dns_rdataclass_in);
+ REQUIRE(rdata->length != 0);
+
+ UNUSED(tctx);
+
+ dns_rdata_toregion(rdata, &region);
+ INSIST(region.length > 1);
+ switch (region.base[0]) {
+ case 0:
+ isc_region_consume(&region, 1);
+ while (region.length != 0) {
+ snprintf(buf, sizeof(buf), "%02x", region.base[0]);
+ isc_region_consume(&region, 1);
+ RETERR(str_totext(buf, target));
+ }
+ break;
+ case 1:
+ RETERR(str_totext("+", target));
+ isc_region_consume(&region, 1);
+ RETERR(mem_tobuffer(target, region.base, region.length));
+ break;
+ default:
+ return (ISC_R_NOTIMPLEMENTED);
+ }
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+fromwire_in_atma(ARGS_FROMWIRE) {
+ isc_region_t region;
+
+ REQUIRE(type == dns_rdatatype_atma);
+ REQUIRE(rdclass == dns_rdataclass_in);
+
+ UNUSED(type);
+ UNUSED(dctx);
+ UNUSED(options);
+ UNUSED(rdclass);
+
+ isc_buffer_activeregion(source, &region);
+ if (region.length < 2) {
+ return (ISC_R_UNEXPECTEDEND);
+ }
+ if (region.base[0] == 1) {
+ unsigned int i;
+ for (i = 1; i < region.length; i++) {
+ if (!isdigit((unsigned char)region.base[i])) {
+ return (DNS_R_FORMERR);
+ }
+ }
+ }
+ RETERR(mem_tobuffer(target, region.base, region.length));
+ isc_buffer_forward(source, region.length);
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+towire_in_atma(ARGS_TOWIRE) {
+ REQUIRE(rdata->type == dns_rdatatype_atma);
+ REQUIRE(rdata->rdclass == dns_rdataclass_in);
+ REQUIRE(rdata->length != 0);
+
+ UNUSED(cctx);
+
+ return (mem_tobuffer(target, rdata->data, rdata->length));
+}
+
+static int
+compare_in_atma(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_atma);
+ REQUIRE(rdata1->rdclass == dns_rdataclass_in);
+ 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_in_atma(ARGS_FROMSTRUCT) {
+ dns_rdata_in_atma_t *atma = source;
+
+ REQUIRE(type == dns_rdatatype_atma);
+ REQUIRE(rdclass == dns_rdataclass_in);
+ REQUIRE(atma != NULL);
+ REQUIRE(atma->common.rdtype == type);
+ REQUIRE(atma->common.rdclass == rdclass);
+ REQUIRE(atma->atma != NULL || atma->atma_len == 0);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ RETERR(mem_tobuffer(target, &atma->format, 1));
+ return (mem_tobuffer(target, atma->atma, atma->atma_len));
+}
+
+static isc_result_t
+tostruct_in_atma(ARGS_TOSTRUCT) {
+ dns_rdata_in_atma_t *atma = target;
+ isc_region_t r;
+
+ REQUIRE(rdata->type == dns_rdatatype_atma);
+ REQUIRE(rdata->rdclass == dns_rdataclass_in);
+ REQUIRE(atma != NULL);
+ REQUIRE(rdata->length != 0);
+
+ atma->common.rdclass = rdata->rdclass;
+ atma->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&atma->common, link);
+
+ dns_rdata_toregion(rdata, &r);
+ atma->format = r.base[0];
+ isc_region_consume(&r, 1);
+ atma->atma_len = r.length;
+ atma->atma = mem_maybedup(mctx, r.base, r.length);
+ if (atma->atma == NULL) {
+ return (ISC_R_NOMEMORY);
+ }
+
+ atma->mctx = mctx;
+ return (ISC_R_SUCCESS);
+}
+
+static void
+freestruct_in_atma(ARGS_FREESTRUCT) {
+ dns_rdata_in_atma_t *atma = source;
+
+ REQUIRE(atma != NULL);
+ REQUIRE(atma->common.rdclass == dns_rdataclass_in);
+ REQUIRE(atma->common.rdtype == dns_rdatatype_atma);
+
+ if (atma->mctx == NULL) {
+ return;
+ }
+
+ if (atma->atma != NULL) {
+ isc_mem_free(atma->mctx, atma->atma);
+ }
+ atma->mctx = NULL;
+}
+
+static isc_result_t
+additionaldata_in_atma(ARGS_ADDLDATA) {
+ REQUIRE(rdata->type == dns_rdatatype_atma);
+ REQUIRE(rdata->rdclass == dns_rdataclass_in);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(add);
+ UNUSED(arg);
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+digest_in_atma(ARGS_DIGEST) {
+ isc_region_t r;
+
+ REQUIRE(rdata->type == dns_rdatatype_atma);
+ REQUIRE(rdata->rdclass == dns_rdataclass_in);
+
+ dns_rdata_toregion(rdata, &r);
+
+ return ((digest)(arg, &r));
+}
+
+static bool
+checkowner_in_atma(ARGS_CHECKOWNER) {
+ REQUIRE(type == dns_rdatatype_atma);
+ REQUIRE(rdclass == dns_rdataclass_in);
+
+ UNUSED(name);
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (true);
+}
+
+static bool
+checknames_in_atma(ARGS_CHECKNAMES) {
+ REQUIRE(rdata->type == dns_rdatatype_atma);
+ REQUIRE(rdata->rdclass == dns_rdataclass_in);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(bad);
+
+ return (true);
+}
+
+static int
+casecompare_in_atma(ARGS_COMPARE) {
+ return (compare_in_atma(rdata1, rdata2));
+}
+
+#endif /* RDATA_IN_1_atma_22_C */
diff --git a/lib/dns/rdata/in_1/atma_34.h b/lib/dns/rdata/in_1/atma_34.h
new file mode 100644
index 0000000..412b428
--- /dev/null
+++ b/lib/dns/rdata/in_1/atma_34.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 RFC1706 */
+
+typedef struct dns_rdata_in_atma {
+ dns_rdatacommon_t common;
+ isc_mem_t *mctx;
+ unsigned char format;
+ unsigned char *atma;
+ uint16_t atma_len;
+} dns_rdata_in_atma_t;
diff --git a/lib/dns/rdata/in_1/dhcid_49.c b/lib/dns/rdata/in_1/dhcid_49.c
new file mode 100644
index 0000000..b3f664b
--- /dev/null
+++ b/lib/dns/rdata/in_1/dhcid_49.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.
+ */
+
+/* RFC 4701 */
+
+#ifndef RDATA_IN_1_DHCID_49_C
+#define RDATA_IN_1_DHCID_49_C 1
+
+#define RRTYPE_DHCID_ATTRIBUTES 0
+
+static isc_result_t
+fromtext_in_dhcid(ARGS_FROMTEXT) {
+ REQUIRE(type == dns_rdatatype_dhcid);
+ REQUIRE(rdclass == dns_rdataclass_in);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(origin);
+ UNUSED(options);
+ UNUSED(callbacks);
+
+ return (isc_base64_tobuffer(lexer, target, -2));
+}
+
+static isc_result_t
+totext_in_dhcid(ARGS_TOTEXT) {
+ isc_region_t sr, sr2;
+ /* " ; 64000 255 64000" */
+ char buf[5 + 3 * 11 + 1];
+
+ REQUIRE(rdata->type == dns_rdatatype_dhcid);
+ REQUIRE(rdata->rdclass == dns_rdataclass_in);
+ REQUIRE(rdata->length != 0);
+
+ dns_rdata_toregion(rdata, &sr);
+ sr2 = sr;
+
+ if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) {
+ RETERR(str_totext("( " /*)*/, 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));
+ if (rdata->length > 2) {
+ snprintf(buf, sizeof(buf), " ; %u %u %u",
+ sr2.base[0] * 256U + sr2.base[1], sr2.base[2],
+ rdata->length - 3U);
+ RETERR(str_totext(buf, target));
+ }
+ }
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+fromwire_in_dhcid(ARGS_FROMWIRE) {
+ isc_region_t sr;
+
+ REQUIRE(type == dns_rdatatype_dhcid);
+ REQUIRE(rdclass == dns_rdataclass_in);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(dctx);
+ UNUSED(options);
+
+ 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_in_dhcid(ARGS_TOWIRE) {
+ isc_region_t sr;
+
+ REQUIRE(rdata->type == dns_rdatatype_dhcid);
+ REQUIRE(rdata->rdclass == dns_rdataclass_in);
+ REQUIRE(rdata->length != 0);
+
+ UNUSED(cctx);
+
+ dns_rdata_toregion(rdata, &sr);
+ return (mem_tobuffer(target, sr.base, sr.length));
+}
+
+static int
+compare_in_dhcid(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_dhcid);
+ REQUIRE(rdata1->rdclass == dns_rdataclass_in);
+ 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_in_dhcid(ARGS_FROMSTRUCT) {
+ dns_rdata_in_dhcid_t *dhcid = source;
+
+ REQUIRE(type == dns_rdatatype_dhcid);
+ REQUIRE(rdclass == dns_rdataclass_in);
+ REQUIRE(dhcid != NULL);
+ REQUIRE(dhcid->common.rdtype == type);
+ REQUIRE(dhcid->common.rdclass == rdclass);
+ REQUIRE(dhcid->length != 0);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ return (mem_tobuffer(target, dhcid->dhcid, dhcid->length));
+}
+
+static isc_result_t
+tostruct_in_dhcid(ARGS_TOSTRUCT) {
+ dns_rdata_in_dhcid_t *dhcid = target;
+ isc_region_t region;
+
+ REQUIRE(rdata->type == dns_rdatatype_dhcid);
+ REQUIRE(rdata->rdclass == dns_rdataclass_in);
+ REQUIRE(dhcid != NULL);
+ REQUIRE(rdata->length != 0);
+
+ dhcid->common.rdclass = rdata->rdclass;
+ dhcid->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&dhcid->common, link);
+
+ dns_rdata_toregion(rdata, &region);
+
+ dhcid->dhcid = mem_maybedup(mctx, region.base, region.length);
+ if (dhcid->dhcid == NULL) {
+ return (ISC_R_NOMEMORY);
+ }
+
+ dhcid->mctx = mctx;
+ return (ISC_R_SUCCESS);
+}
+
+static void
+freestruct_in_dhcid(ARGS_FREESTRUCT) {
+ dns_rdata_in_dhcid_t *dhcid = source;
+
+ REQUIRE(dhcid != NULL);
+ REQUIRE(dhcid->common.rdtype == dns_rdatatype_dhcid);
+ REQUIRE(dhcid->common.rdclass == dns_rdataclass_in);
+
+ if (dhcid->mctx == NULL) {
+ return;
+ }
+
+ if (dhcid->dhcid != NULL) {
+ isc_mem_free(dhcid->mctx, dhcid->dhcid);
+ }
+ dhcid->mctx = NULL;
+}
+
+static isc_result_t
+additionaldata_in_dhcid(ARGS_ADDLDATA) {
+ REQUIRE(rdata->type == dns_rdatatype_dhcid);
+ REQUIRE(rdata->rdclass == dns_rdataclass_in);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(add);
+ UNUSED(arg);
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+digest_in_dhcid(ARGS_DIGEST) {
+ isc_region_t r;
+
+ REQUIRE(rdata->type == dns_rdatatype_dhcid);
+ REQUIRE(rdata->rdclass == dns_rdataclass_in);
+
+ dns_rdata_toregion(rdata, &r);
+
+ return ((digest)(arg, &r));
+}
+
+static bool
+checkowner_in_dhcid(ARGS_CHECKOWNER) {
+ REQUIRE(type == dns_rdatatype_dhcid);
+ REQUIRE(rdclass == dns_rdataclass_in);
+
+ UNUSED(name);
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (true);
+}
+
+static bool
+checknames_in_dhcid(ARGS_CHECKNAMES) {
+ REQUIRE(rdata->type == dns_rdatatype_dhcid);
+ REQUIRE(rdata->rdclass == dns_rdataclass_in);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(bad);
+
+ return (true);
+}
+
+static int
+casecompare_in_dhcid(ARGS_COMPARE) {
+ return (compare_in_dhcid(rdata1, rdata2));
+}
+
+#endif /* RDATA_IN_1_DHCID_49_C */
diff --git a/lib/dns/rdata/in_1/dhcid_49.h b/lib/dns/rdata/in_1/dhcid_49.h
new file mode 100644
index 0000000..338476e
--- /dev/null
+++ b/lib/dns/rdata/in_1/dhcid_49.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_in_dhcid {
+ dns_rdatacommon_t common;
+ isc_mem_t *mctx;
+ unsigned char *dhcid;
+ unsigned int length;
+} dns_rdata_in_dhcid_t;
diff --git a/lib/dns/rdata/in_1/eid_31.c b/lib/dns/rdata/in_1/eid_31.c
new file mode 100644
index 0000000..e5046ca
--- /dev/null
+++ b/lib/dns/rdata/in_1/eid_31.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.
+ */
+
+/* http://ana-3.lcs.mit.edu/~jnc/nimrod/dns.txt */
+
+#ifndef RDATA_IN_1_EID_31_C
+#define RDATA_IN_1_EID_31_C
+
+#define RRTYPE_EID_ATTRIBUTES (0)
+
+static isc_result_t
+fromtext_in_eid(ARGS_FROMTEXT) {
+ REQUIRE(type == dns_rdatatype_eid);
+ REQUIRE(rdclass == dns_rdataclass_in);
+
+ UNUSED(type);
+ UNUSED(origin);
+ UNUSED(options);
+ UNUSED(rdclass);
+ UNUSED(callbacks);
+
+ return (isc_hex_tobuffer(lexer, target, -2));
+}
+
+static isc_result_t
+totext_in_eid(ARGS_TOTEXT) {
+ isc_region_t region;
+
+ REQUIRE(rdata->type == dns_rdatatype_eid);
+ REQUIRE(rdata->rdclass == dns_rdataclass_in);
+ REQUIRE(rdata->length != 0);
+
+ dns_rdata_toregion(rdata, &region);
+
+ if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) {
+ RETERR(str_totext("( ", target));
+ }
+ if (tctx->width == 0) {
+ RETERR(isc_hex_totext(&region, 60, "", target));
+ } else {
+ RETERR(isc_hex_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_in_eid(ARGS_FROMWIRE) {
+ isc_region_t region;
+
+ REQUIRE(type == dns_rdatatype_eid);
+ REQUIRE(rdclass == dns_rdataclass_in);
+
+ UNUSED(type);
+ UNUSED(dctx);
+ UNUSED(options);
+ UNUSED(rdclass);
+
+ isc_buffer_activeregion(source, &region);
+ if (region.length < 1) {
+ return (ISC_R_UNEXPECTEDEND);
+ }
+
+ RETERR(mem_tobuffer(target, region.base, region.length));
+ isc_buffer_forward(source, region.length);
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+towire_in_eid(ARGS_TOWIRE) {
+ REQUIRE(rdata->type == dns_rdatatype_eid);
+ REQUIRE(rdata->rdclass == dns_rdataclass_in);
+ REQUIRE(rdata->length != 0);
+
+ UNUSED(cctx);
+
+ return (mem_tobuffer(target, rdata->data, rdata->length));
+}
+
+static int
+compare_in_eid(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_eid);
+ REQUIRE(rdata1->rdclass == dns_rdataclass_in);
+ 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_in_eid(ARGS_FROMSTRUCT) {
+ dns_rdata_in_eid_t *eid = source;
+
+ REQUIRE(type == dns_rdatatype_eid);
+ REQUIRE(rdclass == dns_rdataclass_in);
+ REQUIRE(eid != NULL);
+ REQUIRE(eid->common.rdtype == type);
+ REQUIRE(eid->common.rdclass == rdclass);
+ REQUIRE(eid->eid != NULL || eid->eid_len == 0);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ return (mem_tobuffer(target, eid->eid, eid->eid_len));
+}
+
+static isc_result_t
+tostruct_in_eid(ARGS_TOSTRUCT) {
+ dns_rdata_in_eid_t *eid = target;
+ isc_region_t r;
+
+ REQUIRE(rdata->type == dns_rdatatype_eid);
+ REQUIRE(rdata->rdclass == dns_rdataclass_in);
+ REQUIRE(eid != NULL);
+ REQUIRE(rdata->length != 0);
+
+ eid->common.rdclass = rdata->rdclass;
+ eid->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&eid->common, link);
+
+ dns_rdata_toregion(rdata, &r);
+ eid->eid_len = r.length;
+ eid->eid = mem_maybedup(mctx, r.base, r.length);
+ if (eid->eid == NULL) {
+ return (ISC_R_NOMEMORY);
+ }
+
+ eid->mctx = mctx;
+ return (ISC_R_SUCCESS);
+}
+
+static void
+freestruct_in_eid(ARGS_FREESTRUCT) {
+ dns_rdata_in_eid_t *eid = source;
+
+ REQUIRE(eid != NULL);
+ REQUIRE(eid->common.rdclass == dns_rdataclass_in);
+ REQUIRE(eid->common.rdtype == dns_rdatatype_eid);
+
+ if (eid->mctx == NULL) {
+ return;
+ }
+
+ if (eid->eid != NULL) {
+ isc_mem_free(eid->mctx, eid->eid);
+ }
+ eid->mctx = NULL;
+}
+
+static isc_result_t
+additionaldata_in_eid(ARGS_ADDLDATA) {
+ REQUIRE(rdata->type == dns_rdatatype_eid);
+ REQUIRE(rdata->rdclass == dns_rdataclass_in);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(add);
+ UNUSED(arg);
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+digest_in_eid(ARGS_DIGEST) {
+ isc_region_t r;
+
+ REQUIRE(rdata->type == dns_rdatatype_eid);
+ REQUIRE(rdata->rdclass == dns_rdataclass_in);
+
+ dns_rdata_toregion(rdata, &r);
+
+ return ((digest)(arg, &r));
+}
+
+static bool
+checkowner_in_eid(ARGS_CHECKOWNER) {
+ REQUIRE(type == dns_rdatatype_eid);
+ REQUIRE(rdclass == dns_rdataclass_in);
+
+ UNUSED(name);
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (true);
+}
+
+static bool
+checknames_in_eid(ARGS_CHECKNAMES) {
+ REQUIRE(rdata->type == dns_rdatatype_eid);
+ REQUIRE(rdata->rdclass == dns_rdataclass_in);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(bad);
+
+ return (true);
+}
+
+static int
+casecompare_in_eid(ARGS_COMPARE) {
+ return (compare_in_eid(rdata1, rdata2));
+}
+
+#endif /* RDATA_IN_1_EID_31_C */
diff --git a/lib/dns/rdata/in_1/eid_31.h b/lib/dns/rdata/in_1/eid_31.h
new file mode 100644
index 0000000..d32bd3e
--- /dev/null
+++ b/lib/dns/rdata/in_1/eid_31.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 http://ana-3.lcs.mit.edu/~jnc/nimrod/dns.txt
+ */
+
+typedef struct dns_rdata_in_eid {
+ dns_rdatacommon_t common;
+ isc_mem_t *mctx;
+ unsigned char *eid;
+ uint16_t eid_len;
+} dns_rdata_in_eid_t;
diff --git a/lib/dns/rdata/in_1/https_65.c b/lib/dns/rdata/in_1/https_65.c
new file mode 100644
index 0000000..af1ad7f
--- /dev/null
+++ b/lib/dns/rdata/in_1/https_65.c
@@ -0,0 +1,183 @@
+/*
+ * 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-svcb-https-02 */
+
+#pragma once
+
+#define RRTYPE_HTTPS_ATTRIBUTES (DNS_RDATATYPEATTR_FOLLOWADDITIONAL)
+
+/*
+ * Most of these functions refer to equivalent functions for SVCB,
+ * since wire and presentation formats are identical.
+ */
+
+static isc_result_t
+fromtext_in_https(ARGS_FROMTEXT) {
+ REQUIRE(type == dns_rdatatype_https);
+ REQUIRE(rdclass == dns_rdataclass_in);
+
+ return (generic_fromtext_in_svcb(CALL_FROMTEXT));
+}
+
+static isc_result_t
+totext_in_https(ARGS_TOTEXT) {
+ REQUIRE(rdata->type == dns_rdatatype_https);
+ REQUIRE(rdata->rdclass == dns_rdataclass_in);
+ REQUIRE(rdata->length != 0);
+
+ return (generic_totext_in_svcb(CALL_TOTEXT));
+}
+
+static isc_result_t
+fromwire_in_https(ARGS_FROMWIRE) {
+ REQUIRE(type == dns_rdatatype_https);
+ REQUIRE(rdclass == dns_rdataclass_in);
+
+ return (generic_fromwire_in_svcb(CALL_FROMWIRE));
+}
+
+static isc_result_t
+towire_in_https(ARGS_TOWIRE) {
+ REQUIRE(rdata->type == dns_rdatatype_https);
+ REQUIRE(rdata->length != 0);
+
+ return (generic_towire_in_svcb(CALL_TOWIRE));
+}
+
+static int
+compare_in_https(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_https);
+ REQUIRE(rdata1->rdclass == dns_rdataclass_in);
+ 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_in_https(ARGS_FROMSTRUCT) {
+ dns_rdata_in_https_t *https = source;
+
+ REQUIRE(type == dns_rdatatype_https);
+ REQUIRE(rdclass == dns_rdataclass_in);
+ REQUIRE(https != NULL);
+ REQUIRE(https->common.rdtype == type);
+ REQUIRE(https->common.rdclass == rdclass);
+
+ return (generic_fromstruct_in_svcb(CALL_FROMSTRUCT));
+}
+
+static isc_result_t
+tostruct_in_https(ARGS_TOSTRUCT) {
+ dns_rdata_in_https_t *https = target;
+
+ REQUIRE(rdata->rdclass == dns_rdataclass_in);
+ REQUIRE(rdata->type == dns_rdatatype_https);
+ REQUIRE(https != NULL);
+ REQUIRE(rdata->length != 0);
+
+ return (generic_tostruct_in_svcb(CALL_TOSTRUCT));
+}
+
+static void
+freestruct_in_https(ARGS_FREESTRUCT) {
+ dns_rdata_in_https_t *https = source;
+
+ REQUIRE(https != NULL);
+ REQUIRE(https->common.rdclass == dns_rdataclass_in);
+ REQUIRE(https->common.rdtype == dns_rdatatype_https);
+
+ generic_freestruct_in_svcb(CALL_FREESTRUCT);
+}
+
+static isc_result_t
+additionaldata_in_https(ARGS_ADDLDATA) {
+ REQUIRE(rdata->type == dns_rdatatype_https);
+ REQUIRE(rdata->rdclass == dns_rdataclass_in);
+
+ return (generic_additionaldata_in_svcb(CALL_ADDLDATA));
+}
+
+static isc_result_t
+digest_in_https(ARGS_DIGEST) {
+ isc_region_t region1;
+
+ REQUIRE(rdata->type == dns_rdatatype_https);
+ REQUIRE(rdata->rdclass == dns_rdataclass_in);
+
+ dns_rdata_toregion(rdata, &region1);
+ return ((digest)(arg, &region1));
+}
+
+static bool
+checkowner_in_https(ARGS_CHECKOWNER) {
+ REQUIRE(type == dns_rdatatype_https);
+ REQUIRE(rdclass == dns_rdataclass_in);
+
+ UNUSED(name);
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (true);
+}
+
+static bool
+checknames_in_https(ARGS_CHECKNAMES) {
+ REQUIRE(rdata->type == dns_rdatatype_https);
+ REQUIRE(rdata->rdclass == dns_rdataclass_in);
+
+ return (generic_checknames_in_svcb(CALL_CHECKNAMES));
+}
+
+static int
+casecompare_in_https(ARGS_COMPARE) {
+ return (compare_in_https(rdata1, rdata2));
+}
+
+isc_result_t
+dns_rdata_in_https_first(dns_rdata_in_https_t *https) {
+ REQUIRE(https != NULL);
+ REQUIRE(https->common.rdtype == dns_rdatatype_https);
+ REQUIRE(https->common.rdclass == dns_rdataclass_in);
+
+ return (generic_rdata_in_svcb_first(https));
+}
+
+isc_result_t
+dns_rdata_in_https_next(dns_rdata_in_https_t *https) {
+ REQUIRE(https != NULL);
+ REQUIRE(https->common.rdtype == dns_rdatatype_https);
+ REQUIRE(https->common.rdclass == dns_rdataclass_in);
+
+ return (generic_rdata_in_svcb_next(https));
+}
+
+void
+dns_rdata_in_https_current(dns_rdata_in_https_t *https, isc_region_t *region) {
+ REQUIRE(https != NULL);
+ REQUIRE(https->common.rdtype == dns_rdatatype_https);
+ REQUIRE(https->common.rdclass == dns_rdataclass_in);
+ REQUIRE(region != NULL);
+
+ generic_rdata_in_svcb_current(https, region);
+}
diff --git a/lib/dns/rdata/in_1/https_65.h b/lib/dns/rdata/in_1/https_65.h
new file mode 100644
index 0000000..589f983
--- /dev/null
+++ b/lib/dns/rdata/in_1/https_65.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 draft-ietf-dnsop-svcb-https-02
+ */
+
+/*
+ * Wire and presentation formats for HTTPS are identical to SVCB.
+ */
+typedef struct dns_rdata_in_svcb dns_rdata_in_https_t;
+
+isc_result_t
+dns_rdata_in_https_first(dns_rdata_in_https_t *);
+
+isc_result_t
+dns_rdata_in_https_next(dns_rdata_in_https_t *);
+
+void
+dns_rdata_in_https_current(dns_rdata_in_https_t *, isc_region_t *);
diff --git a/lib/dns/rdata/in_1/kx_36.c b/lib/dns/rdata/in_1/kx_36.c
new file mode 100644
index 0000000..ce48db1
--- /dev/null
+++ b/lib/dns/rdata/in_1/kx_36.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.
+ */
+
+/* RFC2230 */
+
+#ifndef RDATA_IN_1_KX_36_C
+#define RDATA_IN_1_KX_36_C
+
+#define RRTYPE_KX_ATTRIBUTES (0)
+
+static isc_result_t
+fromtext_in_kx(ARGS_FROMTEXT) {
+ isc_token_t token;
+ dns_name_t name;
+ isc_buffer_t buffer;
+
+ REQUIRE(type == dns_rdatatype_kx);
+ REQUIRE(rdclass == dns_rdataclass_in);
+
+ 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));
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+totext_in_kx(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_kx);
+ REQUIRE(rdata->rdclass == dns_rdataclass_in);
+ 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_in_kx(ARGS_FROMWIRE) {
+ dns_name_t name;
+ isc_region_t sregion;
+
+ REQUIRE(type == dns_rdatatype_kx);
+ REQUIRE(rdclass == dns_rdataclass_in);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ dns_decompress_setmethods(dctx, DNS_COMPRESS_NONE);
+
+ 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_in_kx(ARGS_TOWIRE) {
+ dns_name_t name;
+ dns_offsets_t offsets;
+ isc_region_t region;
+
+ REQUIRE(rdata->type == dns_rdatatype_kx);
+ REQUIRE(rdata->rdclass == dns_rdataclass_in);
+ REQUIRE(rdata->length != 0);
+
+ dns_compress_setmethods(cctx, DNS_COMPRESS_NONE);
+ 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_in_kx(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_kx);
+ REQUIRE(rdata1->rdclass == dns_rdataclass_in);
+ 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_in_kx(ARGS_FROMSTRUCT) {
+ dns_rdata_in_kx_t *kx = source;
+ isc_region_t region;
+
+ REQUIRE(type == dns_rdatatype_kx);
+ REQUIRE(rdclass == dns_rdataclass_in);
+ REQUIRE(kx != NULL);
+ REQUIRE(kx->common.rdtype == type);
+ REQUIRE(kx->common.rdclass == rdclass);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ RETERR(uint16_tobuffer(kx->preference, target));
+ dns_name_toregion(&kx->exchange, &region);
+ return (isc_buffer_copyregion(target, &region));
+}
+
+static isc_result_t
+tostruct_in_kx(ARGS_TOSTRUCT) {
+ isc_region_t region;
+ dns_rdata_in_kx_t *kx = target;
+ dns_name_t name;
+
+ REQUIRE(rdata->type == dns_rdatatype_kx);
+ REQUIRE(rdata->rdclass == dns_rdataclass_in);
+ REQUIRE(kx != NULL);
+ REQUIRE(rdata->length != 0);
+
+ kx->common.rdclass = rdata->rdclass;
+ kx->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&kx->common, link);
+
+ dns_name_init(&name, NULL);
+ dns_rdata_toregion(rdata, &region);
+
+ kx->preference = uint16_fromregion(&region);
+ isc_region_consume(&region, 2);
+
+ dns_name_fromregion(&name, &region);
+ dns_name_init(&kx->exchange, NULL);
+ name_duporclone(&name, mctx, &kx->exchange);
+ kx->mctx = mctx;
+ return (ISC_R_SUCCESS);
+}
+
+static void
+freestruct_in_kx(ARGS_FREESTRUCT) {
+ dns_rdata_in_kx_t *kx = source;
+
+ REQUIRE(kx != NULL);
+ REQUIRE(kx->common.rdclass == dns_rdataclass_in);
+ REQUIRE(kx->common.rdtype == dns_rdatatype_kx);
+
+ if (kx->mctx == NULL) {
+ return;
+ }
+
+ dns_name_free(&kx->exchange, kx->mctx);
+ kx->mctx = NULL;
+}
+
+static isc_result_t
+additionaldata_in_kx(ARGS_ADDLDATA) {
+ dns_name_t name;
+ dns_offsets_t offsets;
+ isc_region_t region;
+
+ REQUIRE(rdata->type == dns_rdatatype_kx);
+ REQUIRE(rdata->rdclass == dns_rdataclass_in);
+
+ 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_in_kx(ARGS_DIGEST) {
+ isc_region_t r1, r2;
+ dns_name_t name;
+
+ REQUIRE(rdata->type == dns_rdatatype_kx);
+ REQUIRE(rdata->rdclass == dns_rdataclass_in);
+
+ 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_in_kx(ARGS_CHECKOWNER) {
+ REQUIRE(type == dns_rdatatype_kx);
+ REQUIRE(rdclass == dns_rdataclass_in);
+
+ UNUSED(name);
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (true);
+}
+
+static bool
+checknames_in_kx(ARGS_CHECKNAMES) {
+ REQUIRE(rdata->type == dns_rdatatype_kx);
+ REQUIRE(rdata->rdclass == dns_rdataclass_in);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(bad);
+
+ return (true);
+}
+
+static int
+casecompare_in_kx(ARGS_COMPARE) {
+ return (compare_in_kx(rdata1, rdata2));
+}
+
+#endif /* RDATA_IN_1_KX_36_C */
diff --git a/lib/dns/rdata/in_1/kx_36.h b/lib/dns/rdata/in_1/kx_36.h
new file mode 100644
index 0000000..9e2243b
--- /dev/null
+++ b/lib/dns/rdata/in_1/kx_36.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 RFC2230 */
+
+typedef struct dns_rdata_in_kx {
+ dns_rdatacommon_t common;
+ isc_mem_t *mctx;
+ uint16_t preference;
+ dns_name_t exchange;
+} dns_rdata_in_kx_t;
diff --git a/lib/dns/rdata/in_1/nimloc_32.c b/lib/dns/rdata/in_1/nimloc_32.c
new file mode 100644
index 0000000..6a9cdb4
--- /dev/null
+++ b/lib/dns/rdata/in_1/nimloc_32.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.
+ */
+
+/* http://ana-3.lcs.mit.edu/~jnc/nimrod/dns.txt */
+
+#ifndef RDATA_IN_1_NIMLOC_32_C
+#define RDATA_IN_1_NIMLOC_32_C
+
+#define RRTYPE_NIMLOC_ATTRIBUTES (0)
+
+static isc_result_t
+fromtext_in_nimloc(ARGS_FROMTEXT) {
+ REQUIRE(type == dns_rdatatype_nimloc);
+ REQUIRE(rdclass == dns_rdataclass_in);
+
+ UNUSED(type);
+ UNUSED(origin);
+ UNUSED(options);
+ UNUSED(rdclass);
+ UNUSED(callbacks);
+
+ return (isc_hex_tobuffer(lexer, target, -2));
+}
+
+static isc_result_t
+totext_in_nimloc(ARGS_TOTEXT) {
+ isc_region_t region;
+
+ REQUIRE(rdata->type == dns_rdatatype_nimloc);
+ REQUIRE(rdata->rdclass == dns_rdataclass_in);
+ REQUIRE(rdata->length != 0);
+
+ dns_rdata_toregion(rdata, &region);
+
+ if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) {
+ RETERR(str_totext("( ", target));
+ }
+ if (tctx->width == 0) {
+ RETERR(isc_hex_totext(&region, 60, "", target));
+ } else {
+ RETERR(isc_hex_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_in_nimloc(ARGS_FROMWIRE) {
+ isc_region_t region;
+
+ REQUIRE(type == dns_rdatatype_nimloc);
+ REQUIRE(rdclass == dns_rdataclass_in);
+
+ UNUSED(type);
+ UNUSED(dctx);
+ UNUSED(options);
+ UNUSED(rdclass);
+
+ isc_buffer_activeregion(source, &region);
+ if (region.length < 1) {
+ return (ISC_R_UNEXPECTEDEND);
+ }
+
+ RETERR(mem_tobuffer(target, region.base, region.length));
+ isc_buffer_forward(source, region.length);
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+towire_in_nimloc(ARGS_TOWIRE) {
+ REQUIRE(rdata->type == dns_rdatatype_nimloc);
+ REQUIRE(rdata->rdclass == dns_rdataclass_in);
+ REQUIRE(rdata->length != 0);
+
+ UNUSED(cctx);
+
+ return (mem_tobuffer(target, rdata->data, rdata->length));
+}
+
+static int
+compare_in_nimloc(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_nimloc);
+ REQUIRE(rdata1->rdclass == dns_rdataclass_in);
+ 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_in_nimloc(ARGS_FROMSTRUCT) {
+ dns_rdata_in_nimloc_t *nimloc = source;
+
+ REQUIRE(type == dns_rdatatype_nimloc);
+ REQUIRE(rdclass == dns_rdataclass_in);
+ REQUIRE(nimloc != NULL);
+ REQUIRE(nimloc->common.rdtype == type);
+ REQUIRE(nimloc->common.rdclass == rdclass);
+ REQUIRE(nimloc->nimloc != NULL || nimloc->nimloc_len == 0);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ return (mem_tobuffer(target, nimloc->nimloc, nimloc->nimloc_len));
+}
+
+static isc_result_t
+tostruct_in_nimloc(ARGS_TOSTRUCT) {
+ dns_rdata_in_nimloc_t *nimloc = target;
+ isc_region_t r;
+
+ REQUIRE(rdata->type == dns_rdatatype_nimloc);
+ REQUIRE(rdata->rdclass == dns_rdataclass_in);
+ REQUIRE(nimloc != NULL);
+ REQUIRE(rdata->length != 0);
+
+ nimloc->common.rdclass = rdata->rdclass;
+ nimloc->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&nimloc->common, link);
+
+ dns_rdata_toregion(rdata, &r);
+ nimloc->nimloc_len = r.length;
+ nimloc->nimloc = mem_maybedup(mctx, r.base, r.length);
+ if (nimloc->nimloc == NULL) {
+ return (ISC_R_NOMEMORY);
+ }
+
+ nimloc->mctx = mctx;
+ return (ISC_R_SUCCESS);
+}
+
+static void
+freestruct_in_nimloc(ARGS_FREESTRUCT) {
+ dns_rdata_in_nimloc_t *nimloc = source;
+
+ REQUIRE(nimloc != NULL);
+ REQUIRE(nimloc->common.rdclass == dns_rdataclass_in);
+ REQUIRE(nimloc->common.rdtype == dns_rdatatype_nimloc);
+
+ if (nimloc->mctx == NULL) {
+ return;
+ }
+
+ if (nimloc->nimloc != NULL) {
+ isc_mem_free(nimloc->mctx, nimloc->nimloc);
+ }
+ nimloc->mctx = NULL;
+}
+
+static isc_result_t
+additionaldata_in_nimloc(ARGS_ADDLDATA) {
+ REQUIRE(rdata->type == dns_rdatatype_nimloc);
+ REQUIRE(rdata->rdclass == dns_rdataclass_in);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(add);
+ UNUSED(arg);
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+digest_in_nimloc(ARGS_DIGEST) {
+ isc_region_t r;
+
+ REQUIRE(rdata->type == dns_rdatatype_nimloc);
+ REQUIRE(rdata->rdclass == dns_rdataclass_in);
+
+ dns_rdata_toregion(rdata, &r);
+
+ return ((digest)(arg, &r));
+}
+
+static bool
+checkowner_in_nimloc(ARGS_CHECKOWNER) {
+ REQUIRE(type == dns_rdatatype_nimloc);
+ REQUIRE(rdclass == dns_rdataclass_in);
+
+ UNUSED(name);
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (true);
+}
+
+static bool
+checknames_in_nimloc(ARGS_CHECKNAMES) {
+ REQUIRE(rdata->type == dns_rdatatype_nimloc);
+ REQUIRE(rdata->rdclass == dns_rdataclass_in);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(bad);
+
+ return (true);
+}
+
+static int
+casecompare_in_nimloc(ARGS_COMPARE) {
+ return (compare_in_nimloc(rdata1, rdata2));
+}
+
+#endif /* RDATA_IN_1_NIMLOC_32_C */
diff --git a/lib/dns/rdata/in_1/nimloc_32.h b/lib/dns/rdata/in_1/nimloc_32.h
new file mode 100644
index 0000000..faa9196
--- /dev/null
+++ b/lib/dns/rdata/in_1/nimloc_32.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 http://ana-3.lcs.mit.edu/~jnc/nimrod/dns.txt
+ */
+
+typedef struct dns_rdata_in_nimloc {
+ dns_rdatacommon_t common;
+ isc_mem_t *mctx;
+ unsigned char *nimloc;
+ uint16_t nimloc_len;
+} dns_rdata_in_nimloc_t;
diff --git a/lib/dns/rdata/in_1/nsap-ptr_23.c b/lib/dns/rdata/in_1/nsap-ptr_23.c
new file mode 100644
index 0000000..9620fed
--- /dev/null
+++ b/lib/dns/rdata/in_1/nsap-ptr_23.c
@@ -0,0 +1,244 @@
+/*
+ * 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.
+ */
+
+/* RFC1348. Obsoleted in RFC 1706 - use PTR instead. */
+
+#ifndef RDATA_IN_1_NSAP_PTR_23_C
+#define RDATA_IN_1_NSAP_PTR_23_C
+
+#define RRTYPE_NSAP_PTR_ATTRIBUTES (0)
+
+static isc_result_t
+fromtext_in_nsap_ptr(ARGS_FROMTEXT) {
+ isc_token_t token;
+ dns_name_t name;
+ isc_buffer_t buffer;
+
+ REQUIRE(type == dns_rdatatype_nsap_ptr);
+ REQUIRE(rdclass == dns_rdataclass_in);
+
+ 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_in_nsap_ptr(ARGS_TOTEXT) {
+ isc_region_t region;
+ dns_name_t name;
+ dns_name_t prefix;
+ bool sub;
+
+ REQUIRE(rdata->type == dns_rdatatype_nsap_ptr);
+ REQUIRE(rdata->rdclass == dns_rdataclass_in);
+ 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_in_nsap_ptr(ARGS_FROMWIRE) {
+ dns_name_t name;
+
+ REQUIRE(type == dns_rdatatype_nsap_ptr);
+ REQUIRE(rdclass == dns_rdataclass_in);
+
+ 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_in_nsap_ptr(ARGS_TOWIRE) {
+ dns_name_t name;
+ dns_offsets_t offsets;
+ isc_region_t region;
+
+ REQUIRE(rdata->type == dns_rdatatype_nsap_ptr);
+ REQUIRE(rdata->rdclass == dns_rdataclass_in);
+ 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_in_nsap_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_nsap_ptr);
+ REQUIRE(rdata1->rdclass == dns_rdataclass_in);
+ 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_in_nsap_ptr(ARGS_FROMSTRUCT) {
+ dns_rdata_in_nsap_ptr_t *nsap_ptr = source;
+ isc_region_t region;
+
+ REQUIRE(type == dns_rdatatype_nsap_ptr);
+ REQUIRE(rdclass == dns_rdataclass_in);
+ REQUIRE(nsap_ptr != NULL);
+ REQUIRE(nsap_ptr->common.rdtype == type);
+ REQUIRE(nsap_ptr->common.rdclass == rdclass);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ dns_name_toregion(&nsap_ptr->owner, &region);
+ return (isc_buffer_copyregion(target, &region));
+}
+
+static isc_result_t
+tostruct_in_nsap_ptr(ARGS_TOSTRUCT) {
+ isc_region_t region;
+ dns_rdata_in_nsap_ptr_t *nsap_ptr = target;
+ dns_name_t name;
+
+ REQUIRE(rdata->type == dns_rdatatype_nsap_ptr);
+ REQUIRE(rdata->rdclass == dns_rdataclass_in);
+ REQUIRE(nsap_ptr != NULL);
+ REQUIRE(rdata->length != 0);
+
+ nsap_ptr->common.rdclass = rdata->rdclass;
+ nsap_ptr->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&nsap_ptr->common, link);
+
+ dns_name_init(&name, NULL);
+ dns_rdata_toregion(rdata, &region);
+ dns_name_fromregion(&name, &region);
+ dns_name_init(&nsap_ptr->owner, NULL);
+ name_duporclone(&name, mctx, &nsap_ptr->owner);
+ nsap_ptr->mctx = mctx;
+ return (ISC_R_SUCCESS);
+}
+
+static void
+freestruct_in_nsap_ptr(ARGS_FREESTRUCT) {
+ dns_rdata_in_nsap_ptr_t *nsap_ptr = source;
+
+ REQUIRE(nsap_ptr != NULL);
+ REQUIRE(nsap_ptr->common.rdclass == dns_rdataclass_in);
+ REQUIRE(nsap_ptr->common.rdtype == dns_rdatatype_nsap_ptr);
+
+ if (nsap_ptr->mctx == NULL) {
+ return;
+ }
+
+ dns_name_free(&nsap_ptr->owner, nsap_ptr->mctx);
+ nsap_ptr->mctx = NULL;
+}
+
+static isc_result_t
+additionaldata_in_nsap_ptr(ARGS_ADDLDATA) {
+ REQUIRE(rdata->type == dns_rdatatype_nsap_ptr);
+ REQUIRE(rdata->rdclass == dns_rdataclass_in);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(add);
+ UNUSED(arg);
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+digest_in_nsap_ptr(ARGS_DIGEST) {
+ isc_region_t r;
+ dns_name_t name;
+
+ REQUIRE(rdata->type == dns_rdatatype_nsap_ptr);
+ REQUIRE(rdata->rdclass == dns_rdataclass_in);
+
+ 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_in_nsap_ptr(ARGS_CHECKOWNER) {
+ REQUIRE(type == dns_rdatatype_nsap_ptr);
+ REQUIRE(rdclass == dns_rdataclass_in);
+
+ UNUSED(name);
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (true);
+}
+
+static bool
+checknames_in_nsap_ptr(ARGS_CHECKNAMES) {
+ REQUIRE(rdata->type == dns_rdatatype_nsap_ptr);
+ REQUIRE(rdata->rdclass == dns_rdataclass_in);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(bad);
+
+ return (true);
+}
+
+static int
+casecompare_in_nsap_ptr(ARGS_COMPARE) {
+ return (compare_in_nsap_ptr(rdata1, rdata2));
+}
+
+#endif /* RDATA_IN_1_NSAP_PTR_23_C */
diff --git a/lib/dns/rdata/in_1/nsap-ptr_23.h b/lib/dns/rdata/in_1/nsap-ptr_23.h
new file mode 100644
index 0000000..45e5b16
--- /dev/null
+++ b/lib/dns/rdata/in_1/nsap-ptr_23.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 RFC1348. Obsoleted in RFC 1706 - use PTR instead. */
+
+typedef struct dns_rdata_in_nsap_ptr {
+ dns_rdatacommon_t common;
+ isc_mem_t *mctx;
+ dns_name_t owner;
+} dns_rdata_in_nsap_ptr_t;
diff --git a/lib/dns/rdata/in_1/nsap_22.c b/lib/dns/rdata/in_1/nsap_22.c
new file mode 100644
index 0000000..fc92014
--- /dev/null
+++ b/lib/dns/rdata/in_1/nsap_22.c
@@ -0,0 +1,260 @@
+/*
+ * 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.
+ */
+
+/* RFC1706 */
+
+#ifndef RDATA_IN_1_NSAP_22_C
+#define RDATA_IN_1_NSAP_22_C
+
+#define RRTYPE_NSAP_ATTRIBUTES (0)
+
+static isc_result_t
+fromtext_in_nsap(ARGS_FROMTEXT) {
+ isc_token_t token;
+ isc_textregion_t *sr;
+ int n;
+ bool valid = false;
+ int digits = 0;
+ unsigned char c = 0;
+
+ REQUIRE(type == dns_rdatatype_nsap);
+ REQUIRE(rdclass == dns_rdataclass_in);
+
+ UNUSED(type);
+ UNUSED(origin);
+ UNUSED(options);
+ UNUSED(rdclass);
+ UNUSED(callbacks);
+
+ /* 0x<hex.string.with.periods> */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ false));
+ sr = &token.value.as_textregion;
+ if (sr->length < 2) {
+ RETTOK(ISC_R_UNEXPECTEDEND);
+ }
+ if (sr->base[0] != '0' || (sr->base[1] != 'x' && sr->base[1] != 'X')) {
+ RETTOK(DNS_R_SYNTAX);
+ }
+ isc_textregion_consume(sr, 2);
+ while (sr->length > 0) {
+ if (sr->base[0] == '.') {
+ isc_textregion_consume(sr, 1);
+ continue;
+ }
+ if ((n = hexvalue(sr->base[0])) == -1) {
+ RETTOK(DNS_R_SYNTAX);
+ }
+ c <<= 4;
+ c += n;
+ if (++digits == 2) {
+ RETERR(mem_tobuffer(target, &c, 1));
+ valid = true;
+ digits = 0;
+ c = 0;
+ }
+ isc_textregion_consume(sr, 1);
+ }
+ if (digits != 0 || !valid) {
+ RETTOK(ISC_R_UNEXPECTEDEND);
+ }
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+totext_in_nsap(ARGS_TOTEXT) {
+ isc_region_t region;
+ char buf[sizeof("xx")];
+
+ REQUIRE(rdata->type == dns_rdatatype_nsap);
+ REQUIRE(rdata->rdclass == dns_rdataclass_in);
+ REQUIRE(rdata->length != 0);
+
+ UNUSED(tctx);
+
+ dns_rdata_toregion(rdata, &region);
+ RETERR(str_totext("0x", target));
+ while (region.length != 0) {
+ snprintf(buf, sizeof(buf), "%02x", region.base[0]);
+ isc_region_consume(&region, 1);
+ RETERR(str_totext(buf, target));
+ }
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+fromwire_in_nsap(ARGS_FROMWIRE) {
+ isc_region_t region;
+
+ REQUIRE(type == dns_rdatatype_nsap);
+ REQUIRE(rdclass == dns_rdataclass_in);
+
+ UNUSED(type);
+ UNUSED(dctx);
+ UNUSED(options);
+ UNUSED(rdclass);
+
+ isc_buffer_activeregion(source, &region);
+ if (region.length < 1) {
+ return (ISC_R_UNEXPECTEDEND);
+ }
+
+ RETERR(mem_tobuffer(target, region.base, region.length));
+ isc_buffer_forward(source, region.length);
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+towire_in_nsap(ARGS_TOWIRE) {
+ REQUIRE(rdata->type == dns_rdatatype_nsap);
+ REQUIRE(rdata->rdclass == dns_rdataclass_in);
+ REQUIRE(rdata->length != 0);
+
+ UNUSED(cctx);
+
+ return (mem_tobuffer(target, rdata->data, rdata->length));
+}
+
+static int
+compare_in_nsap(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_nsap);
+ REQUIRE(rdata1->rdclass == dns_rdataclass_in);
+ 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_in_nsap(ARGS_FROMSTRUCT) {
+ dns_rdata_in_nsap_t *nsap = source;
+
+ REQUIRE(type == dns_rdatatype_nsap);
+ REQUIRE(rdclass == dns_rdataclass_in);
+ REQUIRE(nsap != NULL);
+ REQUIRE(nsap->common.rdtype == type);
+ REQUIRE(nsap->common.rdclass == rdclass);
+ REQUIRE(nsap->nsap != NULL || nsap->nsap_len == 0);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ return (mem_tobuffer(target, nsap->nsap, nsap->nsap_len));
+}
+
+static isc_result_t
+tostruct_in_nsap(ARGS_TOSTRUCT) {
+ dns_rdata_in_nsap_t *nsap = target;
+ isc_region_t r;
+
+ REQUIRE(rdata->type == dns_rdatatype_nsap);
+ REQUIRE(rdata->rdclass == dns_rdataclass_in);
+ REQUIRE(nsap != NULL);
+ REQUIRE(rdata->length != 0);
+
+ nsap->common.rdclass = rdata->rdclass;
+ nsap->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&nsap->common, link);
+
+ dns_rdata_toregion(rdata, &r);
+ nsap->nsap_len = r.length;
+ nsap->nsap = mem_maybedup(mctx, r.base, r.length);
+ if (nsap->nsap == NULL) {
+ return (ISC_R_NOMEMORY);
+ }
+
+ nsap->mctx = mctx;
+ return (ISC_R_SUCCESS);
+}
+
+static void
+freestruct_in_nsap(ARGS_FREESTRUCT) {
+ dns_rdata_in_nsap_t *nsap = source;
+
+ REQUIRE(nsap != NULL);
+ REQUIRE(nsap->common.rdclass == dns_rdataclass_in);
+ REQUIRE(nsap->common.rdtype == dns_rdatatype_nsap);
+
+ if (nsap->mctx == NULL) {
+ return;
+ }
+
+ if (nsap->nsap != NULL) {
+ isc_mem_free(nsap->mctx, nsap->nsap);
+ }
+ nsap->mctx = NULL;
+}
+
+static isc_result_t
+additionaldata_in_nsap(ARGS_ADDLDATA) {
+ REQUIRE(rdata->type == dns_rdatatype_nsap);
+ REQUIRE(rdata->rdclass == dns_rdataclass_in);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(add);
+ UNUSED(arg);
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+digest_in_nsap(ARGS_DIGEST) {
+ isc_region_t r;
+
+ REQUIRE(rdata->type == dns_rdatatype_nsap);
+ REQUIRE(rdata->rdclass == dns_rdataclass_in);
+
+ dns_rdata_toregion(rdata, &r);
+
+ return ((digest)(arg, &r));
+}
+
+static bool
+checkowner_in_nsap(ARGS_CHECKOWNER) {
+ REQUIRE(type == dns_rdatatype_nsap);
+ REQUIRE(rdclass == dns_rdataclass_in);
+
+ UNUSED(name);
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (true);
+}
+
+static bool
+checknames_in_nsap(ARGS_CHECKNAMES) {
+ REQUIRE(rdata->type == dns_rdatatype_nsap);
+ REQUIRE(rdata->rdclass == dns_rdataclass_in);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(bad);
+
+ return (true);
+}
+
+static int
+casecompare_in_nsap(ARGS_COMPARE) {
+ return (compare_in_nsap(rdata1, rdata2));
+}
+
+#endif /* RDATA_IN_1_NSAP_22_C */
diff --git a/lib/dns/rdata/in_1/nsap_22.h b/lib/dns/rdata/in_1/nsap_22.h
new file mode 100644
index 0000000..fd5803c
--- /dev/null
+++ b/lib/dns/rdata/in_1/nsap_22.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 RFC1706 */
+
+typedef struct dns_rdata_in_nsap {
+ dns_rdatacommon_t common;
+ isc_mem_t *mctx;
+ unsigned char *nsap;
+ uint16_t nsap_len;
+} dns_rdata_in_nsap_t;
diff --git a/lib/dns/rdata/in_1/px_26.c b/lib/dns/rdata/in_1/px_26.c
new file mode 100644
index 0000000..441c3c4
--- /dev/null
+++ b/lib/dns/rdata/in_1/px_26.c
@@ -0,0 +1,372 @@
+/*
+ * 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.
+ */
+
+/* RFC2163 */
+
+#ifndef RDATA_IN_1_PX_26_C
+#define RDATA_IN_1_PX_26_C
+
+#define RRTYPE_PX_ATTRIBUTES (0)
+
+static isc_result_t
+fromtext_in_px(ARGS_FROMTEXT) {
+ isc_token_t token;
+ dns_name_t name;
+ isc_buffer_t buffer;
+
+ REQUIRE(type == dns_rdatatype_px);
+ REQUIRE(rdclass == dns_rdataclass_in);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(callbacks);
+
+ if (origin == NULL) {
+ origin = dns_rootname;
+ }
+
+ /*
+ * 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));
+
+ /*
+ * MAP822.
+ */
+ 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));
+
+ /*
+ * MAPX400.
+ */
+ 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_in_px(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_px);
+ REQUIRE(rdata->rdclass == dns_rdataclass_in);
+ REQUIRE(rdata->length != 0);
+
+ dns_name_init(&name, NULL);
+ dns_name_init(&prefix, NULL);
+
+ /*
+ * Preference.
+ */
+ 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));
+
+ /*
+ * MAP822.
+ */
+ dns_name_fromregion(&name, &region);
+ sub = name_prefix(&name, tctx->origin, &prefix);
+ isc_region_consume(&region, name_length(&name));
+ RETERR(dns_name_totext(&prefix, sub, target));
+ RETERR(str_totext(" ", target));
+
+ /*
+ * MAPX400.
+ */
+ dns_name_fromregion(&name, &region);
+ sub = name_prefix(&name, tctx->origin, &prefix);
+ return (dns_name_totext(&prefix, sub, target));
+}
+
+static isc_result_t
+fromwire_in_px(ARGS_FROMWIRE) {
+ dns_name_t name;
+ isc_region_t sregion;
+
+ REQUIRE(type == dns_rdatatype_px);
+ REQUIRE(rdclass == dns_rdataclass_in);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ dns_decompress_setmethods(dctx, DNS_COMPRESS_NONE);
+
+ dns_name_init(&name, NULL);
+
+ /*
+ * Preference.
+ */
+ 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);
+
+ /*
+ * MAP822.
+ */
+ RETERR(dns_name_fromwire(&name, source, dctx, options, target));
+
+ /*
+ * MAPX400.
+ */
+ return (dns_name_fromwire(&name, source, dctx, options, target));
+}
+
+static isc_result_t
+towire_in_px(ARGS_TOWIRE) {
+ dns_name_t name;
+ dns_offsets_t offsets;
+ isc_region_t region;
+
+ REQUIRE(rdata->type == dns_rdatatype_px);
+ REQUIRE(rdata->rdclass == dns_rdataclass_in);
+ REQUIRE(rdata->length != 0);
+
+ dns_compress_setmethods(cctx, DNS_COMPRESS_NONE);
+ /*
+ * Preference.
+ */
+ dns_rdata_toregion(rdata, &region);
+ RETERR(mem_tobuffer(target, region.base, 2));
+ isc_region_consume(&region, 2);
+
+ /*
+ * MAP822.
+ */
+ dns_name_init(&name, offsets);
+ dns_name_fromregion(&name, &region);
+ RETERR(dns_name_towire(&name, cctx, target));
+ isc_region_consume(&region, name_length(&name));
+
+ /*
+ * MAPX400.
+ */
+ dns_name_init(&name, offsets);
+ dns_name_fromregion(&name, &region);
+ return (dns_name_towire(&name, cctx, target));
+}
+
+static int
+compare_in_px(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_px);
+ REQUIRE(rdata1->rdclass == dns_rdataclass_in);
+ 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);
+
+ 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_fromregion(&name1, &region1);
+ dns_name_fromregion(&name2, &region2);
+
+ return (dns_name_rdatacompare(&name1, &name2));
+}
+
+static isc_result_t
+fromstruct_in_px(ARGS_FROMSTRUCT) {
+ dns_rdata_in_px_t *px = source;
+ isc_region_t region;
+
+ REQUIRE(type == dns_rdatatype_px);
+ REQUIRE(rdclass == dns_rdataclass_in);
+ REQUIRE(px != NULL);
+ REQUIRE(px->common.rdtype == type);
+ REQUIRE(px->common.rdclass == rdclass);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ RETERR(uint16_tobuffer(px->preference, target));
+ dns_name_toregion(&px->map822, &region);
+ RETERR(isc_buffer_copyregion(target, &region));
+ dns_name_toregion(&px->mapx400, &region);
+ return (isc_buffer_copyregion(target, &region));
+}
+
+static isc_result_t
+tostruct_in_px(ARGS_TOSTRUCT) {
+ dns_rdata_in_px_t *px = target;
+ dns_name_t name;
+ isc_region_t region;
+
+ REQUIRE(rdata->type == dns_rdatatype_px);
+ REQUIRE(rdata->rdclass == dns_rdataclass_in);
+ REQUIRE(px != NULL);
+ REQUIRE(rdata->length != 0);
+
+ px->common.rdclass = rdata->rdclass;
+ px->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&px->common, link);
+
+ dns_name_init(&name, NULL);
+ dns_rdata_toregion(rdata, &region);
+
+ px->preference = uint16_fromregion(&region);
+ isc_region_consume(&region, 2);
+
+ dns_name_fromregion(&name, &region);
+
+ dns_name_init(&px->map822, NULL);
+ name_duporclone(&name, mctx, &px->map822);
+ isc_region_consume(&region, name_length(&px->map822));
+
+ dns_name_init(&px->mapx400, NULL);
+ name_duporclone(&name, mctx, &px->mapx400);
+
+ px->mctx = mctx;
+ return (ISC_R_SUCCESS);
+}
+
+static void
+freestruct_in_px(ARGS_FREESTRUCT) {
+ dns_rdata_in_px_t *px = source;
+
+ REQUIRE(px != NULL);
+ REQUIRE(px->common.rdclass == dns_rdataclass_in);
+ REQUIRE(px->common.rdtype == dns_rdatatype_px);
+
+ if (px->mctx == NULL) {
+ return;
+ }
+
+ dns_name_free(&px->map822, px->mctx);
+ dns_name_free(&px->mapx400, px->mctx);
+ px->mctx = NULL;
+}
+
+static isc_result_t
+additionaldata_in_px(ARGS_ADDLDATA) {
+ REQUIRE(rdata->type == dns_rdatatype_px);
+ REQUIRE(rdata->rdclass == dns_rdataclass_in);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(add);
+ UNUSED(arg);
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+digest_in_px(ARGS_DIGEST) {
+ isc_region_t r1, r2;
+ dns_name_t name;
+ isc_result_t result;
+
+ REQUIRE(rdata->type == dns_rdatatype_px);
+ REQUIRE(rdata->rdclass == dns_rdataclass_in);
+
+ 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);
+ result = dns_name_digest(&name, digest, arg);
+ if (result != ISC_R_SUCCESS) {
+ return (result);
+ }
+ isc_region_consume(&r2, name_length(&name));
+ dns_name_init(&name, NULL);
+ dns_name_fromregion(&name, &r2);
+
+ return (dns_name_digest(&name, digest, arg));
+}
+
+static bool
+checkowner_in_px(ARGS_CHECKOWNER) {
+ REQUIRE(type == dns_rdatatype_px);
+ REQUIRE(rdclass == dns_rdataclass_in);
+
+ UNUSED(name);
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (true);
+}
+
+static bool
+checknames_in_px(ARGS_CHECKNAMES) {
+ REQUIRE(rdata->type == dns_rdatatype_px);
+ REQUIRE(rdata->rdclass == dns_rdataclass_in);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(bad);
+
+ return (true);
+}
+
+static int
+casecompare_in_px(ARGS_COMPARE) {
+ return (compare_in_px(rdata1, rdata2));
+}
+
+#endif /* RDATA_IN_1_PX_26_C */
diff --git a/lib/dns/rdata/in_1/px_26.h b/lib/dns/rdata/in_1/px_26.h
new file mode 100644
index 0000000..36a1c0e
--- /dev/null
+++ b/lib/dns/rdata/in_1/px_26.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 RFC2163 */
+
+typedef struct dns_rdata_in_px {
+ dns_rdatacommon_t common;
+ isc_mem_t *mctx;
+ uint16_t preference;
+ dns_name_t map822;
+ dns_name_t mapx400;
+} dns_rdata_in_px_t;
diff --git a/lib/dns/rdata/in_1/srv_33.c b/lib/dns/rdata/in_1/srv_33.c
new file mode 100644
index 0000000..6818b03
--- /dev/null
+++ b/lib/dns/rdata/in_1/srv_33.c
@@ -0,0 +1,413 @@
+/*
+ * 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.
+ */
+
+/* RFC2782 */
+
+#ifndef RDATA_IN_1_SRV_33_C
+#define RDATA_IN_1_SRV_33_C
+
+#define RRTYPE_SRV_ATTRIBUTES (DNS_RDATATYPEATTR_FOLLOWADDITIONAL)
+
+static isc_result_t
+fromtext_in_srv(ARGS_FROMTEXT) {
+ isc_token_t token;
+ dns_name_t name;
+ isc_buffer_t buffer;
+ bool ok;
+
+ REQUIRE(type == dns_rdatatype_srv);
+ REQUIRE(rdclass == dns_rdataclass_in);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ 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));
+
+ /*
+ * Port.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
+ false));
+ if (token.value.as_ulong > 0xffffU) {
+ RETTOK(ISC_R_RANGE);
+ }
+ RETERR(uint16_tobuffer(token.value.as_ulong, target));
+
+ /*
+ * Target.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ false));
+ 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_in_srv(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_srv);
+ REQUIRE(rdata->rdclass == dns_rdataclass_in);
+ REQUIRE(rdata->length != 0);
+
+ dns_name_init(&name, NULL);
+ dns_name_init(&prefix, NULL);
+
+ /*
+ * Priority.
+ */
+ 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));
+
+ /*
+ * Weight.
+ */
+ num = uint16_fromregion(&region);
+ isc_region_consume(&region, 2);
+ snprintf(buf, sizeof(buf), "%u", num);
+ RETERR(str_totext(buf, target));
+ RETERR(str_totext(" ", target));
+
+ /*
+ * Port.
+ */
+ num = uint16_fromregion(&region);
+ isc_region_consume(&region, 2);
+ snprintf(buf, sizeof(buf), "%u", num);
+ RETERR(str_totext(buf, target));
+ RETERR(str_totext(" ", target));
+
+ /*
+ * 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_in_srv(ARGS_FROMWIRE) {
+ dns_name_t name;
+ isc_region_t sr;
+
+ REQUIRE(type == dns_rdatatype_srv);
+ REQUIRE(rdclass == dns_rdataclass_in);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ dns_decompress_setmethods(dctx, DNS_COMPRESS_NONE);
+
+ dns_name_init(&name, NULL);
+
+ /*
+ * Priority, weight, port.
+ */
+ 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);
+
+ /*
+ * Target.
+ */
+ return (dns_name_fromwire(&name, source, dctx, options, target));
+}
+
+static isc_result_t
+towire_in_srv(ARGS_TOWIRE) {
+ dns_name_t name;
+ dns_offsets_t offsets;
+ isc_region_t sr;
+
+ REQUIRE(rdata->type == dns_rdatatype_srv);
+ REQUIRE(rdata->length != 0);
+
+ dns_compress_setmethods(cctx, DNS_COMPRESS_NONE);
+ /*
+ * Priority, weight, port.
+ */
+ dns_rdata_toregion(rdata, &sr);
+ RETERR(mem_tobuffer(target, sr.base, 6));
+ isc_region_consume(&sr, 6);
+
+ /*
+ * Target.
+ */
+ dns_name_init(&name, offsets);
+ dns_name_fromregion(&name, &sr);
+ return (dns_name_towire(&name, cctx, target));
+}
+
+static int
+compare_in_srv(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_srv);
+ REQUIRE(rdata1->rdclass == dns_rdataclass_in);
+ REQUIRE(rdata1->length != 0);
+ REQUIRE(rdata2->length != 0);
+
+ /*
+ * Priority, weight, port.
+ */
+ order = memcmp(rdata1->data, rdata2->data, 6);
+ if (order != 0) {
+ return (order < 0 ? -1 : 1);
+ }
+
+ /*
+ * Target.
+ */
+ dns_name_init(&name1, NULL);
+ dns_name_init(&name2, NULL);
+
+ dns_rdata_toregion(rdata1, &region1);
+ dns_rdata_toregion(rdata2, &region2);
+
+ isc_region_consume(&region1, 6);
+ isc_region_consume(&region2, 6);
+
+ dns_name_fromregion(&name1, &region1);
+ dns_name_fromregion(&name2, &region2);
+
+ return (dns_name_rdatacompare(&name1, &name2));
+}
+
+static isc_result_t
+fromstruct_in_srv(ARGS_FROMSTRUCT) {
+ dns_rdata_in_srv_t *srv = source;
+ isc_region_t region;
+
+ REQUIRE(type == dns_rdatatype_srv);
+ REQUIRE(rdclass == dns_rdataclass_in);
+ REQUIRE(srv != NULL);
+ REQUIRE(srv->common.rdtype == type);
+ REQUIRE(srv->common.rdclass == rdclass);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ RETERR(uint16_tobuffer(srv->priority, target));
+ RETERR(uint16_tobuffer(srv->weight, target));
+ RETERR(uint16_tobuffer(srv->port, target));
+ dns_name_toregion(&srv->target, &region);
+ return (isc_buffer_copyregion(target, &region));
+}
+
+static isc_result_t
+tostruct_in_srv(ARGS_TOSTRUCT) {
+ isc_region_t region;
+ dns_rdata_in_srv_t *srv = target;
+ dns_name_t name;
+
+ REQUIRE(rdata->rdclass == dns_rdataclass_in);
+ REQUIRE(rdata->type == dns_rdatatype_srv);
+ REQUIRE(srv != NULL);
+ REQUIRE(rdata->length != 0);
+
+ srv->common.rdclass = rdata->rdclass;
+ srv->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&srv->common, link);
+
+ dns_name_init(&name, NULL);
+ dns_rdata_toregion(rdata, &region);
+ srv->priority = uint16_fromregion(&region);
+ isc_region_consume(&region, 2);
+ srv->weight = uint16_fromregion(&region);
+ isc_region_consume(&region, 2);
+ srv->port = uint16_fromregion(&region);
+ isc_region_consume(&region, 2);
+ dns_name_fromregion(&name, &region);
+ dns_name_init(&srv->target, NULL);
+ name_duporclone(&name, mctx, &srv->target);
+ srv->mctx = mctx;
+ return (ISC_R_SUCCESS);
+}
+
+static void
+freestruct_in_srv(ARGS_FREESTRUCT) {
+ dns_rdata_in_srv_t *srv = source;
+
+ REQUIRE(srv != NULL);
+ REQUIRE(srv->common.rdclass == dns_rdataclass_in);
+ REQUIRE(srv->common.rdtype == dns_rdatatype_srv);
+
+ if (srv->mctx == NULL) {
+ return;
+ }
+
+ dns_name_free(&srv->target, srv->mctx);
+ srv->mctx = NULL;
+}
+
+static isc_result_t
+additionaldata_in_srv(ARGS_ADDLDATA) {
+ char buf[sizeof("_65000._tcp")];
+ dns_fixedname_t fixed;
+ dns_name_t name;
+ dns_offsets_t offsets;
+ isc_region_t region;
+ uint16_t port;
+ isc_result_t result;
+
+ REQUIRE(rdata->type == dns_rdatatype_srv);
+ REQUIRE(rdata->rdclass == dns_rdataclass_in);
+
+ UNUSED(owner);
+
+ dns_name_init(&name, offsets);
+ dns_rdata_toregion(rdata, &region);
+ isc_region_consume(&region, 4);
+ port = uint16_fromregion(&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);
+ snprintf(buf, sizeof(buf), "_%u._tcp", port);
+ result = dns_name_fromstring2(dns_fixedname_name(&fixed), buf, NULL, 0,
+ NULL);
+ if (result != ISC_R_SUCCESS) {
+ return (ISC_R_SUCCESS);
+ }
+
+ result = dns_name_concatenate(dns_fixedname_name(&fixed), &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_in_srv(ARGS_DIGEST) {
+ isc_region_t r1, r2;
+ dns_name_t name;
+
+ REQUIRE(rdata->type == dns_rdatatype_srv);
+ REQUIRE(rdata->rdclass == dns_rdataclass_in);
+
+ dns_rdata_toregion(rdata, &r1);
+ r2 = r1;
+ isc_region_consume(&r2, 6);
+ r1.length = 6;
+ RETERR((digest)(arg, &r1));
+ dns_name_init(&name, NULL);
+ dns_name_fromregion(&name, &r2);
+ return (dns_name_digest(&name, digest, arg));
+}
+
+static bool
+checkowner_in_srv(ARGS_CHECKOWNER) {
+ REQUIRE(type == dns_rdatatype_srv);
+ REQUIRE(rdclass == dns_rdataclass_in);
+
+ UNUSED(name);
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (true);
+}
+
+static bool
+checknames_in_srv(ARGS_CHECKNAMES) {
+ isc_region_t region;
+ dns_name_t name;
+
+ REQUIRE(rdata->type == dns_rdatatype_srv);
+ REQUIRE(rdata->rdclass == dns_rdataclass_in);
+
+ UNUSED(owner);
+
+ dns_rdata_toregion(rdata, &region);
+ isc_region_consume(&region, 6);
+ 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_in_srv(ARGS_COMPARE) {
+ return (compare_in_srv(rdata1, rdata2));
+}
+
+#endif /* RDATA_IN_1_SRV_33_C */
diff --git a/lib/dns/rdata/in_1/srv_33.h b/lib/dns/rdata/in_1/srv_33.h
new file mode 100644
index 0000000..fbfa92c
--- /dev/null
+++ b/lib/dns/rdata/in_1/srv_33.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 RFC2782 */
+
+typedef struct dns_rdata_in_srv {
+ dns_rdatacommon_t common;
+ isc_mem_t *mctx;
+ uint16_t priority;
+ uint16_t weight;
+ uint16_t port;
+ dns_name_t target;
+} dns_rdata_in_srv_t;
diff --git a/lib/dns/rdata/in_1/svcb_64.c b/lib/dns/rdata/in_1/svcb_64.c
new file mode 100644
index 0000000..0d9da89
--- /dev/null
+++ b/lib/dns/rdata/in_1/svcb_64.c
@@ -0,0 +1,1338 @@
+/*
+ * 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-svcb-https-02 */
+
+#ifndef RDATA_IN_1_SVCB_64_C
+#define RDATA_IN_1_SVCB_64_C
+
+#define RRTYPE_SVCB_ATTRIBUTES (DNS_RDATATYPEATTR_FOLLOWADDITIONAL)
+
+#define SVCB_MAN_KEY 0
+#define SVCB_ALPN_KEY 1
+#define SVCB_NO_DEFAULT_ALPN_KEY 2
+#define MAX_CNAMES 16 /* See ns/query.c MAX_RESTARTS */
+
+/*
+ * Service Binding Parameter Registry
+ */
+enum encoding {
+ sbpr_text,
+ sbpr_port,
+ sbpr_ipv4s,
+ sbpr_ipv6s,
+ sbpr_base64,
+ sbpr_empty,
+ sbpr_alpn,
+ sbpr_keylist,
+ sbpr_dohpath
+};
+static const struct {
+ const char *name; /* Restricted to lowercase LDH by registry. */
+ unsigned int value;
+ enum encoding encoding;
+ bool initial; /* Part of the first defined set of encodings. */
+} sbpr[] = {
+ { "mandatory", 0, sbpr_keylist, true },
+ { "alpn", 1, sbpr_alpn, true },
+ { "no-default-alpn", 2, sbpr_empty, true },
+ { "port", 3, sbpr_port, true },
+ { "ipv4hint", 4, sbpr_ipv4s, true },
+ { "ech", 5, sbpr_base64, true },
+ { "ipv6hint", 6, sbpr_ipv6s, true },
+ { "dohpath", 7, sbpr_dohpath, false },
+};
+
+static isc_result_t
+alpn_fromtxt(isc_textregion_t *source, isc_buffer_t *target) {
+ isc_textregion_t source0 = *source;
+ do {
+ RETERR(commatxt_fromtext(&source0, true, target));
+ } while (source0.length != 0);
+ return (ISC_R_SUCCESS);
+}
+
+static int
+svckeycmp(const void *a1, const void *a2) {
+ const unsigned char *u1 = a1, *u2 = a2;
+ if (*u1 != *u2) {
+ return (*u1 - *u2);
+ }
+ return (*(++u1) - *(++u2));
+}
+
+static isc_result_t
+svcsortkeylist(isc_buffer_t *target, unsigned int used) {
+ isc_region_t region;
+
+ isc_buffer_usedregion(target, &region);
+ isc_region_consume(&region, used);
+ INSIST(region.length > 0U);
+ qsort(region.base, region.length / 2, 2, svckeycmp);
+ /* Reject duplicates. */
+ while (region.length >= 4) {
+ if (region.base[0] == region.base[2] &&
+ region.base[1] == region.base[3])
+ {
+ return (DNS_R_SYNTAX);
+ }
+ isc_region_consume(&region, 2);
+ }
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+svcb_validate(uint16_t key, isc_region_t *region) {
+ size_t i;
+
+ for (i = 0; i < ARRAY_SIZE(sbpr); i++) {
+ if (sbpr[i].value == key) {
+ switch (sbpr[i].encoding) {
+ case sbpr_port:
+ if (region->length != 2) {
+ return (DNS_R_FORMERR);
+ }
+ break;
+ case sbpr_ipv4s:
+ if ((region->length % 4) != 0 ||
+ region->length == 0)
+ {
+ return (DNS_R_FORMERR);
+ }
+ break;
+ case sbpr_ipv6s:
+ if ((region->length % 16) != 0 ||
+ region->length == 0)
+ {
+ return (DNS_R_FORMERR);
+ }
+ break;
+ case sbpr_alpn: {
+ if (region->length == 0) {
+ return (DNS_R_FORMERR);
+ }
+ while (region->length != 0) {
+ size_t l = *region->base + 1;
+ if (l == 1U || l > region->length) {
+ return (DNS_R_FORMERR);
+ }
+ isc_region_consume(region, l);
+ }
+ break;
+ }
+ case sbpr_keylist: {
+ if ((region->length % 2) != 0 ||
+ region->length == 0)
+ {
+ return (DNS_R_FORMERR);
+ }
+ /* In order? */
+ while (region->length >= 4) {
+ if (region->base[0] > region->base[2] ||
+ (region->base[0] ==
+ region->base[2] &&
+ region->base[1] >=
+ region->base[3]))
+ {
+ return (DNS_R_FORMERR);
+ }
+ isc_region_consume(region, 2);
+ }
+ break;
+ }
+ case sbpr_text:
+ case sbpr_base64:
+ break;
+ case sbpr_dohpath:
+ /*
+ * Minimum valid dohpath is "/{?dns}" as
+ * it MUST be relative (leading "/") and
+ * MUST contain "{?dns}".
+ */
+ if (region->length < 7) {
+ return (DNS_R_FORMERR);
+ }
+ /* MUST be relative */
+ if (region->base[0] != '/') {
+ return (DNS_R_FORMERR);
+ }
+ /* MUST be UTF8 */
+ if (!isc_utf8_valid(region->base,
+ region->length))
+ {
+ return (DNS_R_FORMERR);
+ }
+ /* MUST contain "{?dns}" */
+ if (strnstr((char *)region->base, "{?dns}",
+ region->length) == NULL)
+ {
+ return (DNS_R_FORMERR);
+ }
+ break;
+ case sbpr_empty:
+ if (region->length != 0) {
+ return (DNS_R_FORMERR);
+ }
+ break;
+ }
+ }
+ }
+ return (ISC_R_SUCCESS);
+}
+
+/*
+ * Parse keyname from region.
+ */
+static isc_result_t
+svc_keyfromregion(isc_textregion_t *region, char sep, uint16_t *value,
+ isc_buffer_t *target) {
+ char *e = NULL;
+ size_t i;
+ unsigned long ul;
+
+ /* Look for known key names. */
+ for (i = 0; i < ARRAY_SIZE(sbpr); i++) {
+ size_t len = strlen(sbpr[i].name);
+ if (strncasecmp(region->base, sbpr[i].name, len) != 0 ||
+ (region->base[len] != 0 && region->base[len] != sep))
+ {
+ continue;
+ }
+ isc_textregion_consume(region, len);
+ ul = sbpr[i].value;
+ goto finish;
+ }
+ /* Handle keyXXXXX form. */
+ if (strncmp(region->base, "key", 3) != 0) {
+ return (DNS_R_SYNTAX);
+ }
+ isc_textregion_consume(region, 3);
+ /* Disallow [+-]XXXXX which is allowed by strtoul. */
+ if (region->length == 0 || *region->base == '-' || *region->base == '+')
+ {
+ return (DNS_R_SYNTAX);
+ }
+ /* No zero padding. */
+ if (region->length > 1 && *region->base == '0' &&
+ region->base[1] != sep)
+ {
+ return (DNS_R_SYNTAX);
+ }
+ ul = strtoul(region->base, &e, 10);
+ /* Valid number? */
+ if (e == region->base || (*e != sep && *e != 0)) {
+ return (DNS_R_SYNTAX);
+ }
+ if (ul > 0xffff) {
+ return (ISC_R_RANGE);
+ }
+ isc_textregion_consume(region, e - region->base);
+finish:
+ if (sep == ',' && region->length == 1) {
+ return (DNS_R_SYNTAX);
+ }
+ /* Consume separator. */
+ if (region->length != 0) {
+ isc_textregion_consume(region, 1);
+ }
+ RETERR(uint16_tobuffer(ul, target));
+ if (value != NULL) {
+ *value = ul;
+ }
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+svc_fromtext(isc_textregion_t *region, isc_buffer_t *target) {
+ char *e = NULL;
+ char abuf[16];
+ char tbuf[sizeof("aaaa:aaaa:aaaa:aaaa:aaaa:aaaa:255.255.255.255,")];
+ isc_buffer_t sb;
+ isc_region_t keyregion;
+ size_t len;
+ uint16_t key;
+ unsigned int i;
+ unsigned int used;
+ unsigned long ul;
+
+ for (i = 0; i < ARRAY_SIZE(sbpr); i++) {
+ len = strlen(sbpr[i].name);
+ if (strncmp(region->base, sbpr[i].name, len) != 0 ||
+ (region->base[len] != 0 && region->base[len] != '='))
+ {
+ continue;
+ }
+
+ if (region->base[len] == '=') {
+ len++;
+ }
+
+ RETERR(uint16_tobuffer(sbpr[i].value, target));
+ isc_textregion_consume(region, len);
+
+ sb = *target;
+ RETERR(uint16_tobuffer(0, target)); /* length */
+
+ switch (sbpr[i].encoding) {
+ case sbpr_text:
+ case sbpr_dohpath:
+ RETERR(multitxt_fromtext(region, target));
+ break;
+ case sbpr_alpn:
+ RETERR(alpn_fromtxt(region, target));
+ break;
+ case sbpr_port:
+ if (!isdigit((unsigned char)*region->base)) {
+ return (DNS_R_SYNTAX);
+ }
+ ul = strtoul(region->base, &e, 10);
+ if (*e != '\0') {
+ return (DNS_R_SYNTAX);
+ }
+ if (ul > 0xffff) {
+ return (ISC_R_RANGE);
+ }
+ RETERR(uint16_tobuffer(ul, target));
+ break;
+ case sbpr_ipv4s:
+ do {
+ snprintf(tbuf, sizeof(tbuf), "%*s",
+ (int)(region->length), region->base);
+ e = strchr(tbuf, ',');
+ if (e != NULL) {
+ *e++ = 0;
+ isc_textregion_consume(region,
+ e - tbuf);
+ }
+ if (inet_pton(AF_INET, tbuf, abuf) != 1) {
+ return (DNS_R_SYNTAX);
+ }
+ mem_tobuffer(target, abuf, 4);
+ } while (e != NULL);
+ break;
+ case sbpr_ipv6s:
+ do {
+ snprintf(tbuf, sizeof(tbuf), "%*s",
+ (int)(region->length), region->base);
+ e = strchr(tbuf, ',');
+ if (e != NULL) {
+ *e++ = 0;
+ isc_textregion_consume(region,
+ e - tbuf);
+ }
+ if (inet_pton(AF_INET6, tbuf, abuf) != 1) {
+ return (DNS_R_SYNTAX);
+ }
+ mem_tobuffer(target, abuf, 16);
+ } while (e != NULL);
+ break;
+ case sbpr_base64:
+ RETERR(isc_base64_decodestring(region->base, target));
+ break;
+ case sbpr_empty:
+ if (region->length != 0) {
+ return (DNS_R_SYNTAX);
+ }
+ break;
+ case sbpr_keylist:
+ if (region->length == 0) {
+ return (DNS_R_SYNTAX);
+ }
+ used = isc_buffer_usedlength(target);
+ while (region->length != 0) {
+ RETERR(svc_keyfromregion(region, ',', NULL,
+ target));
+ }
+ RETERR(svcsortkeylist(target, used));
+ break;
+ default:
+ UNREACHABLE();
+ }
+
+ len = isc_buffer_usedlength(target) -
+ isc_buffer_usedlength(&sb) - 2;
+ RETERR(uint16_tobuffer(len, &sb)); /* length */
+ switch (sbpr[i].encoding) {
+ case sbpr_dohpath:
+ /*
+ * Apply constraints not applied by multitxt_fromtext.
+ */
+ keyregion.base = isc_buffer_used(&sb);
+ keyregion.length = isc_buffer_usedlength(target) -
+ isc_buffer_usedlength(&sb);
+ RETERR(svcb_validate(sbpr[i].value, &keyregion));
+ break;
+ default:
+ break;
+ }
+ return (ISC_R_SUCCESS);
+ }
+
+ RETERR(svc_keyfromregion(region, '=', &key, target));
+ if (region->length == 0) {
+ RETERR(uint16_tobuffer(0, target)); /* length */
+ /* Sanity check keyXXXXX form. */
+ keyregion.base = isc_buffer_used(target);
+ keyregion.length = 0;
+ return (svcb_validate(key, &keyregion));
+ }
+ sb = *target;
+ RETERR(uint16_tobuffer(0, target)); /* dummy length */
+ RETERR(multitxt_fromtext(region, target));
+ len = isc_buffer_usedlength(target) - isc_buffer_usedlength(&sb) - 2;
+ RETERR(uint16_tobuffer(len, &sb)); /* length */
+ /* Sanity check keyXXXXX form. */
+ keyregion.base = isc_buffer_used(&sb);
+ keyregion.length = len;
+ return (svcb_validate(key, &keyregion));
+}
+
+static const char *
+svcparamkey(unsigned short value, enum encoding *encoding, char *buf,
+ size_t len) {
+ size_t i;
+ int n;
+
+ for (i = 0; i < ARRAY_SIZE(sbpr); i++) {
+ if (sbpr[i].value == value && sbpr[i].initial) {
+ *encoding = sbpr[i].encoding;
+ return (sbpr[i].name);
+ }
+ }
+ n = snprintf(buf, len, "key%u", value);
+ INSIST(n > 0 && (unsigned)n < len);
+ *encoding = sbpr_text;
+ return (buf);
+}
+
+static isc_result_t
+svcsortkeys(isc_buffer_t *target, unsigned int used) {
+ isc_region_t r1, r2, man = { .base = NULL, .length = 0 };
+ unsigned char buf[1024];
+ uint16_t mankey = 0;
+ bool have_alpn = false;
+
+ if (isc_buffer_usedlength(target) == used) {
+ return (ISC_R_SUCCESS);
+ }
+
+ /*
+ * Get the parameters into r1.
+ */
+ isc_buffer_usedregion(target, &r1);
+ isc_region_consume(&r1, used);
+
+ while (1) {
+ uint16_t key1, len1, key2, len2;
+ unsigned char *base1, *base2;
+
+ r2 = r1;
+
+ /*
+ * Get the first parameter.
+ */
+ base1 = r1.base;
+ key1 = uint16_fromregion(&r1);
+ isc_region_consume(&r1, 2);
+ len1 = uint16_fromregion(&r1);
+ isc_region_consume(&r1, 2);
+ isc_region_consume(&r1, len1);
+
+ /*
+ * Was there only one key left?
+ */
+ if (r1.length == 0) {
+ if (mankey != 0) {
+ /* Is this the last mandatory key? */
+ if (key1 != mankey || man.length != 0) {
+ return (DNS_R_INCONSISTENTRR);
+ }
+ } else if (key1 == SVCB_MAN_KEY) {
+ /* Lone mandatory field. */
+ return (DNS_R_DISALLOWED);
+ } else if (key1 == SVCB_NO_DEFAULT_ALPN_KEY &&
+ !have_alpn)
+ {
+ /* Missing required ALPN field. */
+ return (DNS_R_DISALLOWED);
+ }
+ return (ISC_R_SUCCESS);
+ }
+
+ /*
+ * Find the smallest parameter.
+ */
+ while (r1.length != 0) {
+ base2 = r1.base;
+ key2 = uint16_fromregion(&r1);
+ isc_region_consume(&r1, 2);
+ len2 = uint16_fromregion(&r1);
+ isc_region_consume(&r1, 2);
+ isc_region_consume(&r1, len2);
+ if (key2 == key1) {
+ return (DNS_R_DUPLICATE);
+ }
+ if (key2 < key1) {
+ base1 = base2;
+ key1 = key2;
+ len1 = len2;
+ }
+ }
+
+ /*
+ * Do we need to move the smallest parameter to the start?
+ */
+ if (base1 != r2.base) {
+ size_t offset = 0;
+ size_t bytes = len1 + 4;
+ size_t length = base1 - r2.base;
+
+ /*
+ * Move the smallest parameter to the start.
+ */
+ while (bytes > 0) {
+ size_t count;
+
+ if (bytes > sizeof(buf)) {
+ count = sizeof(buf);
+ } else {
+ count = bytes;
+ }
+ memmove(buf, base1, count);
+ memmove(r2.base + offset + count,
+ r2.base + offset, length);
+ memmove(r2.base + offset, buf, count);
+ base1 += count;
+ bytes -= count;
+ offset += count;
+ }
+ }
+
+ /*
+ * Check ALPN is present when NO-DEFAULT-ALPN is set.
+ */
+ if (key1 == SVCB_ALPN_KEY) {
+ have_alpn = true;
+ } else if (key1 == SVCB_NO_DEFAULT_ALPN_KEY && !have_alpn) {
+ /* Missing required ALPN field. */
+ return (DNS_R_DISALLOWED);
+ }
+
+ /*
+ * Check key against mandatory key list.
+ */
+ if (mankey != 0) {
+ if (key1 > mankey) {
+ return (DNS_R_INCONSISTENTRR);
+ }
+ if (key1 == mankey) {
+ if (man.length >= 2) {
+ mankey = uint16_fromregion(&man);
+ isc_region_consume(&man, 2);
+ } else {
+ mankey = 0;
+ }
+ }
+ }
+
+ /*
+ * Is this the mandatory key?
+ */
+ if (key1 == SVCB_MAN_KEY) {
+ man = r2;
+ man.length = len1 + 4;
+ isc_region_consume(&man, 4);
+ if (man.length >= 2) {
+ mankey = uint16_fromregion(&man);
+ isc_region_consume(&man, 2);
+ if (mankey == SVCB_MAN_KEY) {
+ return (DNS_R_DISALLOWED);
+ }
+ } else {
+ return (DNS_R_SYNTAX);
+ }
+ }
+
+ /*
+ * Consume the smallest parameter.
+ */
+ isc_region_consume(&r2, len1 + 4);
+ r1 = r2;
+ }
+}
+
+static isc_result_t
+generic_fromtext_in_svcb(ARGS_FROMTEXT) {
+ isc_token_t token;
+ dns_name_t name;
+ isc_buffer_t buffer;
+ bool alias;
+ bool ok = true;
+ unsigned int used;
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(callbacks);
+
+ /*
+ * SvcPriority.
+ */
+ 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));
+
+ alias = token.value.as_ulong == 0;
+
+ /*
+ * TargetName.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_qstring,
+ 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 (!alias && (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);
+ }
+
+ if (alias) {
+ return (ISC_R_SUCCESS);
+ }
+
+ /*
+ * SvcParams
+ */
+ used = isc_buffer_usedlength(target);
+ while (1) {
+ RETERR(isc_lex_getmastertoken(lexer, &token,
+ isc_tokentype_qvpair, true));
+ if (token.type == isc_tokentype_eol ||
+ token.type == isc_tokentype_eof)
+ {
+ isc_lex_ungettoken(lexer, &token);
+ return (svcsortkeys(target, used));
+ }
+
+ if (token.type != isc_tokentype_string && /* key only */
+ token.type != isc_tokentype_qvpair &&
+ token.type != isc_tokentype_vpair)
+ {
+ RETTOK(DNS_R_SYNTAX);
+ }
+ RETTOK(svc_fromtext(&token.value.as_textregion, target));
+ }
+}
+
+static isc_result_t
+fromtext_in_svcb(ARGS_FROMTEXT) {
+ REQUIRE(type == dns_rdatatype_svcb);
+ REQUIRE(rdclass == dns_rdataclass_in);
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(callbacks);
+
+ return (generic_fromtext_in_svcb(CALL_FROMTEXT));
+}
+
+static isc_result_t
+generic_totext_in_svcb(ARGS_TOTEXT) {
+ isc_region_t region;
+ dns_name_t name;
+ dns_name_t prefix;
+ bool sub;
+ char buf[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255")];
+ unsigned short num;
+ int n;
+
+ REQUIRE(rdata->length != 0);
+
+ dns_name_init(&name, NULL);
+ dns_name_init(&prefix, NULL);
+
+ dns_rdata_toregion(rdata, &region);
+
+ /*
+ * SvcPriority.
+ */
+ num = uint16_fromregion(&region);
+ isc_region_consume(&region, 2);
+ n = snprintf(buf, sizeof(buf), "%u ", num);
+ INSIST(n > 0 && (unsigned)n < sizeof(buf));
+ RETERR(str_totext(buf, target));
+
+ /*
+ * TargetName.
+ */
+ dns_name_fromregion(&name, &region);
+ isc_region_consume(&region, name_length(&name));
+ sub = name_prefix(&name, tctx->origin, &prefix);
+ RETERR(dns_name_totext(&prefix, sub, target));
+
+ while (region.length > 0) {
+ isc_region_t r;
+ enum encoding encoding;
+
+ RETERR(str_totext(" ", target));
+
+ INSIST(region.length >= 2);
+ num = uint16_fromregion(&region);
+ isc_region_consume(&region, 2);
+ RETERR(str_totext(svcparamkey(num, &encoding, buf, sizeof(buf)),
+ target));
+
+ INSIST(region.length >= 2);
+ num = uint16_fromregion(&region);
+ isc_region_consume(&region, 2);
+
+ INSIST(region.length >= num);
+ r = region;
+ r.length = num;
+ isc_region_consume(&region, num);
+ if (num == 0) {
+ continue;
+ }
+ if (encoding != sbpr_empty) {
+ RETERR(str_totext("=", target));
+ }
+ switch (encoding) {
+ case sbpr_text:
+ RETERR(multitxt_totext(&r, target));
+ break;
+ case sbpr_port:
+ num = uint16_fromregion(&r);
+ isc_region_consume(&r, 2);
+ n = snprintf(buf, sizeof(buf), "%u", num);
+ INSIST(n > 0 && (unsigned)n < sizeof(buf));
+ RETERR(str_totext(buf, target));
+ INSIST(r.length == 0U);
+ break;
+ case sbpr_ipv4s:
+ while (r.length > 0U) {
+ INSIST(r.length >= 4U);
+ inet_ntop(AF_INET, r.base, buf, sizeof(buf));
+ RETERR(str_totext(buf, target));
+ isc_region_consume(&r, 4);
+ if (r.length != 0U) {
+ RETERR(str_totext(",", target));
+ }
+ }
+ break;
+ case sbpr_ipv6s:
+ while (r.length > 0U) {
+ INSIST(r.length >= 16U);
+ inet_ntop(AF_INET6, r.base, buf, sizeof(buf));
+ RETERR(str_totext(buf, target));
+ isc_region_consume(&r, 16);
+ if (r.length != 0U) {
+ RETERR(str_totext(",", target));
+ }
+ }
+ break;
+ case sbpr_base64:
+ RETERR(isc_base64_totext(&r, 0, "", target));
+ break;
+ case sbpr_alpn:
+ INSIST(r.length != 0U);
+ RETERR(str_totext("\"", target));
+ while (r.length != 0) {
+ commatxt_totext(&r, false, true, target);
+ if (r.length != 0) {
+ RETERR(str_totext(",", target));
+ }
+ }
+ RETERR(str_totext("\"", target));
+ break;
+ case sbpr_empty:
+ INSIST(r.length == 0U);
+ break;
+ case sbpr_keylist:
+ while (r.length > 0) {
+ num = uint16_fromregion(&r);
+ isc_region_consume(&r, 2);
+ RETERR(str_totext(svcparamkey(num, &encoding,
+ buf, sizeof(buf)),
+ target));
+ if (r.length != 0) {
+ RETERR(str_totext(",", target));
+ }
+ }
+ break;
+ default:
+ UNREACHABLE();
+ }
+ }
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+totext_in_svcb(ARGS_TOTEXT) {
+ REQUIRE(rdata->type == dns_rdatatype_svcb);
+ REQUIRE(rdata->rdclass == dns_rdataclass_in);
+ REQUIRE(rdata->length != 0);
+
+ return (generic_totext_in_svcb(CALL_TOTEXT));
+}
+
+static isc_result_t
+generic_fromwire_in_svcb(ARGS_FROMWIRE) {
+ dns_name_t name;
+ isc_region_t region, man = { .base = NULL, .length = 0 };
+ bool alias, first = true, have_alpn = false;
+ uint16_t lastkey = 0, mankey = 0;
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ dns_decompress_setmethods(dctx, DNS_COMPRESS_NONE);
+
+ dns_name_init(&name, NULL);
+
+ /*
+ * SvcPriority.
+ */
+ isc_buffer_activeregion(source, &region);
+ if (region.length < 2) {
+ return (ISC_R_UNEXPECTEDEND);
+ }
+ RETERR(mem_tobuffer(target, region.base, 2));
+ alias = uint16_fromregion(&region) == 0;
+ isc_buffer_forward(source, 2);
+
+ /*
+ * TargetName.
+ */
+ RETERR(dns_name_fromwire(&name, source, dctx, options, target));
+
+ if (alias) {
+ return (ISC_R_SUCCESS);
+ }
+
+ /*
+ * SvcParams.
+ */
+ isc_buffer_activeregion(source, &region);
+ while (region.length > 0U) {
+ isc_region_t keyregion;
+ uint16_t key, len;
+
+ /*
+ * SvcParamKey
+ */
+ if (region.length < 2U) {
+ return (ISC_R_UNEXPECTEDEND);
+ }
+ RETERR(mem_tobuffer(target, region.base, 2));
+ key = uint16_fromregion(&region);
+ isc_region_consume(&region, 2);
+
+ /*
+ * Keys must be unique and in order.
+ */
+ if (!first && key <= lastkey) {
+ return (DNS_R_FORMERR);
+ }
+
+ /*
+ * Check mandatory keys.
+ */
+ if (mankey != 0) {
+ /* Missing mandatory key? */
+ if (key > mankey) {
+ return (DNS_R_FORMERR);
+ }
+ if (key == mankey) {
+ /* Get next mandatory key. */
+ if (man.length >= 2) {
+ mankey = uint16_fromregion(&man);
+ isc_region_consume(&man, 2);
+ } else {
+ mankey = 0;
+ }
+ }
+ }
+
+ /*
+ * Check alpn present when no-default-alpn is set.
+ */
+ if (key == SVCB_ALPN_KEY) {
+ have_alpn = true;
+ } else if (key == SVCB_NO_DEFAULT_ALPN_KEY && !have_alpn) {
+ return (DNS_R_FORMERR);
+ }
+
+ first = false;
+ lastkey = key;
+
+ /*
+ * SvcParamValue length.
+ */
+ if (region.length < 2U) {
+ return (ISC_R_UNEXPECTEDEND);
+ }
+ RETERR(mem_tobuffer(target, region.base, 2));
+ len = uint16_fromregion(&region);
+ isc_region_consume(&region, 2);
+
+ /*
+ * SvcParamValue.
+ */
+ if (region.length < len) {
+ return (ISC_R_UNEXPECTEDEND);
+ }
+
+ /*
+ * Remember manatory key.
+ */
+ if (key == SVCB_MAN_KEY) {
+ man = region;
+ man.length = len;
+ /* Get first mandatory key */
+ if (man.length >= 2) {
+ mankey = uint16_fromregion(&man);
+ isc_region_consume(&man, 2);
+ if (mankey == SVCB_MAN_KEY) {
+ return (DNS_R_FORMERR);
+ }
+ } else {
+ return (DNS_R_FORMERR);
+ }
+ }
+ keyregion = region;
+ keyregion.length = len;
+ RETERR(svcb_validate(key, &keyregion));
+ RETERR(mem_tobuffer(target, region.base, len));
+ isc_region_consume(&region, len);
+ isc_buffer_forward(source, len + 4);
+ }
+
+ /*
+ * Do we have an outstanding mandatory key?
+ */
+ if (mankey != 0) {
+ return (DNS_R_FORMERR);
+ }
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+fromwire_in_svcb(ARGS_FROMWIRE) {
+ REQUIRE(type == dns_rdatatype_svcb);
+ REQUIRE(rdclass == dns_rdataclass_in);
+
+ return (generic_fromwire_in_svcb(CALL_FROMWIRE));
+}
+
+static isc_result_t
+generic_towire_in_svcb(ARGS_TOWIRE) {
+ dns_name_t name;
+ dns_offsets_t offsets;
+ isc_region_t region;
+
+ REQUIRE(rdata->length != 0);
+
+ dns_compress_setmethods(cctx, DNS_COMPRESS_NONE);
+
+ /*
+ * SvcPriority.
+ */
+ dns_rdata_toregion(rdata, &region);
+ RETERR(mem_tobuffer(target, region.base, 2));
+ isc_region_consume(&region, 2);
+
+ /*
+ * TargetName.
+ */
+ dns_name_init(&name, offsets);
+ dns_name_fromregion(&name, &region);
+ RETERR(dns_name_towire(&name, cctx, target));
+ isc_region_consume(&region, name_length(&name));
+
+ /*
+ * SvcParams.
+ */
+ return (mem_tobuffer(target, region.base, region.length));
+}
+
+static isc_result_t
+towire_in_svcb(ARGS_TOWIRE) {
+ REQUIRE(rdata->type == dns_rdatatype_svcb);
+ REQUIRE(rdata->length != 0);
+
+ return (generic_towire_in_svcb(CALL_TOWIRE));
+}
+
+static int
+compare_in_svcb(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_svcb);
+ REQUIRE(rdata1->rdclass == dns_rdataclass_in);
+ 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
+generic_fromstruct_in_svcb(ARGS_FROMSTRUCT) {
+ dns_rdata_in_svcb_t *svcb = source;
+ isc_region_t region;
+
+ REQUIRE(svcb != NULL);
+ REQUIRE(svcb->common.rdtype == type);
+ REQUIRE(svcb->common.rdclass == rdclass);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ RETERR(uint16_tobuffer(svcb->priority, target));
+ dns_name_toregion(&svcb->svcdomain, &region);
+ RETERR(isc_buffer_copyregion(target, &region));
+
+ return (mem_tobuffer(target, svcb->svc, svcb->svclen));
+}
+
+static isc_result_t
+fromstruct_in_svcb(ARGS_FROMSTRUCT) {
+ dns_rdata_in_svcb_t *svcb = source;
+
+ REQUIRE(type == dns_rdatatype_svcb);
+ REQUIRE(rdclass == dns_rdataclass_in);
+ REQUIRE(svcb != NULL);
+ REQUIRE(svcb->common.rdtype == type);
+ REQUIRE(svcb->common.rdclass == rdclass);
+
+ return (generic_fromstruct_in_svcb(CALL_FROMSTRUCT));
+}
+
+static isc_result_t
+generic_tostruct_in_svcb(ARGS_TOSTRUCT) {
+ isc_region_t region;
+ dns_rdata_in_svcb_t *svcb = target;
+ dns_name_t name;
+
+ REQUIRE(svcb != NULL);
+ REQUIRE(rdata->length != 0);
+
+ svcb->common.rdclass = rdata->rdclass;
+ svcb->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&svcb->common, link);
+
+ dns_rdata_toregion(rdata, &region);
+
+ svcb->priority = uint16_fromregion(&region);
+ isc_region_consume(&region, 2);
+
+ dns_name_init(&svcb->svcdomain, NULL);
+ dns_name_init(&name, NULL);
+ dns_name_fromregion(&name, &region);
+ isc_region_consume(&region, name_length(&name));
+
+ name_duporclone(&name, mctx, &svcb->svcdomain);
+ svcb->svclen = region.length;
+ svcb->svc = mem_maybedup(mctx, region.base, region.length);
+
+ if (svcb->svc == NULL) {
+ if (mctx != NULL) {
+ dns_name_free(&svcb->svcdomain, svcb->mctx);
+ }
+ return (ISC_R_NOMEMORY);
+ }
+
+ svcb->offset = 0;
+ svcb->mctx = mctx;
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+tostruct_in_svcb(ARGS_TOSTRUCT) {
+ dns_rdata_in_svcb_t *svcb = target;
+
+ REQUIRE(rdata->rdclass == dns_rdataclass_in);
+ REQUIRE(rdata->type == dns_rdatatype_svcb);
+ REQUIRE(svcb != NULL);
+ REQUIRE(rdata->length != 0);
+
+ return (generic_tostruct_in_svcb(CALL_TOSTRUCT));
+}
+
+static void
+generic_freestruct_in_svcb(ARGS_FREESTRUCT) {
+ dns_rdata_in_svcb_t *svcb = source;
+
+ REQUIRE(svcb != NULL);
+
+ if (svcb->mctx == NULL) {
+ return;
+ }
+
+ dns_name_free(&svcb->svcdomain, svcb->mctx);
+ isc_mem_free(svcb->mctx, svcb->svc);
+ svcb->mctx = NULL;
+}
+
+static void
+freestruct_in_svcb(ARGS_FREESTRUCT) {
+ dns_rdata_in_svcb_t *svcb = source;
+
+ REQUIRE(svcb != NULL);
+ REQUIRE(svcb->common.rdclass == dns_rdataclass_in);
+ REQUIRE(svcb->common.rdtype == dns_rdatatype_svcb);
+
+ generic_freestruct_in_svcb(CALL_FREESTRUCT);
+}
+
+static isc_result_t
+generic_additionaldata_in_svcb(ARGS_ADDLDATA) {
+ bool alias, done = false;
+ dns_fixedname_t fixed;
+ dns_name_t name, *fname = NULL;
+ dns_offsets_t offsets;
+ dns_rdataset_t rdataset;
+ isc_region_t region;
+ unsigned int cnames = 0;
+
+ dns_name_init(&name, offsets);
+ dns_rdata_toregion(rdata, &region);
+ alias = uint16_fromregion(&region) == 0;
+ isc_region_consume(&region, 2);
+
+ dns_name_fromregion(&name, &region);
+
+ if (dns_name_equal(&name, dns_rootname)) {
+ /*
+ * "." only means owner name in service form.
+ */
+ if (alias || dns_name_equal(owner, dns_rootname) ||
+ !dns_name_ishostname(owner, false))
+ {
+ return (ISC_R_SUCCESS);
+ }
+ /* Only lookup address records */
+ return ((add)(arg, owner, dns_rdatatype_a, NULL));
+ }
+
+ /*
+ * Follow CNAME chains when processing HTTPS and SVCB records.
+ */
+ dns_rdataset_init(&rdataset);
+ fname = dns_fixedname_initname(&fixed);
+ do {
+ RETERR((add)(arg, &name, dns_rdatatype_cname, &rdataset));
+ if (dns_rdataset_isassociated(&rdataset)) {
+ isc_result_t result;
+ result = dns_rdataset_first(&rdataset);
+ if (result == ISC_R_SUCCESS) {
+ dns_rdata_t current = DNS_RDATA_INIT;
+ dns_rdata_cname_t cname;
+
+ dns_rdataset_current(&rdataset, &current);
+
+ result = dns_rdata_tostruct(&current, &cname,
+ NULL);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ dns_name_copy(&cname.cname, fname);
+ dns_name_clone(fname, &name);
+ } else {
+ done = true;
+ }
+ dns_rdataset_disassociate(&rdataset);
+ } else {
+ done = true;
+ }
+ /*
+ * Stop following a potentially infinite CNAME chain.
+ */
+ if (!done && cnames++ > MAX_CNAMES) {
+ return (ISC_R_SUCCESS);
+ }
+ } while (!done);
+
+ /*
+ * Look up HTTPS/SVCB records when processing the alias form.
+ */
+ if (alias) {
+ RETERR((add)(arg, &name, rdata->type, &rdataset));
+ /*
+ * Don't return A or AAAA if this is not the last element
+ * in the HTTP / SVCB chain.
+ */
+ if (dns_rdataset_isassociated(&rdataset)) {
+ dns_rdataset_disassociate(&rdataset);
+ return (ISC_R_SUCCESS);
+ }
+ }
+ return ((add)(arg, &name, dns_rdatatype_a, NULL));
+}
+
+static isc_result_t
+additionaldata_in_svcb(ARGS_ADDLDATA) {
+ REQUIRE(rdata->type == dns_rdatatype_svcb);
+ REQUIRE(rdata->rdclass == dns_rdataclass_in);
+
+ return (generic_additionaldata_in_svcb(CALL_ADDLDATA));
+}
+
+static isc_result_t
+digest_in_svcb(ARGS_DIGEST) {
+ isc_region_t region1;
+
+ REQUIRE(rdata->type == dns_rdatatype_svcb);
+ REQUIRE(rdata->rdclass == dns_rdataclass_in);
+
+ dns_rdata_toregion(rdata, &region1);
+ return ((digest)(arg, &region1));
+}
+
+static bool
+checkowner_in_svcb(ARGS_CHECKOWNER) {
+ REQUIRE(type == dns_rdatatype_svcb);
+ REQUIRE(rdclass == dns_rdataclass_in);
+
+ UNUSED(name);
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (true);
+}
+
+static bool
+generic_checknames_in_svcb(ARGS_CHECKNAMES) {
+ isc_region_t region;
+ dns_name_t name;
+ bool alias;
+
+ UNUSED(owner);
+
+ dns_rdata_toregion(rdata, &region);
+ INSIST(region.length > 1);
+ alias = uint16_fromregion(&region) == 0;
+ isc_region_consume(&region, 2);
+ dns_name_init(&name, NULL);
+ dns_name_fromregion(&name, &region);
+ if (!alias && !dns_name_ishostname(&name, false)) {
+ if (bad != NULL) {
+ dns_name_clone(&name, bad);
+ }
+ return (false);
+ }
+ return (true);
+}
+
+static bool
+checknames_in_svcb(ARGS_CHECKNAMES) {
+ REQUIRE(rdata->type == dns_rdatatype_svcb);
+ REQUIRE(rdata->rdclass == dns_rdataclass_in);
+
+ return (generic_checknames_in_svcb(CALL_CHECKNAMES));
+}
+
+static int
+casecompare_in_svcb(ARGS_COMPARE) {
+ return (compare_in_svcb(rdata1, rdata2));
+}
+
+static isc_result_t
+generic_rdata_in_svcb_first(dns_rdata_in_svcb_t *svcb) {
+ if (svcb->svclen == 0) {
+ return (ISC_R_NOMORE);
+ }
+ svcb->offset = 0;
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+generic_rdata_in_svcb_next(dns_rdata_in_svcb_t *svcb) {
+ isc_region_t region;
+ size_t len;
+
+ if (svcb->offset >= svcb->svclen) {
+ return (ISC_R_NOMORE);
+ }
+
+ region.base = svcb->svc + svcb->offset;
+ region.length = svcb->svclen - svcb->offset;
+ INSIST(region.length >= 4);
+ isc_region_consume(&region, 2);
+ len = uint16_fromregion(&region);
+ INSIST(region.length >= len + 2);
+ svcb->offset += len + 4;
+ return (svcb->offset >= svcb->svclen ? ISC_R_NOMORE : ISC_R_SUCCESS);
+}
+
+static void
+generic_rdata_in_svcb_current(dns_rdata_in_svcb_t *svcb, isc_region_t *region) {
+ size_t len;
+
+ INSIST(svcb->offset <= svcb->svclen);
+
+ region->base = svcb->svc + svcb->offset;
+ region->length = svcb->svclen - svcb->offset;
+ INSIST(region->length >= 4);
+ isc_region_consume(region, 2);
+ len = uint16_fromregion(region);
+ INSIST(region->length >= len + 2);
+ region->base = svcb->svc + svcb->offset;
+ region->length = len + 4;
+}
+
+isc_result_t
+dns_rdata_in_svcb_first(dns_rdata_in_svcb_t *svcb) {
+ REQUIRE(svcb != NULL);
+ REQUIRE(svcb->common.rdtype == dns_rdatatype_svcb);
+ REQUIRE(svcb->common.rdclass == dns_rdataclass_in);
+
+ return (generic_rdata_in_svcb_first(svcb));
+}
+
+isc_result_t
+dns_rdata_in_svcb_next(dns_rdata_in_svcb_t *svcb) {
+ REQUIRE(svcb != NULL);
+ REQUIRE(svcb->common.rdtype == dns_rdatatype_svcb);
+ REQUIRE(svcb->common.rdclass == dns_rdataclass_in);
+
+ return (generic_rdata_in_svcb_next(svcb));
+}
+
+void
+dns_rdata_in_svcb_current(dns_rdata_in_svcb_t *svcb, isc_region_t *region) {
+ REQUIRE(svcb != NULL);
+ REQUIRE(svcb->common.rdtype == dns_rdatatype_svcb);
+ REQUIRE(svcb->common.rdclass == dns_rdataclass_in);
+ REQUIRE(region != NULL);
+
+ generic_rdata_in_svcb_current(svcb, region);
+}
+
+#endif /* RDATA_IN_1_SVCB_64_C */
diff --git a/lib/dns/rdata/in_1/svcb_64.h b/lib/dns/rdata/in_1/svcb_64.h
new file mode 100644
index 0000000..c861716
--- /dev/null
+++ b/lib/dns/rdata/in_1/svcb_64.h
@@ -0,0 +1,37 @@
+/*
+ * 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-dnsop-svcb-https-02
+ */
+
+typedef struct dns_rdata_in_svcb {
+ dns_rdatacommon_t common;
+ isc_mem_t *mctx;
+ uint16_t priority;
+ dns_name_t svcdomain;
+ unsigned char *svc;
+ uint16_t svclen;
+ uint16_t offset;
+} dns_rdata_in_svcb_t;
+
+isc_result_t
+dns_rdata_in_svcb_first(dns_rdata_in_svcb_t *);
+
+isc_result_t
+dns_rdata_in_svcb_next(dns_rdata_in_svcb_t *);
+
+void
+dns_rdata_in_svcb_current(dns_rdata_in_svcb_t *, isc_region_t *);
diff --git a/lib/dns/rdata/in_1/wks_11.c b/lib/dns/rdata/in_1/wks_11.c
new file mode 100644
index 0000000..7252065
--- /dev/null
+++ b/lib/dns/rdata/in_1/wks_11.c
@@ -0,0 +1,404 @@
+/*
+ * 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_IN_1_WKS_11_C
+#define RDATA_IN_1_WKS_11_C
+
+#include <limits.h>
+#include <stdlib.h>
+
+#include <isc/net.h>
+#include <isc/netdb.h>
+#include <isc/once.h>
+
+#define RRTYPE_WKS_ATTRIBUTES (0)
+
+static isc_mutex_t wks_lock;
+
+static void
+init_lock(void) {
+ isc_mutex_init(&wks_lock);
+}
+
+static bool
+mygetprotobyname(const char *name, long *proto) {
+ struct protoent *pe;
+
+ LOCK(&wks_lock);
+ pe = getprotobyname(name);
+ if (pe != NULL) {
+ *proto = pe->p_proto;
+ }
+ UNLOCK(&wks_lock);
+ return (pe != NULL);
+}
+
+static bool
+mygetservbyname(const char *name, const char *proto, long *port) {
+ struct servent *se;
+
+ LOCK(&wks_lock);
+ se = getservbyname(name, proto);
+ if (se != NULL) {
+ *port = ntohs(se->s_port);
+ }
+ UNLOCK(&wks_lock);
+ return (se != NULL);
+}
+
+static isc_result_t
+fromtext_in_wks(ARGS_FROMTEXT) {
+ static isc_once_t once = ISC_ONCE_INIT;
+ isc_token_t token;
+ isc_region_t region;
+ struct in_addr addr;
+ char *e = NULL;
+ long proto;
+ unsigned char bm[8 * 1024]; /* 64k bits */
+ long port;
+ long maxport = -1;
+ const char *ps = NULL;
+ unsigned int n;
+ char service[32];
+ int i;
+ isc_result_t result;
+
+ REQUIRE(type == dns_rdatatype_wks);
+ REQUIRE(rdclass == dns_rdataclass_in);
+
+ UNUSED(type);
+ UNUSED(origin);
+ UNUSED(options);
+ UNUSED(rdclass);
+ UNUSED(callbacks);
+
+ RUNTIME_CHECK(isc_once_do(&once, init_lock) == ISC_R_SUCCESS);
+
+ /*
+ * IPv4 dotted quad.
+ */
+ CHECK(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ false));
+
+ isc_buffer_availableregion(target, &region);
+ if (inet_pton(AF_INET, DNS_AS_STR(token), &addr) != 1) {
+ CHECKTOK(DNS_R_BADDOTTEDQUAD);
+ }
+ if (region.length < 4) {
+ return (ISC_R_NOSPACE);
+ }
+ memmove(region.base, &addr, 4);
+ isc_buffer_add(target, 4);
+
+ /*
+ * Protocol.
+ */
+ CHECK(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ false));
+
+ proto = strtol(DNS_AS_STR(token), &e, 10);
+ if (*e != '\0' && !mygetprotobyname(DNS_AS_STR(token), &proto)) {
+ CHECKTOK(DNS_R_UNKNOWNPROTO);
+ }
+
+ if (proto < 0 || proto > 0xff) {
+ CHECKTOK(ISC_R_RANGE);
+ }
+
+ if (proto == IPPROTO_TCP) {
+ ps = "tcp";
+ } else if (proto == IPPROTO_UDP) {
+ ps = "udp";
+ }
+
+ CHECK(uint8_tobuffer(proto, target));
+
+ memset(bm, 0, sizeof(bm));
+ do {
+ CHECK(isc_lex_getmastertoken(lexer, &token,
+ isc_tokentype_string, true));
+ if (token.type != isc_tokentype_string) {
+ break;
+ }
+
+ /*
+ * Lowercase the service string as some getservbyname() are
+ * case sensitive and the database is usually in lowercase.
+ */
+ strlcpy(service, DNS_AS_STR(token), sizeof(service));
+ for (i = strlen(service) - 1; i >= 0; i--) {
+ if (isupper(service[i] & 0xff)) {
+ service[i] = tolower(service[i] & 0xff);
+ }
+ }
+
+ port = strtol(DNS_AS_STR(token), &e, 10);
+ if (*e != 0 && !mygetservbyname(service, ps, &port) &&
+ !mygetservbyname(DNS_AS_STR(token), ps, &port))
+ {
+ CHECKTOK(DNS_R_UNKNOWNSERVICE);
+ }
+ if (port < 0 || port > 0xffff) {
+ CHECKTOK(ISC_R_RANGE);
+ }
+ if (port > maxport) {
+ maxport = port;
+ }
+ bm[port / 8] |= (0x80 >> (port % 8));
+ } while (1);
+
+ /*
+ * Let upper layer handle eol/eof.
+ */
+ isc_lex_ungettoken(lexer, &token);
+
+ n = (maxport + 8) / 8;
+ result = mem_tobuffer(target, bm, n);
+
+cleanup:
+ return (result);
+}
+
+static isc_result_t
+totext_in_wks(ARGS_TOTEXT) {
+ isc_region_t sr;
+ unsigned short proto;
+ char buf[sizeof("65535")];
+ unsigned int i, j;
+
+ UNUSED(tctx);
+
+ REQUIRE(rdata->type == dns_rdatatype_wks);
+ REQUIRE(rdata->rdclass == dns_rdataclass_in);
+ REQUIRE(rdata->length >= 5);
+
+ dns_rdata_toregion(rdata, &sr);
+ RETERR(inet_totext(AF_INET, tctx->flags, &sr, target));
+ isc_region_consume(&sr, 4);
+
+ proto = uint8_fromregion(&sr);
+ snprintf(buf, sizeof(buf), "%u", proto);
+ RETERR(str_totext(" ", target));
+ RETERR(str_totext(buf, target));
+ isc_region_consume(&sr, 1);
+
+ INSIST(sr.length <= 8 * 1024);
+ 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) {
+ {
+ snprintf(buf, sizeof(buf), "%u",
+ i * 8 + j);
+ RETERR(str_totext(" ", target));
+ RETERR(str_totext(buf, target));
+ }
+ }
+ }
+ }
+ }
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+fromwire_in_wks(ARGS_FROMWIRE) {
+ isc_region_t sr;
+ isc_region_t tr;
+
+ REQUIRE(type == dns_rdatatype_wks);
+ REQUIRE(rdclass == dns_rdataclass_in);
+
+ UNUSED(type);
+ UNUSED(dctx);
+ UNUSED(options);
+ UNUSED(rdclass);
+
+ isc_buffer_activeregion(source, &sr);
+ isc_buffer_availableregion(target, &tr);
+
+ if (sr.length < 5) {
+ return (ISC_R_UNEXPECTEDEND);
+ }
+ if (sr.length > 8 * 1024 + 5) {
+ return (DNS_R_EXTRADATA);
+ }
+ if (sr.length > 5 && sr.base[sr.length - 1] == 0) {
+ return (DNS_R_FORMERR);
+ }
+ if (tr.length < sr.length) {
+ return (ISC_R_NOSPACE);
+ }
+
+ memmove(tr.base, sr.base, sr.length);
+ isc_buffer_add(target, sr.length);
+ isc_buffer_forward(source, sr.length);
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+towire_in_wks(ARGS_TOWIRE) {
+ isc_region_t sr;
+
+ UNUSED(cctx);
+
+ REQUIRE(rdata->type == dns_rdatatype_wks);
+ REQUIRE(rdata->rdclass == dns_rdataclass_in);
+ REQUIRE(rdata->length != 0);
+
+ dns_rdata_toregion(rdata, &sr);
+ return (mem_tobuffer(target, sr.base, sr.length));
+}
+
+static int
+compare_in_wks(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_wks);
+ REQUIRE(rdata1->rdclass == dns_rdataclass_in);
+ 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_in_wks(ARGS_FROMSTRUCT) {
+ dns_rdata_in_wks_t *wks = source;
+ uint32_t a;
+
+ REQUIRE(type == dns_rdatatype_wks);
+ REQUIRE(rdclass == dns_rdataclass_in);
+ REQUIRE(wks != NULL);
+ REQUIRE(wks->common.rdtype == type);
+ REQUIRE(wks->common.rdclass == rdclass);
+ REQUIRE((wks->map != NULL && wks->map_len <= 8 * 1024) ||
+ wks->map_len == 0);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ a = ntohl(wks->in_addr.s_addr);
+ RETERR(uint32_tobuffer(a, target));
+ RETERR(uint8_tobuffer(wks->protocol, target));
+ return (mem_tobuffer(target, wks->map, wks->map_len));
+}
+
+static isc_result_t
+tostruct_in_wks(ARGS_TOSTRUCT) {
+ dns_rdata_in_wks_t *wks = target;
+ uint32_t n;
+ isc_region_t region;
+
+ REQUIRE(wks != NULL);
+ REQUIRE(rdata->type == dns_rdatatype_wks);
+ REQUIRE(rdata->rdclass == dns_rdataclass_in);
+ REQUIRE(rdata->length != 0);
+
+ wks->common.rdclass = rdata->rdclass;
+ wks->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&wks->common, link);
+
+ dns_rdata_toregion(rdata, &region);
+ n = uint32_fromregion(&region);
+ wks->in_addr.s_addr = htonl(n);
+ isc_region_consume(&region, 4);
+ wks->protocol = uint8_fromregion(&region);
+ isc_region_consume(&region, 1);
+ wks->map_len = region.length;
+ wks->map = mem_maybedup(mctx, region.base, region.length);
+ if (wks->map == NULL) {
+ return (ISC_R_NOMEMORY);
+ }
+ wks->mctx = mctx;
+ return (ISC_R_SUCCESS);
+}
+
+static void
+freestruct_in_wks(ARGS_FREESTRUCT) {
+ dns_rdata_in_wks_t *wks = source;
+
+ REQUIRE(wks != NULL);
+ REQUIRE(wks->common.rdtype == dns_rdatatype_wks);
+ REQUIRE(wks->common.rdclass == dns_rdataclass_in);
+
+ if (wks->mctx == NULL) {
+ return;
+ }
+
+ if (wks->map != NULL) {
+ isc_mem_free(wks->mctx, wks->map);
+ }
+ wks->mctx = NULL;
+}
+
+static isc_result_t
+additionaldata_in_wks(ARGS_ADDLDATA) {
+ REQUIRE(rdata->type == dns_rdatatype_wks);
+ REQUIRE(rdata->rdclass == dns_rdataclass_in);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(add);
+ UNUSED(arg);
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+digest_in_wks(ARGS_DIGEST) {
+ isc_region_t r;
+
+ REQUIRE(rdata->type == dns_rdatatype_wks);
+ REQUIRE(rdata->rdclass == dns_rdataclass_in);
+
+ dns_rdata_toregion(rdata, &r);
+
+ return ((digest)(arg, &r));
+}
+
+static bool
+checkowner_in_wks(ARGS_CHECKOWNER) {
+ REQUIRE(type == dns_rdatatype_wks);
+ REQUIRE(rdclass == dns_rdataclass_in);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ return (dns_name_ishostname(name, wildcard));
+}
+
+static bool
+checknames_in_wks(ARGS_CHECKNAMES) {
+ REQUIRE(rdata->type == dns_rdatatype_wks);
+ REQUIRE(rdata->rdclass == dns_rdataclass_in);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(bad);
+
+ return (true);
+}
+
+static int
+casecompare_in_wks(ARGS_COMPARE) {
+ return (compare_in_wks(rdata1, rdata2));
+}
+
+#endif /* RDATA_IN_1_WKS_11_C */
diff --git a/lib/dns/rdata/in_1/wks_11.h b/lib/dns/rdata/in_1/wks_11.h
new file mode 100644
index 0000000..8863725
--- /dev/null
+++ b/lib/dns/rdata/in_1/wks_11.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_in_wks {
+ dns_rdatacommon_t common;
+ isc_mem_t *mctx;
+ struct in_addr in_addr;
+ uint16_t protocol;
+ unsigned char *map;
+ uint16_t map_len;
+} dns_rdata_in_wks_t;