Commit 5eefd38e1b for bind

commit 5eefd38e1b18a059c7b18e56a0b6861d661b0384
Author: Alessio Podda <alessio@isc.org>
Date:   Tue Apr 14 17:23:05 2026 +0200

    Coalesce calls to dns_linkedname_name

    As a cleanup, in cases where the same linkedname is repeadetly cast to
    dns_name_t, assign the cast to a separate variable once and pass it
    around.

diff --git a/bin/delv/delv.c b/bin/delv/delv.c
index 2450223172..e94bd84701 100644
--- a/bin/delv/delv.c
+++ b/bin/delv/delv.c
@@ -444,7 +444,7 @@ print_status(dns_rdataset_t *rdataset) {
 }

 static void
-printdata(dns_rdataset_t *rdataset, dns_name_t *owner) {
+printdata(dns_rdataset_t *rdataset, const dns_name_t *owner) {
 	isc_result_t result = ISC_R_SUCCESS;
 	static dns_trust_t trust;
 	static bool first = true;
@@ -1947,7 +1947,7 @@ recvresponse(void *arg) {
 	dns_message_t *query = dns_request_getarg(request);
 	isc_result_t result = dns_request_getresult(request);
 	dns_message_t *response = NULL;
-	dns_name_t *prev = NULL;
+	const dns_name_t *prev = NULL;

 	if (result != ISC_R_SUCCESS) {
 		fatal("request event result: %s", isc_result_totext(result));
@@ -1968,10 +1968,11 @@ recvresponse(void *arg) {
 		goto cleanup;
 	}

-	MSG_SECTION_FOREACH(response, DNS_SECTION_ANSWER, name) {
+	MSG_SECTION_FOREACH(response, DNS_SECTION_ANSWER, linkedname) {
+		const dns_name_t *name = dns_linkedname_name(linkedname);
 		dns_rdatatype_t prevtype = dns_rdatatype_none;

-		ISC_LIST_FOREACH(name->list, rdataset, link) {
+		ISC_LIST_FOREACH(linkedname->list, rdataset, link) {
 			dns_rdataset_t rds, sigs;
 			int options = 0;

@@ -1982,7 +1983,7 @@ recvresponse(void *arg) {
 			 * fine, we can just print that version.
 			 */
 			if (!showtrust) {
-				printdata(rdataset, dns_linkedname_name(name));
+				printdata(rdataset, name);
 				continue;
 			}

@@ -1994,12 +1995,10 @@ recvresponse(void *arg) {
 			 * duplicate output, so we check here whether we've
 			 * already printed this name and type.
 			 */
-			if (prev != NULL &&
-			    dns_name_equal(prev, dns_linkedname_name(name)))
-			{
+			if (prev != NULL && dns_name_equal(prev, name)) {
 				continue;
 			}
-			prev = dns_linkedname_name(name);
+			prev = name;

 			if (prevtype == rdataset->type) {
 				continue;
@@ -2017,15 +2016,13 @@ recvresponse(void *arg) {
 			if (cdflag) {
 				options |= DNS_DBFIND_PENDINGOK;
 			}
-			result = dns_view_simplefind(
-				view, dns_linkedname_name(name), rdataset->type,
-				0, options, &rds, &sigs);
+			result = dns_view_simplefind(view, name, rdataset->type,
+						     0, options, &rds, &sigs);
 			if (result == ISC_R_SUCCESS) {
-				printdata(&rds, dns_linkedname_name(name));
+				printdata(&rds, name);
 				dns_rdataset_disassociate(&rds);
 				if (dns_rdataset_isassociated(&sigs)) {
-					printdata(&sigs,
-						  dns_linkedname_name(name));
+					printdata(&sigs, name);
 					dns_rdataset_disassociate(&sigs);
 				}
 			}
diff --git a/bin/dig/dighost.c b/bin/dig/dighost.c
index 621a7852b0..89ff9ba235 100644
--- a/bin/dig/dighost.c
+++ b/bin/dig/dighost.c
@@ -2174,8 +2174,10 @@ setup_lookup(dig_lookup_t *lookup) {
 	}

 	if (lookup->origin != NULL) {
+		dns_linkedname_t *oname = NULL;
+
 		debug("trying origin %s", lookup->origin->origin);
-		dns_message_gettempname(lookup->sendmsg, &lookup->oname);
+		dns_message_gettempname(lookup->sendmsg, &oname);
 		/* XXX Helper funct to conv char* to name? */
 		origin = lookup->origin->origin;
 #ifdef HAVE_LIBIDN2
@@ -2188,12 +2190,11 @@ setup_lookup(dig_lookup_t *lookup) {
 		len = (unsigned int)strlen(origin);
 		isc_buffer_init(&b, origin, len);
 		isc_buffer_add(&b, len);
-		result = dns_name_fromtext(dns_linkedname_name(lookup->oname),
-					   &b, dns_rootname, 0);
+		result = dns_name_fromtext(dns_linkedname_name(oname), &b,
+					   dns_rootname, 0);
 		if (result != ISC_R_SUCCESS) {
 			dns_message_puttempname(lookup->sendmsg, &lookup->name);
-			dns_message_puttempname(lookup->sendmsg,
-						&lookup->oname);
+			dns_message_puttempname(lookup->sendmsg, &oname);
 			fatal("'%s' is not in legal name syntax (%s)", origin,
 			      isc_result_totext(result));
 		}
@@ -2213,8 +2214,7 @@ setup_lookup(dig_lookup_t *lookup) {
 				if (!dns_name_isabsolute(name)) {
 					result = dns_name_concatenate(
 						name,
-						dns_linkedname_name(
-							lookup->oname),
+						dns_linkedname_name(oname),
 						dns_linkedname_name(
 							lookup->name));
 				} else {
@@ -2227,7 +2227,7 @@ setup_lookup(dig_lookup_t *lookup) {
 				dns_message_puttempname(lookup->sendmsg,
 							&lookup->name);
 				dns_message_puttempname(lookup->sendmsg,
-							&lookup->oname);
+							&oname);
 				if (result == DNS_R_NAMETOOLONG) {
 					return false;
 				}
@@ -2236,7 +2236,7 @@ setup_lookup(dig_lookup_t *lookup) {
 				      isc_result_totext(result));
 			}
 		}
-		dns_message_puttempname(lookup->sendmsg, &lookup->oname);
+		dns_message_puttempname(lookup->sendmsg, &oname);
 	} else {
 		debug("using root origin");
 		if (lookup->trace && lookup->trace_root) {
diff --git a/bin/dig/dighost.h b/bin/dig/dighost.h
index 16cf60fb9f..196f83284e 100644
--- a/bin/dig/dighost.h
+++ b/bin/dig/dighost.h
@@ -138,7 +138,6 @@ struct dig_lookup {
 	dns_linkedname_t *name;
 	isc_interval_t interval;
 	dns_message_t *sendmsg;
-	dns_linkedname_t *oname;
 	ISC_LINK(dig_lookup_t) link;
 	ISC_LIST(dig_query_t) q;
 	ISC_LIST(dig_query_t) connecting;
diff --git a/bin/nsupdate/nsupdate.c b/bin/nsupdate/nsupdate.c
index 9eac232fd9..79f2fb8979 100644
--- a/bin/nsupdate/nsupdate.c
+++ b/bin/nsupdate/nsupdate.c
@@ -1877,7 +1877,7 @@ evaluate_class(char *cmdline) {
 static uint16_t
 update_addordelete(char *cmdline, bool isdelete) {
 	isc_result_t result;
-	dns_linkedname_t *name = NULL;
+	dns_linkedname_t *linkedname = NULL;
 	uint32_t ttl;
 	char *word;
 	dns_rdataclass_t rdataclass;
@@ -1893,10 +1893,11 @@ update_addordelete(char *cmdline, bool isdelete) {
 	/*
 	 * Read the owner name.
 	 */
-	retval = parse_name(&cmdline, updatemsg, &name);
+	retval = parse_name(&cmdline, updatemsg, &linkedname);
 	if (retval != STATUS_MORE) {
 		return retval;
 	}
+	const dns_name_t *name = dns_linkedname_name(linkedname);

 	dns_message_gettemprdata(updatemsg, &rdata);

@@ -2022,8 +2023,8 @@ parseclass:
 		dns_fixedname_t fixed;
 		dns_name_t *bad;

-		if (!dns_rdata_checkowner(dns_linkedname_name(name),
-					  rdata->rdclass, rdata->type, true))
+		if (!dns_rdata_checkowner(name, rdata->rdclass, rdata->type,
+					  true))
 		{
 			char namebuf[DNS_NAME_FORMATSIZE];

@@ -2035,9 +2036,7 @@ parseclass:
 		}

 		bad = dns_fixedname_initname(&fixed);
-		if (!dns_rdata_checknames(rdata, dns_linkedname_name(name),
-					  bad))
-		{
+		if (!dns_rdata_checknames(rdata, name, bad)) {
 			char namebuf[DNS_NAME_FORMATSIZE];

 			dns_name_format(bad, namebuf, sizeof(namebuf));
@@ -2048,7 +2047,7 @@ parseclass:
 	}

 	if (!isdelete && checksvcb && rdata->type == dns_rdatatype_svcb) {
-		result = dns_rdata_checksvcb(dns_linkedname_name(name), rdata);
+		result = dns_rdata_checksvcb(name, rdata);
 		if (result != ISC_R_SUCCESS) {
 			fprintf(stderr, "check-svcb failed: %s\n",
 				isc_result_totext(result));
@@ -2079,14 +2078,14 @@ doneparsing:
 	rdatalist->ttl = (dns_ttl_t)ttl;
 	ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
 	dns_rdatalist_tordataset(rdatalist, rdataset);
-	ISC_LIST_INIT(name->list);
-	ISC_LIST_APPEND(name->list, rdataset, link);
-	dns_message_addname(updatemsg, name, DNS_SECTION_UPDATE);
+	ISC_LIST_INIT(linkedname->list);
+	ISC_LIST_APPEND(linkedname->list, rdataset, link);
+	dns_message_addname(updatemsg, linkedname, DNS_SECTION_UPDATE);
 	return STATUS_MORE;

 failure:
-	if (name != NULL) {
-		dns_message_puttempname(updatemsg, &name);
+	if (linkedname != NULL) {
+		dns_message_puttempname(updatemsg, &linkedname);
 	}
 	dns_message_puttemprdata(updatemsg, &rdata);
 	return STATUS_SYNTAX;
diff --git a/lib/dns/tkey.c b/lib/dns/tkey.c
index 750bf03d58..d50168ae3b 100644
--- a/lib/dns/tkey.c
+++ b/lib/dns/tkey.c
@@ -285,7 +285,7 @@ cleanup:
 }

 static isc_result_t
-process_deletetkey(dns_name_t *signer, dns_name_t *name,
+process_deletetkey(const dns_name_t *signer, const dns_name_t *name,
 		   dns_rdata_tkey_t *tkeyin, dns_rdata_tkey_t *tkeyout,
 		   dns_tsigkeyring_t *ring) {
 	isc_result_t result;
@@ -402,7 +402,6 @@ dns_tkey_processquery(dns_message_t *msg, dns_tkeyctx_t *tctx,
 		/*
 		 * A delete operation uses the fully specified qname.
 		 */
-		// FIXME: Is this correct?
 		keyname = dns_linkedname_name(qname);
 		CHECK(process_deletetkey(signer, keyname, &tkeyin, &tkeyout,
 					 ring));
diff --git a/lib/ns/update.c b/lib/ns/update.c
index 2891144431..9d503f8eec 100644
--- a/lib/ns/update.c
+++ b/lib/ns/update.c
@@ -216,7 +216,7 @@ typedef struct {
 	dns_db_t *db;
 	dns_dbversion_t *ver;
 	dns_diff_t *diff;
-	dns_name_t *name;
+	const dns_name_t *name;
 	dns_name_t *oldname;
 	dns_rdata_t *update_rr;
 	dns_ttl_t update_rr_ttl;
@@ -241,7 +241,7 @@ forward_done(void *arg);
 static isc_result_t
 add_rr_prepare_action(void *data, rr_t *rr);
 static isc_result_t
-rr_exists(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
+rr_exists(dns_db_t *db, dns_dbversion_t *ver, const dns_name_t *name,
 	  const dns_rdata_t *rdata, bool *flag);

 /**************************************************************************/
@@ -442,7 +442,7 @@ cleanup:

 static isc_result_t
 update_one_rr(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff,
-	      dns_diffop_t op, dns_name_t *name, dns_ttl_t ttl,
+	      dns_diffop_t op, const dns_name_t *name, dns_ttl_t ttl,
 	      dns_rdata_t *rdata) {
 	dns_difftuple_t *tuple = NULL;

@@ -514,7 +514,7 @@ foreach_node_rr_action(void *data, dns_rdataset_t *rdataset) {
  * If 'action' returns an error, abort iteration and return the error.
  */
 static isc_result_t
-foreach_rrset(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
+foreach_rrset(dns_db_t *db, dns_dbversion_t *ver, const dns_name_t *name,
 	      rrset_func *action, void *action_data) {
 	isc_result_t result;
 	dns_dbnode_t *node;
@@ -576,7 +576,7 @@ cleanup_node:
  * and return the error.
  */
 static isc_result_t
-foreach_node_rr(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
+foreach_node_rr(dns_db_t *db, dns_dbversion_t *ver, const dns_name_t *name,
 		rr_func *rr_action, void *rr_action_data) {
 	foreach_node_rr_ctx_t ctx;
 	ctx.rr_action = rr_action;
@@ -594,7 +594,7 @@ foreach_node_rr(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
  * If 'action' returns an error, abort iteration and return the error.
  */
 static isc_result_t
-foreach_rr(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
+foreach_rr(dns_db_t *db, dns_dbversion_t *ver, const dns_name_t *name,
 	   dns_rdatatype_t type, dns_rdatatype_t covers, rr_func *rr_action,
 	   void *rr_action_data) {
 	isc_result_t result;
@@ -727,7 +727,7 @@ rrset_exists_action(void *data ISC_ATTR_UNUSED, rr_t *rr ISC_ATTR_UNUSED) {
  * to false otherwise.
  */
 static isc_result_t
-rrset_exists(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
+rrset_exists(dns_db_t *db, dns_dbversion_t *ver, const dns_name_t *name,
 	     dns_rdatatype_t type, dns_rdatatype_t covers, bool *exists) {
 	isc_result_t result;
 	result = foreach_rr(db, ver, name, type, covers, rrset_exists_action,
@@ -758,7 +758,7 @@ cname_compatibility_action(void *data ISC_ATTR_UNUSED, dns_rdataset_t *rrset) {
  */
 static isc_result_t
 cname_incompatible_rrset_exists(dns_db_t *db, dns_dbversion_t *ver,
-				dns_name_t *name, bool *exists) {
+				const dns_name_t *name, bool *exists) {
 	isc_result_t result;
 	result = foreach_rrset(db, ver, name, cname_compatibility_action, NULL);
 	RETURN_EXISTENCE_FLAG;
@@ -778,7 +778,7 @@ count_rr_action(void *data, rr_t *rr ISC_ATTR_UNUSED) {
  * Count the number of RRs of 'type' belonging to 'name' in 'ver' of 'db'.
  */
 static isc_result_t
-rr_count(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
+rr_count(dns_db_t *db, dns_dbversion_t *ver, const dns_name_t *name,
 	 dns_rdatatype_t type, dns_rdatatype_t covers, int *countp) {
 	*countp = 0;
 	return foreach_rr(db, ver, name, type, covers, count_rr_action, countp);
@@ -798,7 +798,7 @@ name_exists_action(void *data ISC_ATTR_UNUSED,
  * Set '*exists' to true iff the given name exists, to false otherwise.
  */
 static isc_result_t
-name_exists(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
+name_exists(dns_db_t *db, dns_dbversion_t *ver, const dns_name_t *name,
 	    bool *exists) {
 	isc_result_t result;
 	result = foreach_rrset(db, ver, name, name_exists_action, NULL);
@@ -812,10 +812,10 @@ name_exists(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
  */
 typedef struct {
 	/* The ownername of the record to be updated. */
-	dns_name_t *name;
+	const dns_name_t *name;

 	/* The signature's name if the request was signed. */
-	dns_name_t *signer;
+	const dns_name_t *signer;

 	/* The address of the client. */
 	isc_netaddr_t *addr;
@@ -898,9 +898,10 @@ ssu_checkrule(void *data, dns_rdataset_t *rrset) {
 }

 static bool
-ssu_checkall(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
-	     dns_ssutable_t *ssutable, dns_name_t *signer, isc_netaddr_t *addr,
-	     dns_aclenv_t *aclenv, bool tcp, dst_key_t *key) {
+ssu_checkall(dns_db_t *db, dns_dbversion_t *ver, const dns_name_t *name,
+	     dns_ssutable_t *ssutable, const dns_name_t *signer,
+	     isc_netaddr_t *addr, dns_aclenv_t *aclenv, bool tcp,
+	     dst_key_t *key) {
 	isc_result_t result;
 	ssu_check_t ssuinfo;

@@ -960,7 +961,7 @@ ssu_checkrr(void *data, rr_t *rr) {
  * 'name' and 'rdata' to 'diff'.
  */
 static void
-temp_append(dns_diff_t *diff, dns_name_t *name, dns_rdata_t *rdata) {
+temp_append(dns_diff_t *diff, const dns_name_t *name, dns_rdata_t *rdata) {
 	dns_difftuple_t *tuple = NULL;

 	REQUIRE(DNS_DIFF_VALID(diff));
@@ -1170,7 +1171,7 @@ typedef struct {
 	dns_db_t *db;
 	dns_dbversion_t *ver;
 	dns_diff_t *diff;
-	dns_name_t *name;
+	const dns_name_t *name;
 	dns_rdata_t *update_rr;
 } conditional_delete_ctx_t;

@@ -1390,7 +1391,7 @@ delete_if_action(void *data, rr_t *rr) {
  */
 static isc_result_t
 delete_if(rr_predicate *predicate, dns_zone_t *zone, dns_db_t *db,
-	  dns_dbversion_t *ver, dns_name_t *name, dns_rdatatype_t type,
+	  dns_dbversion_t *ver, const dns_name_t *name, dns_rdatatype_t type,
 	  dns_rdatatype_t covers, dns_rdata_t *update_rr, dns_diff_t *diff) {
 	conditional_delete_ctx_t ctx;
 	ctx.predicate = predicate;
@@ -1642,16 +1643,17 @@ send_update(ns_client_t *client, dns_zone_t *zone) {
 	}

 	update = 0;
-	MSG_SECTION_FOREACH(request, DNS_SECTION_UPDATE, name) {
+	MSG_SECTION_FOREACH(request, DNS_SECTION_UPDATE, linkedname) {
 		dns_rdata_t rdata = DNS_RDATA_INIT;
 		dns_ttl_t ttl;
 		dns_rdataclass_t update_class;
+		const dns_name_t *name = dns_linkedname_name(linkedname);

 		INSIST(ssutable == NULL || update < maxbytypelen);
-		get_current_rr(name, &rdata, &covers, &ttl, &update_class);
+		get_current_rr(linkedname, &rdata, &covers, &ttl,
+			       &update_class);

-		if (!dns_name_issubdomain(dns_linkedname_name(name), zonename))
-		{
+		if (!dns_name_issubdomain(name, zonename)) {
 			FAILC(DNS_R_NOTZONE, "update RR is outside zone");
 		}
 		if (update_class == dns_rdataclass_in) {
@@ -1663,8 +1665,7 @@ send_update(ns_client_t *client, dns_zone_t *zone) {
 			if (dns_rdatatype_ismeta(rdata.type)) {
 				FAILC(DNS_R_FORMERR, "meta-RR in update");
 			}
-			result = dns_zone_checknames(
-				zone, dns_linkedname_name(name), &rdata);
+			result = dns_zone_checknames(zone, name, &rdata);
 			if (result != ISC_R_SUCCESS) {
 				CLEANUP(DNS_R_REFUSED);
 			}
@@ -1672,14 +1673,12 @@ send_update(ns_client_t *client, dns_zone_t *zone) {
 			    rdata.rdclass == dns_rdataclass_in &&
 			    rdata.type == dns_rdatatype_svcb)
 			{
-				result = dns_rdata_checksvcb(
-					dns_linkedname_name(name), &rdata);
+				result = dns_rdata_checksvcb(name, &rdata);
 				if (result != ISC_R_SUCCESS) {
 					const char *reason =
 						isc_result_totext(result);
-					FAILNT(DNS_R_REFUSED,
-					       dns_linkedname_name(name),
-					       rdata.type, reason);
+					FAILNT(DNS_R_REFUSED, name, rdata.type,
+					       reason);
 				}
 			}
 		} else if (update_class == dns_rdataclass_any) {
@@ -1712,7 +1711,7 @@ send_update(ns_client_t *client, dns_zone_t *zone) {
 			FAILC(DNS_R_REFUSED, "explicit NSEC updates are not "
 					     "allowed in secure zones");
 		} else if (rdata.type == dns_rdatatype_rrsig &&
-			   !dns_name_equal(dns_linkedname_name(name), zonename))
+			   !dns_name_equal(name, zonename))
 		{
 			FAILC(DNS_R_REFUSED,
 			      "explicit RRSIG updates are currently not "
@@ -1759,7 +1758,7 @@ send_update(ns_client_t *client, dns_zone_t *zone) {
 			{
 				ssu_check_t ssuinfo;

-				ssuinfo.name = dns_linkedname_name(name);
+				ssuinfo.name = name;
 				ssuinfo.table = ssutable;
 				ssuinfo.signer = client->inner.signer;
 				ssuinfo.addr = &netaddr;
@@ -1767,10 +1766,9 @@ send_update(ns_client_t *client, dns_zone_t *zone) {
 				ssuinfo.tcp = client->inner.tcp;
 				ssuinfo.key = tsigkey;

-				result = foreach_rr(
-					db, ver, dns_linkedname_name(name),
-					rdata.type, dns_rdatatype_none,
-					ssu_checkrr, &ssuinfo);
+				result = foreach_rr(db, ver, name, rdata.type,
+						    dns_rdatatype_none,
+						    ssu_checkrr, &ssuinfo);
 				if (result != ISC_R_SUCCESS) {
 					FAILC(DNS_R_REFUSED,
 					      "rejected by secure update");
@@ -1779,15 +1777,13 @@ send_update(ns_client_t *client, dns_zone_t *zone) {
 				   update_class == dns_rdataclass_none)
 			{
 				bool flag;
-				CHECK(rr_exists(db, ver,
-						dns_linkedname_name(name),
-						&rdata, &flag));
+				CHECK(rr_exists(db, ver, name, &rdata, &flag));
 				if (flag &&
 				    !dns_ssutable_checkrules(
 					    ssutable, client->inner.signer,
-					    dns_linkedname_name(name), &netaddr,
-					    client->inner.tcp, env, rdata.type,
-					    target, tsigkey, NULL))
+					    name, &netaddr, client->inner.tcp,
+					    env, rdata.type, target, tsigkey,
+					    NULL))
 				{
 					FAILC(DNS_R_REFUSED,
 					      "rejected by secure update");
@@ -1796,9 +1792,9 @@ send_update(ns_client_t *client, dns_zone_t *zone) {
 				const dns_ssurule_t *ssurule = NULL;
 				if (!dns_ssutable_checkrules(
 					    ssutable, client->inner.signer,
-					    dns_linkedname_name(name), &netaddr,
-					    client->inner.tcp, env, rdata.type,
-					    target, tsigkey, &ssurule))
+					    name, &netaddr, client->inner.tcp,
+					    env, rdata.type, target, tsigkey,
+					    &ssurule))
 				{
 					FAILC(DNS_R_REFUSED,
 					      "rejected by secure update");
@@ -1806,11 +1802,10 @@ send_update(ns_client_t *client, dns_zone_t *zone) {
 				maxbytype[update] = dns_ssurule_max(ssurule,
 								    rdata.type);
 			} else {
-				if (!ssu_checkall(
-					    db, ver, dns_linkedname_name(name),
-					    ssutable, client->inner.signer,
-					    &netaddr, env, client->inner.tcp,
-					    tsigkey))
+				if (!ssu_checkall(db, ver, name, ssutable,
+						  client->inner.signer,
+						  &netaddr, env,
+						  client->inner.tcp, tsigkey))
 				{
 					FAILC(DNS_R_REFUSED,
 					      "rejected by secure update");
@@ -2141,7 +2136,7 @@ check_mx(ns_client_t *client, dns_zone_t *zone, dns_db_t *db,
 }

 static isc_result_t
-rr_exists(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
+rr_exists(dns_db_t *db, dns_dbversion_t *ver, const dns_name_t *name,
 	  const dns_rdata_t *rdata, bool *flag) {
 	dns_rdataset_t rdataset;
 	dns_dbnode_t *node = NULL;
@@ -2696,22 +2691,23 @@ update_action(void *arg) {
 	 * Check prerequisites.
 	 */

-	MSG_SECTION_FOREACH(request, DNS_SECTION_PREREQUISITE, name) {
+	MSG_SECTION_FOREACH(request, DNS_SECTION_PREREQUISITE, linkedname) {
 		dns_rdata_t rdata = DNS_RDATA_INIT;
 		dns_ttl_t ttl;
 		dns_rdataclass_t update_class;
+		const dns_name_t *name = dns_linkedname_name(linkedname);
 		bool flag;

-		get_current_rr(name, &rdata, &covers, &ttl, &update_class);
+		get_current_rr(linkedname, &rdata, &covers, &ttl,
+			       &update_class);

 		if (ttl != 0) {
 			PREREQFAILC(DNS_R_FORMERR,
 				    "prerequisite TTL is not zero");
 		}

-		if (!dns_name_issubdomain(dns_linkedname_name(name), zonename))
-		{
-			PREREQFAILN(DNS_R_NOTZONE, dns_linkedname_name(name),
+		if (!dns_name_issubdomain(name, zonename)) {
+			PREREQFAILN(DNS_R_NOTZONE, name,
 				    "prerequisite name is out of zone");
 		}

@@ -2722,26 +2718,20 @@ update_action(void *arg) {
 					    "not empty");
 			}
 			if (rdata.type == dns_rdatatype_any) {
-				CHECK(name_exists(db, ver,
-						  dns_linkedname_name(name),
-						  &flag));
+				CHECK(name_exists(db, ver, name, &flag));
 				if (!flag) {
 					PREREQFAILN(
-						DNS_R_NXDOMAIN,
-						dns_linkedname_name(name),
+						DNS_R_NXDOMAIN, name,
 						"'name in use' prerequisite "
 						"not satisfied");
 				}
 			} else {
-				CHECK(rrset_exists(db, ver,
-						   dns_linkedname_name(name),
-						   rdata.type, covers, &flag));
+				CHECK(rrset_exists(db, ver, name, rdata.type,
+						   covers, &flag));
 				if (!flag) {
 					/* RRset does not exist. */
 					PREREQFAILNT(
-						DNS_R_NXRRSET,
-						dns_linkedname_name(name),
-						rdata.type,
+						DNS_R_NXRRSET, name, rdata.type,
 						"'rrset exists (value "
 						"independent)' prerequisite "
 						"not satisfied");
@@ -2754,33 +2744,27 @@ update_action(void *arg) {
 					    "not empty");
 			}
 			if (rdata.type == dns_rdatatype_any) {
-				CHECK(name_exists(db, ver,
-						  dns_linkedname_name(name),
-						  &flag));
+				CHECK(name_exists(db, ver, name, &flag));
 				if (flag) {
 					PREREQFAILN(
-						DNS_R_YXDOMAIN,
-						dns_linkedname_name(name),
+						DNS_R_YXDOMAIN, name,
 						"'name not in use' "
 						"prerequisite not satisfied");
 				}
 			} else {
-				CHECK(rrset_exists(db, ver,
-						   dns_linkedname_name(name),
-						   rdata.type, covers, &flag));
+				CHECK(rrset_exists(db, ver, name, rdata.type,
+						   covers, &flag));
 				if (flag) {
 					/* RRset exists. */
 					PREREQFAILNT(
-						DNS_R_YXRRSET,
-						dns_linkedname_name(name),
-						rdata.type,
+						DNS_R_YXRRSET, name, rdata.type,
 						"'rrset does not exist' "
 						"prerequisite not satisfied");
 				}
 			}
 		} else if (update_class == dns_rdataclass_in) {
 			/* "temp<rr.name, rr.type> += rr;" */
-			temp_append(&temp, dns_linkedname_name(name), &rdata);
+			temp_append(&temp, name, &rdata);
 		} else {
 			PREREQFAILC(DNS_R_FORMERR, "malformed prerequisite");
 		}
@@ -2820,16 +2804,18 @@ update_action(void *arg) {
 	INSIST(ssutable == NULL || maxbytype != NULL);

 	update = 0;
-	MSG_SECTION_FOREACH(request, DNS_SECTION_UPDATE, name) {
+	MSG_SECTION_FOREACH(request, DNS_SECTION_UPDATE, linkedname) {
 		dns_rdata_t rdata = DNS_RDATA_INIT;
 		dns_ttl_t ttl;
 		dns_rdataclass_t update_class;
+		const dns_name_t *name = dns_linkedname_name(linkedname);
 		bool flag;
 		size_t maxidx = update++;

 		INSIST(ssutable == NULL || maxidx < maxbytypelen);

-		get_current_rr(name, &rdata, &covers, &ttl, &update_class);
+		get_current_rr(linkedname, &rdata, &covers, &ttl,
+			       &update_class);

 		if (update_class == dns_rdataclass_in) {
 			/*
@@ -2849,7 +2835,7 @@ update_action(void *arg) {
 			}
 			if ((rdata.type == dns_rdatatype_ns ||
 			     rdata.type == dns_rdatatype_dname) &&
-			    dns_name_iswildcard(dns_linkedname_name(name)))
+			    dns_name_iswildcard(name))
 			{
 				char typebuf[DNS_RDATATYPE_FORMATSIZE];

@@ -2863,8 +2849,7 @@ update_action(void *arg) {
 			}
 			if (rdata.type == dns_rdatatype_cname) {
 				CHECK(cname_incompatible_rrset_exists(
-					db, ver, dns_linkedname_name(name),
-					&flag));
+					db, ver, name, &flag));
 				if (flag) {
 					update_log(
 						client, zone, LOGLEVEL_PROTOCOL,
@@ -2873,8 +2858,7 @@ update_action(void *arg) {
 					continue;
 				}
 			} else {
-				CHECK(rrset_exists(db, ver,
-						   dns_linkedname_name(name),
+				CHECK(rrset_exists(db, ver, name,
 						   dns_rdatatype_cname,
 						   dns_rdatatype_none, &flag));
 				if (flag && !dns_rdatatype_atcname(rdata.type))
@@ -2888,8 +2872,7 @@ update_action(void *arg) {
 			}
 			if (rdata.type == dns_rdatatype_soa) {
 				bool ok;
-				CHECK(rrset_exists(db, ver,
-						   dns_linkedname_name(name),
+				CHECK(rrset_exists(db, ver, name,
 						   dns_rdatatype_soa,
 						   dns_rdatatype_none, &flag));
 				if (!flag) {
@@ -2913,7 +2896,7 @@ update_action(void *arg) {
 			}

 			if (dns_rdatatype_atparent(rdata.type) &&
-			    dns_name_equal(dns_linkedname_name(name), zonename))
+			    dns_name_equal(name, zonename))
 			{
 				char typebuf[DNS_RDATATYPE_FORMATSIZE];

@@ -2951,12 +2934,10 @@ update_action(void *arg) {
 			}

 			if ((options & DNS_ZONEOPT_CHECKWILDCARD) != 0 &&
-			    dns_name_internalwildcard(
-				    dns_linkedname_name(name)))
+			    dns_name_internalwildcard(name))
 			{
 				char namestr[DNS_NAME_FORMATSIZE];
-				dns_name_format(dns_linkedname_name(name),
-						namestr, sizeof(namestr));
+				dns_name_format(name, namestr, sizeof(namestr));
 				update_log(client, zone, LOGLEVEL_PROTOCOL,
 					   "warning: ownername '%s' contains a "
 					   "non-terminal wildcard",
@@ -2977,10 +2958,8 @@ update_action(void *arg) {

 			if (maxbytype != NULL && maxbytype[maxidx] != 0) {
 				unsigned int count = 0;
-				CHECK(foreach_rr(db, ver,
-						 dns_linkedname_name(name),
-						 rdata.type, covers,
-						 count_action, &count));
+				CHECK(foreach_rr(db, ver, name, rdata.type,
+						 covers, count_action, &count));
 				if (count >= maxbytype[maxidx]) {
 					update_log(client, zone,
 						   LOGLEVEL_PROTOCOL,
@@ -3000,8 +2979,7 @@ update_action(void *arg) {
 				int len = 0;
 				const char *truncated = "";

-				dns_name_format(dns_linkedname_name(name),
-						namestr, sizeof(namestr));
+				dns_name_format(name, namestr, sizeof(namestr));
 				dns_rdatatype_format(rdata.type, typestr,
 						     sizeof(typestr));
 				isc_buffer_init(&buf, rdstr, sizeof(rdstr));
@@ -3031,17 +3009,16 @@ update_action(void *arg) {
 				ctx.db = db;
 				ctx.ver = ver;
 				ctx.diff = &diff;
-				ctx.name = dns_linkedname_name(name);
-				ctx.oldname = dns_linkedname_name(name);
+				ctx.name = name;
+				ctx.oldname = dns_linkedname_name(linkedname);
 				ctx.update_rr = &rdata;
 				ctx.update_rr_ttl = ttl;
 				ctx.ignore_add = false;
 				dns_diff_init(mctx, &ctx.del_diff);
 				dns_diff_init(mctx, &ctx.add_diff);
-				CHECK(foreach_rr(db, ver,
-						 dns_linkedname_name(name),
-						 rdata.type, covers,
-						 add_rr_prepare_action, &ctx));
+				CHECK(foreach_rr(db, ver, name, rdata.type,
+						 covers, add_rr_prepare_action,
+						 &ctx));

 				if (ctx.ignore_add) {
 					dns_diff_clear(&ctx.del_diff);
@@ -3061,8 +3038,7 @@ update_action(void *arg) {
 					}
 					result = update_one_rr(
 						db, ver, &diff, DNS_DIFFOP_ADD,
-						dns_linkedname_name(name), ttl,
-						&rdata);
+						name, ttl, &rdata);
 					if (result != ISC_R_SUCCESS) {
 						update_log(client, zone,
 							   LOGLEVEL_PROTOCOL,
@@ -3078,48 +3054,39 @@ update_action(void *arg) {
 			if (rdata.type == dns_rdatatype_any) {
 				if (isc_log_wouldlog(LOGLEVEL_PROTOCOL)) {
 					char namestr[DNS_NAME_FORMATSIZE];
-					dns_name_format(
-						dns_linkedname_name(name),
-						namestr, sizeof(namestr));
+					dns_name_format(name, namestr,
+							sizeof(namestr));
 					update_log(client, zone,
 						   LOGLEVEL_PROTOCOL,
 						   "delete all rrsets from "
 						   "name '%s'",
 						   namestr);
 				}
-				if (dns_name_equal(dns_linkedname_name(name),
-						   zonename))
-				{
+				if (dns_name_equal(name, zonename)) {
 					CHECK(delete_if(
 						apex_special_processing_any,
-						zone, db, ver,
-						dns_linkedname_name(name),
+						zone, db, ver, name,
 						dns_rdatatype_any,
 						dns_rdatatype_none, &rdata,
 						&diff));
 				} else {
-					CHECK(delete_if(
-						type_not_dnssec, zone, db, ver,
-						dns_linkedname_name(name),
-						dns_rdatatype_any,
-						dns_rdatatype_none, &rdata,
-						&diff));
+					CHECK(delete_if(type_not_dnssec, zone,
+							db, ver, name,
+							dns_rdatatype_any,
+							dns_rdatatype_none,
+							&rdata, &diff));
 				}
-			} else if (dns_name_equal(dns_linkedname_name(name),
-						  zonename))
-			{
+			} else if (dns_name_equal(name, zonename)) {
 				CHECK(delete_if(
 					apex_special_processing, zone, db, ver,
-					dns_linkedname_name(name),
-					dns_rdatatype_any, dns_rdatatype_none,
-					&rdata, &diff));
+					name, dns_rdatatype_any,
+					dns_rdatatype_none, &rdata, &diff));
 			} else {
 				if (isc_log_wouldlog(LOGLEVEL_PROTOCOL)) {
 					char namestr[DNS_NAME_FORMATSIZE];
 					char typestr[DNS_RDATATYPE_FORMATSIZE];
-					dns_name_format(
-						dns_linkedname_name(name),
-						namestr, sizeof(namestr));
+					dns_name_format(name, namestr,
+							sizeof(namestr));
 					dns_rdatatype_format(rdata.type,
 							     typestr,
 							     sizeof(typestr));
@@ -3128,8 +3095,7 @@ update_action(void *arg) {
 						   "deleting rrset at '%s' %s",
 						   namestr, typestr);
 				}
-				CHECK(delete_if(true_p, zone, db, ver,
-						dns_linkedname_name(name),
+				CHECK(delete_if(true_p, zone, db, ver, name,
 						rdata.type, covers, &rdata,
 						&diff));
 			}
@@ -3141,8 +3107,7 @@ update_action(void *arg) {
 			 * The (name == zonename) condition appears in
 			 * RFC2136 3.4.2.4 but is missing from the pseudocode.
 			 */
-			if (dns_name_equal(dns_linkedname_name(name), zonename))
-			{
+			if (dns_name_equal(name, zonename)) {
 				if (rdata.type == dns_rdatatype_soa) {
 					update_log(client, zone,
 						   LOGLEVEL_PROTOCOL,
@@ -3153,9 +3118,7 @@ update_action(void *arg) {
 				if (rdata.type == dns_rdatatype_ns) {
 					int count;
 					CHECK(rr_count(
-						db, ver,
-						dns_linkedname_name(name),
-						dns_rdatatype_ns,
+						db, ver, name, dns_rdatatype_ns,
 						dns_rdatatype_none, &count));
 					if (count == 1) {
 						update_log(client, zone,
@@ -3189,15 +3152,13 @@ update_action(void *arg) {
 					}
 				}
 			}
-			dns_name_format(dns_linkedname_name(name), namestr,
-					sizeof(namestr));
+			dns_name_format(name, namestr, sizeof(namestr));
 			dns_rdatatype_format(rdata.type, typestr,
 					     sizeof(typestr));
 			update_log(client, zone, LOGLEVEL_PROTOCOL,
 				   "deleting an RR at %s %s", namestr, typestr);
-			CHECK(delete_if(rr_equal_p, zone, db, ver,
-					dns_linkedname_name(name), rdata.type,
-					covers, &rdata, &diff));
+			CHECK(delete_if(rr_equal_p, zone, db, ver, name,
+					rdata.type, covers, &rdata, &diff));
 		}
 	}

diff --git a/lib/ns/xfrout.c b/lib/ns/xfrout.c
index 3676cb1067..b7373fe5f0 100644
--- a/lib/ns/xfrout.c
+++ b/lib/ns/xfrout.c
@@ -713,7 +713,8 @@ xfrout_delayed_timeout(void *arg, isc_result_t result);
 void
 ns_xfr_start(ns_client_t *client, dns_rdatatype_t reqtype) {
 	isc_result_t result;
-	dns_linkedname_t *question_name;
+	dns_linkedname_t *question_name_wl;
+	dns_name_t *question_name;
 	dns_rdataset_t *question_rdataset;
 	dns_zone_t *zone = NULL, *raw = NULL, *mayberaw;
 	dns_db_t *db = NULL;
@@ -766,20 +767,21 @@ ns_xfr_start(ns_client_t *client, dns_rdatatype_t reqtype) {
 	 * The question section must contain exactly one question, and
 	 * it must be for AXFR/IXFR as appropriate.
 	 */
-	question_name = ISC_LIST_HEAD(request->sections[DNS_SECTION_QUESTION]);
-	question_rdataset = ISC_LIST_HEAD(question_name->list);
+	question_name_wl =
+		ISC_LIST_HEAD(request->sections[DNS_SECTION_QUESTION]);
+	question_name = dns_linkedname_name(question_name_wl);
+	question_rdataset = ISC_LIST_HEAD(question_name_wl->list);
 	question_class = question_rdataset->rdclass;
 	INSIST(question_rdataset->type == reqtype);
 	if (ISC_LIST_NEXT(question_rdataset, link) != NULL) {
 		FAILC(DNS_R_FORMERR, "multiple questions");
 	}

-	if (ISC_LIST_NEXT(question_name, link) != NULL) {
+	if (ISC_LIST_NEXT(question_name_wl, link) != NULL) {
 		FAILC(DNS_R_FORMERR, "multiple questions");
 	}

-	result = dns_view_findzone(client->inner.view,
-				   dns_linkedname_name(question_name),
+	result = dns_view_findzone(client->inner.view, question_name,
 				   DNS_ZTFIND_EXACT, &zone);
 	if (result != ISC_R_SUCCESS || dns_zone_gettype(zone) == dns_zone_dlz) {
 		/*
@@ -789,8 +791,7 @@ ns_xfr_start(ns_client_t *client, dns_rdatatype_t reqtype) {
 		 */
 		if (!ISC_LIST_EMPTY(client->inner.view->dlz_searched)) {
 			result = dns_dlzallowzonexfr(
-				client->inner.view,
-				dns_linkedname_name(question_name),
+				client->inner.view, question_name,
 				&client->inner.peeraddr, &db);
 			if (result == ISC_R_DEFAULT) {
 				useviewacl = true;
@@ -845,8 +846,8 @@ ns_xfr_start(ns_client_t *client, dns_rdatatype_t reqtype) {
 		dns_db_currentversion(db, &ver);
 	}

-	xfrout_log1(client, dns_linkedname_name(question_name), question_class,
-		    ISC_LOG_DEBUG(6), "%s question section OK", mnemonic);
+	xfrout_log1(client, question_name, question_class, ISC_LOG_DEBUG(6),
+		    "%s question section OK", mnemonic);

 	/*
 	 * Check the authority section.  Look for a SOA record with
@@ -889,8 +890,8 @@ got_soa:
 		CHECK(result);
 	}

-	xfrout_log1(client, dns_linkedname_name(question_name), question_class,
-		    ISC_LOG_DEBUG(6), "%s authority section OK", mnemonic);
+	xfrout_log1(client, question_name, question_class, ISC_LOG_DEBUG(6),
+		    "%s authority section OK", mnemonic);

 	/*
 	 * If not a DLZ zone or we are falling back to the view's transfer
@@ -899,8 +900,7 @@ got_soa:
 	if (!is_dlz || useviewacl) {
 		dns_acl_t *acl;

-		ns_client_aclmsg("zone transfer",
-				 dns_linkedname_name(question_name), reqtype,
+		ns_client_aclmsg("zone transfer", question_name, reqtype,
 				 client->inner.view->rdclass, msg, sizeof(msg));
 		if (useviewacl) {
 			acl = client->inner.view->transferacl;
@@ -997,8 +997,7 @@ got_soa:
 							      &provide_ixfr);
 			}
 			if (!provide_ixfr) {
-				xfrout_log1(client,
-					    dns_linkedname_name(question_name),
+				xfrout_log1(client, question_name,
 					    question_class, ISC_LOG_DEBUG(4),
 					    "IXFR delta response disabled due "
 					    "to 'provide-ixfr no;' being set");
@@ -1016,8 +1015,8 @@ got_soa:
 			result = ISC_R_NOTFOUND;
 		}
 		if (result == ISC_R_NOTFOUND || result == ISC_R_RANGE) {
-			xfrout_log1(client, dns_linkedname_name(question_name),
-				    question_class, ISC_LOG_INFO,
+			xfrout_log1(client, question_name, question_class,
+				    ISC_LOG_INFO,
 				    "IXFR version not in journal, "
 				    "falling back to AXFR (serial %u)",
 				    begin_serial);
@@ -1032,8 +1031,7 @@ got_soa:
 			if (ratio != 0 && ((100 * jsize) / dbsize) > ratio) {
 				data_stream->methods->destroy(&data_stream);
 				data_stream = NULL;
-				xfrout_log1(client,
-					    dns_linkedname_name(question_name),
+				xfrout_log1(client, question_name,
 					    question_class, ISC_LOG_INFO,
 					    "IXFR delta size (%zu bytes) "
 					    "exceeds the maximum ratio to "
@@ -1044,8 +1042,7 @@ got_soa:
 				mnemonic = "AXFR-style IXFR";
 				goto axfr_fallback;
 			} else {
-				xfrout_log1(client,
-					    dns_linkedname_name(question_name),
+				xfrout_log1(client, question_name,
 					    question_class, ISC_LOG_DEBUG(4),
 					    "IXFR delta size (%zu bytes); "
 					    "database size "
@@ -1076,17 +1073,15 @@ have_stream:
 	 */

 	if (is_dlz) {
-		xfrout_ctx_create(mctx, client, request->id,
-				  dns_linkedname_name(question_name), reqtype,
-				  question_class, zone, db, ver, stream,
-				  dns_message_gettsigkey(request), tsigbuf,
-				  request->verified_sig, 3600, 3600,
+		xfrout_ctx_create(mctx, client, request->id, question_name,
+				  reqtype, question_class, zone, db, ver,
+				  stream, dns_message_gettsigkey(request),
+				  tsigbuf, request->verified_sig, 3600, 3600,
 				  (format == dns_many_answers) ? true : false,
 				  &xfr);
 	} else {
 		xfrout_ctx_create(
-			mctx, client, request->id,
-			dns_linkedname_name(question_name), reqtype,
+			mctx, client, request->id, question_name, reqtype,
 			question_class, zone, db, ver, stream,
 			dns_message_gettsigkey(request), tsigbuf,
 			request->verified_sig, dns_zone_getmaxxfrout(zone),
@@ -1108,19 +1103,16 @@ have_stream:
 	xfr->poll = is_poll;
 	if (is_poll) {
 		xfr->mnemonic = "IXFR poll response";
-		xfrout_log1(client, dns_linkedname_name(question_name),
-			    question_class, ISC_LOG_DEBUG(1),
-			    "IXFR poll up to date%s%s",
+		xfrout_log1(client, question_name, question_class,
+			    ISC_LOG_DEBUG(1), "IXFR poll up to date%s%s",
 			    (xfr->tsigkey != NULL) ? ": TSIG " : "", keyname);
 	} else if (is_ixfr) {
-		xfrout_log1(client, dns_linkedname_name(question_name),
-			    question_class, ISC_LOG_INFO,
+		xfrout_log1(client, question_name, question_class, ISC_LOG_INFO,
 			    "%s started%s%s (serial %u -> %u)", mnemonic,
 			    (xfr->tsigkey != NULL) ? ": TSIG " : "", keyname,
 			    begin_serial, current_serial);
 	} else {
-		xfrout_log1(client, dns_linkedname_name(question_name),
-			    question_class, ISC_LOG_INFO,
+		xfrout_log1(client, question_name, question_class, ISC_LOG_INFO,
 			    "%s started%s%s (serial %u)", mnemonic,
 			    (xfr->tsigkey != NULL) ? ": TSIG " : "", keyname,
 			    current_serial);