Commit 6b89d3f5b7 for bind

commit 6b89d3f5b730149cbb7ba8e8c66835027cbaeeb2
Author: Alessio Podda <alessio@isc.org>
Date:   Thu Sep 24 15:15:50 2026 +0200

    Fold rdclass choice into the switch

    We fold the rdclass choice into the switch by creating a key off
    rdclass and rdtype.

    This also makes every non-IN rdclass be a pure copy, which is intended
    behaviour.

diff --git a/lib/dns/rdata/towire.c b/lib/dns/rdata/towire.c
index e357ac4ed6..4a86571b61 100644
--- a/lib/dns/rdata/towire.c
+++ b/lib/dns/rdata/towire.c
@@ -289,11 +289,13 @@ towire_in_px(ARGS_TOWIRE) {
 	return dns_name_towire(&name, cctx, target);
 }

+#define RDATA_KEY(rdclass, rdtype) \
+	(((uint32_t)(rdclass) << 16) | (uint32_t)(rdtype))
+
 isc_result_t
 dns_rdata_towire(dns_rdata_t *rdata, dns_compress_t *cctx,
 		 isc_buffer_t *target) {
-	isc_result_t result = ISC_R_NOTIMPLEMENTED;
-	bool use_default = false;
+	isc_result_t result;
 	isc_buffer_t st;

 	REQUIRE(rdata != NULL);
@@ -309,172 +311,113 @@ dns_rdata_towire(dns_rdata_t *rdata, dns_compress_t *cctx,

 	st = *target;

-	switch (rdata->type) {
-	case dns_rdatatype_ns:
+	switch (RDATA_KEY(rdata->rdclass, rdata->type)) {
+	case RDATA_KEY(dns_rdataclass_in, dns_rdatatype_ns):
 		result = towire_name(rdata, cctx, target, true, 0, 0);
 		break;
-	case dns_rdatatype_md:
+	case RDATA_KEY(dns_rdataclass_in, dns_rdatatype_md):
 		result = towire_name(rdata, cctx, target, true, 0, 0);
 		break;
-	case dns_rdatatype_mf:
+	case RDATA_KEY(dns_rdataclass_in, dns_rdatatype_mf):
 		result = towire_name(rdata, cctx, target, true, 0, 0);
 		break;
-	case dns_rdatatype_cname:
+	case RDATA_KEY(dns_rdataclass_in, dns_rdatatype_cname):
 		result = towire_name(rdata, cctx, target, true, 0, 0);
 		break;
-	case dns_rdatatype_soa:
+	case RDATA_KEY(dns_rdataclass_in, dns_rdatatype_soa):
 		result = towire_soa(rdata, cctx, target);
 		break;
-	case dns_rdatatype_mb:
+	case RDATA_KEY(dns_rdataclass_in, dns_rdatatype_mb):
 		result = towire_name(rdata, cctx, target, true, 0, 0);
 		break;
-	case dns_rdatatype_mg:
+	case RDATA_KEY(dns_rdataclass_in, dns_rdatatype_mg):
 		result = towire_name(rdata, cctx, target, true, 0, 0);
 		break;
-	case dns_rdatatype_mr:
+	case RDATA_KEY(dns_rdataclass_in, dns_rdatatype_mr):
 		result = towire_name(rdata, cctx, target, true, 0, 0);
 		break;
-	case dns_rdatatype_ptr:
+	case RDATA_KEY(dns_rdataclass_in, dns_rdatatype_ptr):
 		result = towire_name(rdata, cctx, target, true, 0, 0);
 		break;
-	case dns_rdatatype_minfo:
+	case RDATA_KEY(dns_rdataclass_in, dns_rdatatype_minfo):
 		result = towire_minfo(rdata, cctx, target);
 		break;
-	case dns_rdatatype_mx:
+	case RDATA_KEY(dns_rdataclass_in, dns_rdatatype_mx):
 		result = towire_name(rdata, cctx, target, true, 2, 0);
 		break;
-	case dns_rdatatype_rp:
+	case RDATA_KEY(dns_rdataclass_in, dns_rdatatype_rp):
 		result = towire_rp(rdata, cctx, target);
 		break;
-	case dns_rdatatype_afsdb:
+	case RDATA_KEY(dns_rdataclass_in, dns_rdatatype_afsdb):
 		result = towire_name(rdata, cctx, target, false, 2, 0);
 		break;
-	case dns_rdatatype_rt:
+	case RDATA_KEY(dns_rdataclass_in, dns_rdatatype_rt):
 		result = towire_name(rdata, cctx, target, false, 2, 0);
 		break;
-	case dns_rdatatype_nsap_ptr:
-		switch (rdata->rdclass) {
-		case dns_rdataclass_in:
-			result = towire_name(rdata, cctx, target, false, 0, 0);
-			break;
-		default:
-			use_default = 1;
-			break;
-		}
-		break;
-	case dns_rdatatype_sig:
+	case RDATA_KEY(dns_rdataclass_in, dns_rdatatype_nsap_ptr):
+		result = towire_name(rdata, cctx, target, false, 0, 0);
+		break;
+	case RDATA_KEY(dns_rdataclass_in, dns_rdatatype_sig):
 		result = towire_name(rdata, cctx, target, false, 18,
 				     TOWIRE_NAME_REST);
 		break;
-	case dns_rdatatype_px:
-		switch (rdata->rdclass) {
-		case dns_rdataclass_in:
-			result = towire_in_px(rdata, cctx, target);
-			break;
-		default:
-			use_default = 1;
-			break;
-		}
-		break;
-	case dns_rdatatype_nxt:
+	case RDATA_KEY(dns_rdataclass_in, dns_rdatatype_px):
+		result = towire_in_px(rdata, cctx, target);
+		break;
+	case RDATA_KEY(dns_rdataclass_in, dns_rdatatype_nxt):
 		result = towire_name(rdata, cctx, target, false, 0,
 				     TOWIRE_NAME_REST);
 		break;
-	case dns_rdatatype_srv:
-		switch (rdata->rdclass) {
-		case dns_rdataclass_in:
-			result = towire_name(rdata, cctx, target, false, 6, 0);
-			break;
-		default:
-			use_default = 1;
-			break;
-		}
-		break;
-	case dns_rdatatype_naptr:
+	case RDATA_KEY(dns_rdataclass_in, dns_rdatatype_srv):
+		result = towire_name(rdata, cctx, target, false, 6, 0);
+		break;
+	case RDATA_KEY(dns_rdataclass_in, dns_rdatatype_naptr):
 		result = towire_naptr(rdata, cctx, target);
 		break;
-	case dns_rdatatype_kx:
-		switch (rdata->rdclass) {
-		case dns_rdataclass_in:
-			result = towire_name(rdata, cctx, target, false, 2, 0);
-			break;
-		default:
-			use_default = 1;
-			break;
-		}
-		break;
-	case dns_rdatatype_a6:
-		switch (rdata->rdclass) {
-		case dns_rdataclass_in:
-			result = towire_in_a6(rdata, cctx, target);
-			break;
-		default:
-			use_default = 1;
-			break;
-		}
-		break;
-	case dns_rdatatype_dname:
+	case RDATA_KEY(dns_rdataclass_in, dns_rdatatype_kx):
+		result = towire_name(rdata, cctx, target, false, 2, 0);
+		break;
+	case RDATA_KEY(dns_rdataclass_in, dns_rdatatype_a6):
+		result = towire_in_a6(rdata, cctx, target);
+		break;
+	case RDATA_KEY(dns_rdataclass_in, dns_rdatatype_dname):
 		result = towire_name(rdata, cctx, target, false, 0, 0);
 		break;
-	case dns_rdatatype_rrsig:
+	case RDATA_KEY(dns_rdataclass_in, dns_rdatatype_rrsig):
 		result = towire_name(rdata, cctx, target, false, 18,
 				     TOWIRE_NAME_REST);
 		break;
-	case dns_rdatatype_nsec:
+	case RDATA_KEY(dns_rdataclass_in, dns_rdatatype_nsec):
 		result = towire_name(rdata, cctx, target, false, 0,
 				     TOWIRE_NAME_REST);
 		break;
-	case dns_rdatatype_talink:
+	case RDATA_KEY(dns_rdataclass_in, dns_rdatatype_talink):
 		result = towire_talink(rdata, cctx, target);
 		break;
-	case dns_rdatatype_svcb:
-		switch (rdata->rdclass) {
-		case dns_rdataclass_in:
-			result = towire_name(rdata, cctx, target, false, 2,
-					     TOWIRE_NAME_REST);
-			break;
-		default:
-			use_default = 1;
-			break;
-		}
-		break;
-	case dns_rdatatype_https:
-		switch (rdata->rdclass) {
-		case dns_rdataclass_in:
-			result = towire_name(rdata, cctx, target, false, 2,
-					     TOWIRE_NAME_REST);
-			break;
-		default:
-			use_default = 1;
-			break;
-		}
-		break;
-	case dns_rdatatype_dsync:
+	case RDATA_KEY(dns_rdataclass_in, dns_rdatatype_svcb):
+		result = towire_name(rdata, cctx, target, false, 2,
+				     TOWIRE_NAME_REST);
+		break;
+	case RDATA_KEY(dns_rdataclass_in, dns_rdatatype_https):
+		result = towire_name(rdata, cctx, target, false, 2,
+				     TOWIRE_NAME_REST);
+		break;
+	case RDATA_KEY(dns_rdataclass_in, dns_rdatatype_dsync):
 		result = towire_name(rdata, cctx, target, false, 5, 0);
 		break;
-	case dns_rdatatype_tkey:
+	case RDATA_KEY(dns_rdataclass_in, dns_rdatatype_tkey):
 		result = towire_name(rdata, cctx, target, false, 0,
 				     TOWIRE_NAME_REST);
 		break;
-	case dns_rdatatype_tsig:
-		switch (rdata->rdclass) {
-		case dns_rdataclass_any:
-			result = towire_name(rdata, cctx, target, false, 0,
-					     TOWIRE_NAME_REST);
-			break;
-		default:
-			use_default = 1;
-			break;
-		}
+	case RDATA_KEY(dns_rdataclass_any, dns_rdatatype_tsig):
+		result = towire_name(rdata, cctx, target, false, 0,
+				     TOWIRE_NAME_REST);
 		break;
 	default:
-		use_default = 1;
+		result = mem_tobuffer(target, rdata->data, rdata->length);
 		break;
 	}

-	if (use_default) {
-		return mem_tobuffer(target, rdata->data, rdata->length);
-	}
 	if (result != ISC_R_SUCCESS) {
 		*target = st;
 		dns_compress_rollback(cctx, target->used);
diff --git a/tests/dns/rdata_test.c b/tests/dns/rdata_test.c
index b3774236cc..3acb79e4c1 100644
--- a/tests/dns/rdata_test.c
+++ b/tests/dns/rdata_test.c
@@ -3934,6 +3934,42 @@ ISC_RUN_TEST_IMPL(secalg_format) {
 	assert_string_equal(small, "");
 }

+/* Non-IN names must be copied without compression, even on repeated use. */
+ISC_RUN_TEST_IMPL(towire_other_classes) {
+	unsigned char wire[] = { 2,   'n', 's', 7,   'e', 'x',
+				 'a', 'm', 'p', 'l', 'e', 0 };
+	isc_region_t region = { .base = wire, .length = sizeof(wire) };
+	dns_rdataclass_t classes[] = { dns_rdataclass_ch, dns_rdataclass_hs,
+				       65535 };
+
+	for (size_t i = 0; i < sizeof(classes) / sizeof(classes[0]); i++) {
+		dns_rdata_t rdata = DNS_RDATA_INIT;
+		dns_compress_t cctx;
+		unsigned char buf[2 * sizeof(wire)];
+		isc_buffer_t target;
+		isc_result_t result;
+
+		dns_rdata_fromregion(&rdata, classes[i], dns_rdatatype_ns,
+				     &region);
+		dns_compress_init(&cctx, isc_g_mctx, 0);
+		isc_buffer_init(&target, buf, sizeof(buf));
+		for (size_t j = 0; j < 2; j++) {
+			result = dns_rdata_towire(&rdata, &cctx, &target);
+			assert_int_equal(result, ISC_R_SUCCESS);
+			assert_int_equal(isc_buffer_usedlength(&target),
+					 (j + 1) * sizeof(wire));
+			assert_memory_equal(buf + j * sizeof(wire), wire,
+					    sizeof(wire));
+		}
+		result = dns_rdata_towire(&rdata, &cctx, &target);
+		assert_int_equal(result, ISC_R_NOSPACE);
+		assert_int_equal(isc_buffer_usedlength(&target), sizeof(buf));
+		assert_memory_equal(buf, wire, sizeof(wire));
+		assert_memory_equal(buf + sizeof(wire), wire, sizeof(wire));
+		dns_compress_invalidate(&cctx);
+	}
+}
+
 ISC_TEST_LIST_START

 /* types */
@@ -3980,6 +4016,7 @@ ISC_TEST_ENTRY(atcname)
 ISC_TEST_ENTRY(atparent)
 ISC_TEST_ENTRY(iszonecutauth)
 ISC_TEST_ENTRY(secalg_format)
+ISC_TEST_ENTRY(towire_other_classes)
 ISC_TEST_LIST_END

 ISC_TEST_MAIN