Index | Thread | Search

From:
Stuart Henderson <stu@spacehopper.org>
Subject:
nsd 4.15.0
To:
tech <tech@openbsd.org>
Date:
Tue, 7 Jul 2026 11:17:20 +0100

Download raw body.

Thread
  • Stuart Henderson:

    nsd 4.15.0

here's an update to NSD 4.15.0. diff is ordered as doc changes, code
changes, autogenerated crap (i.e. when you hit the generated autoconf
files bit there's nothing more of interest).

Index: doc/ChangeLog
===================================================================
RCS file: /cvs/src/usr.sbin/nsd/doc/ChangeLog,v
diff -u -p -r1.22 ChangeLog
--- doc/ChangeLog	26 Jun 2026 08:55:55 -0000	1.22
+++ doc/ChangeLog	7 Jul 2026 10:12:26 -0000
@@ -1,3 +1,48 @@
+29 June 2026: Jannik
+	- Merge #483 from ruuda: Improve Prometheus metrics: Move zonestats from
+	  metric name to label
+
+26 June 2026: Willem
+	- Fix nsd-control assoc_tsig, if that interrupts a zone transfer in
+	  progress, to not crash. It restarts the transfer from the primary.
+	  Thanks to Qifan Zhang, Palo Alto Networks, for the report.
+	- Fix nsd-control del_tsig, if that interrupts a zone transfer in
+	  progress, to not crash. It does not delete the key, if in use.
+	  Thanks to Qifan Zhang, Palo Alto Networks, for the report.
+	- Fix catalog producer zone with long name, so that it does not crash
+	  on that. Thanks to Qifan Zhang, Palo Alto Networks, for the report.
+	- Fix catalog consumer zone with long name for member unique label that
+	  is long, so that it does not crash on that.
+	  Thanks to Qifan Zhang, Palo Alto Networks, for the report.
+	- Fix that non-IN-class records cause a zone transfer to be rejected.
+	  Also such records are not added from a transfer. This stops an
+	  assertion failure.
+	  Thanks to Qifan Zhang, Palo Alto Networks, for the report.
+	- Fix to disallow a SOA record in the middle of an AXFR. This stops an
+	  assertion failure.
+	  Thanks to Qifan Zhang, Palo Alto Networks, for the report.
+	- Fix to set zone is_secure to false when IXFR removes RRSIG DNSKEY.
+	  This stops an assertion failure. Also fix soa and ns rrset change in
+	  IXFR when packed rrsets are disabled.
+	  Thanks to Qifan Zhang, Palo Alto Networks, for the report.
+	- Fix to handle NSEC3 zones without space for hashes. Zones with a apex
+	  domain name length >= 223 bytes, that have a NSEC3PARAM must not be
+	  prehashed, since the hashed owner name would not fit.
+	  Thanks Qifan Zhang, Palo Alto Networks, for the report
+	- Fix to add hardening to zone_ixfr_remove_oldest, for IXFR processing.
+	  Thanks to Qifan Zhang, Palo Alto Networks, for the report.
+	- Fix for xfrd crash with too short response to a UDP SOA query
+	  Only for release builds and only when configured for XFR over UDP
+	  Thanks to Qifan Zhang, Palo Alto Networks, for the report.
+	- Fix that out-of-zone records are skipped from zone transfers.
+	  Otherwise such records could stick around after zone deletion and
+	  cause failures for DS queries.
+	  Thanks to Qifan Zhang, Palo Alto Networks, for the report.
+
+25 June 2026: Willem
+	- Merge the NSD version 4.14.3 security release branch into master.
+	- Continue with 4.14.4 for development
+
 24 June 2026: Willem
 	- Fix for CVE-2026-12244: A specially crafted SVCB RR can cause a heap
 	  overflow of up to 65509 attacker controlled bytes.
@@ -19,6 +64,72 @@
 	  transferring over TCP.
 	  Thanks to Qifan Zhang, Palo Alto Networks for the report.
 	  https://www.nlnetlabs.nl/downloads/nsd/CVE-2026-12490.txt
+
+22 Jun 2026: Willem
+	- More robust removing of RRs from an IXFR processing.
+	  Thanks zhangph for reporting this issue
+
+22 Jun 2026: Wouter
+	- Fix unit test for stopmany for process role logs.
+
+22 Jun 2026: Willem
+	- Fix that wrong buffer position in IXFR for the first SOA causes the
+	  storage to retrieve wrong information. Later data would overwrite it
+	  so it did not cause observable trouble. Thanks to Tristan Madani
+	  (@TristanInSec) from Talence Security for the report.
+
+22 Jun 2026: Willem
+	- Fix notify and zone transfer processing for malformed SOA records,
+	  with a short rdata content. It stops an assertion failure. Thanks to
+	  Tristan Madani (@TristanInSec) from Talence Security for the report.
+
+19 Jun 2026: Wouter
+	- Fix to update github ci actions/checkout to v7.
+
+18 Jun 2026: Willem
+	- Fix overflow for NSEC3 zones with 255-octet name
+	  Thanks to Haruki Oyama (Waseda University) for the report, and
+	  Qifan Zhang, Palo Alto Networks, for also reporting this issue.
+
+15 Jun 2026: Willem
+	- Fix print of NXT RR without bitmap
+	  Thanks to Qifan Zhang, Palo Alto Networks, for the report.
+
+15 Jun 2026: Willem
+	- Fix to not fail on NSEC3 records with a bad owner name.
+	  Thanks to Qifan Zhang, Palo Alto Networks, for the report.
+
+15 Jun 2026: Willem
+	- Fix print of malformed HIP records.
+	  Thanks to Qifan Zhang, Palo Alto Networks, for the report, and
+	  Haruki Oyama (Waseda University) for also reporting this issue.
+
+15 Jun 2026: Willem
+	- Fix notify relay ipc to check for large size.
+	  This stops desync of the internal notify pipe.
+	  Thanks to Qifan Zhang, Palo Alto Networks for the report.
+
+15 Jun 2026: Willem
+	- Fix PROXYv2 header read and consume, it checks the header size.
+	  Thanks to Qifan Zhang, Palo Alto Networks for the report.
+
+12 May 2026: Jannik
+	- Merge #484 from orlitzky: OpenRC: fix network deps and support both
+	  supervisors
+
+24 April 2026: Jannik
+	- Merge #481 from jaredmauch: Fix pedantic/CodeQL warning in sources
+
+14 April 2026: Jannik
+	- Fix XDP cleanup code being executed even if xdp is not configured
+
+25 March 2026: Wouter
+	- Fix #478: Feature request: reduce syslog noise from frequent
+	  read-only control commands (e.g. stats_noreset). It logs the
+	  verbosity command always, and others at 2 and higher.
+
+19 March 2026: Jannik
+	- Continue with 4.14.3 for development
 
 11 March 2026: Wouter
 	- Fix in IXFR processing, to commit the collected RRs before
Index: doc/README
===================================================================
RCS file: /cvs/src/usr.sbin/nsd/doc/README,v
diff -u -p -r1.12 README
--- doc/README	26 Jun 2026 08:55:55 -0000	1.12
+++ doc/README	7 Jul 2026 10:12:26 -0000
@@ -21,7 +21,7 @@
 
 1.0 Introduction
 
-This is NSD Name Server Daemon (NSD) version 4.14.3.
+This is NSD Name Server Daemon (NSD) version 4.15.0.
 
 The NLnet Labs Name Server Daemon (NSD) is an authoritative RFC compliant 
 DNS nameserver. It was first conceived to allow for more genetic 
@@ -57,7 +57,7 @@ and uses a simple configuration file 'ns
 
 1.2 Quick build and install
 
-Step 1: Unpack the source with gtar -xzvf nsd-4.14.3.tar.gz
+Step 1: Unpack the source with gtar -xzvf nsd-4.15.0.tar.gz
 
 Step 2: Create user nsd or any other unprivileged user of your
         choice. In case of later make sure to use
@@ -111,9 +111,9 @@ Step 11: If desired add 'nsd-control wri
 Use your favorite combination of tar and gnu zip to unpack the source,
 for example
 
-$ gtar -xzvf nsd-4.14.3.tar.gz
+$ gtar -xzvf nsd-4.15.0.tar.gz
 
-will unpack the source into the ./nsd-4.14.3 directory...
+will unpack the source into the ./nsd-4.15.0 directory...
 
 
 2.2 Configuring NSD
Index: nsd.conf.5.in
===================================================================
RCS file: /cvs/src/usr.sbin/nsd/nsd.conf.5.in,v
diff -u -p -r1.56 nsd.conf.5.in
--- nsd.conf.5.in	26 Jun 2026 08:55:55 -0000	1.56
+++ nsd.conf.5.in	7 Jul 2026 10:12:26 -0000
@@ -1,4 +1,4 @@
-.TH "nsd.conf" "5" "jun 24, 2026" "NLnet Labs" "nsd 4.14.3"
+.TH "nsd.conf" "5" "jul  7, 2026" "NLnet Labs" "nsd 4.15.0"
 .\" Copyright (c) 2001\-2024, NLnet Labs. All rights reserved.
 .\" See LICENSE for the license.
 .SH "NAME"
@@ -690,14 +690,21 @@ can help with drivers with broken AF_XDP
 .TP
 .B metrics\-enable:\fR <yes or no>
 Enable the prometheus metrics HTTP endpoint. It exposes the same statistics as
-the \fInsd\-control\fR(8) stats_noreset command, but with metric names
+the \fInsd\-control stats_noreset\fR command, but with metric names
 following the prometheus specification. (Requires libevent2)
 
-To generate per zone metrics, specify the \fBzonestats\fR option on the desired
-zones.
-
-Beware, that when using \fInsd\-control\fR(8) stats (instead of stats_noreset),
-the statistics will be reset for the HTTP metrics endpoint as well.
+To generate metrics per zone (or more accurately, per zonestats group),
+specify the \fBzonestats\fR option on the desired zones. This will expose the
+zonestats metrics with the zonestats name as a label called "zone", for
+example with \fBzonestats: examplezone\fR:
+.sp
+.nf
+	nsd_zonestats_queries_total{zone="examplezone"}
+.fi
+.sp
+Beware, that when using \fInsd\-control stats\fR (instead of \fInsd\-control
+stats_noreset\fR), the statistics will be reset for the HTTP metrics endpoint
+as well.
 .TP
 .B metrics\-interface:\fR <ip4 or ip6 | interface name>
 NSD will bind to the listed addresses or interfaces to serve the prometheus
Index: doc/RELNOTES
===================================================================
RCS file: /cvs/src/usr.sbin/nsd/doc/RELNOTES,v
diff -u -p -r1.20 RELNOTES
--- doc/RELNOTES	26 Jun 2026 08:55:55 -0000	1.20
+++ doc/RELNOTES	7 Jul 2026 10:12:26 -0000
@@ -1,5 +1,80 @@
 NSD RELEASE NOTES
 
+4.15.0
+================
+FEATURES:
+	- Merge #483 from ruuda: Improve Prometheus metrics: Move zonestats from
+	  metric name to label
+BUG FIXES:
+	- Fix #478: Feature request: reduce syslog noise from frequent
+	  read-only control commands (e.g. stats_noreset). It logs the
+	  verbosity command always, and others at 2 and higher.
+	- Fix XDP cleanup code being executed even if xdp is not configured
+	- Merge #481 from jaredmauch: Fix pedantic/CodeQL warning in sources
+	- Merge #484 from orlitzky: OpenRC: fix network deps and support both
+	  supervisors
+	- Fix PROXYv2 header read and consume, it checks the header size.
+	  Thanks to Qifan Zhang, Palo Alto Networks for the report.
+	- Fix notify relay ipc to check for large size.
+	  This stops desync of the internal notify pipe.
+	  Thanks to Qifan Zhang, Palo Alto Networks for the report.
+	- Fix print of malformed HIP records.
+	  Thanks to Qifan Zhang, Palo Alto Networks, for the report, and
+	  Haruki Oyama (Waseda University) for also reporting this issue.
+	- Fix to not fail on NSEC3 records with a bad owner name.
+	  Thanks to Qifan Zhang, Palo Alto Networks, for the report.
+	- Fix print of NXT RR without bitmap
+	  Thanks to Qifan Zhang, Palo Alto Networks, for the report.
+	- Fix overflow for NSEC3 zones with 255-octet name
+	  Thanks to Haruki Oyama (Waseda University) for the report, and
+	  Qifan Zhang, Palo Alto Networks, for also reporting this issue.
+	- Fix to update github ci actions/checkout to v7.
+	- Fix notify and zone transfer processing for malformed SOA records,
+	  with a short rdata content. It stops an assertion failure. Thanks to
+	  Tristan Madani (@TristanInSec) from Talence Security for the report.
+	- Fix that wrong buffer position in IXFR for the first SOA causes the
+	  storage to retrieve wrong information. Later data would overwrite it
+	  so it did not cause observable trouble. Thanks to Tristan Madani
+	  (@TristanInSec) from Talence Security for the report.
+	- More robust removing of RRs from an IXFR processing.
+	  Thanks zhangph for reporting this issue
+	- Fix unit test for stopmany for process role logs.
+	- Fix nsd-control assoc_tsig, if that interrupts a zone transfer in
+	  progress, to not crash. It restarts the transfer from the primary.
+	  Thanks to Qifan Zhang, Palo Alto Networks, for the report.
+	- Fix nsd-control del_tsig, if that interrupts a zone transfer in
+	  progress, to not crash. It does not delete the key, if in use.
+	  Thanks to Qifan Zhang, Palo Alto Networks, for the report.
+	- Fix catalog producer zone with long name, so that it does not crash
+	  on that. Thanks to Qifan Zhang, Palo Alto Networks, for the report.
+	- Fix catalog consumer zone with long name for member unique label that
+	  is long, so that it does not crash on that.
+	  Thanks to Qifan Zhang, Palo Alto Networks, for the report.
+	- Fix that non-IN-class records cause a zone transfer to be rejected.
+	  Also such records are not added from a transfer. This stops an
+	  assertion failure.
+	  Thanks to Qifan Zhang, Palo Alto Networks, for the report.
+	- Fix to disallow a SOA record in the middle of an AXFR. This stops an
+	  assertion failure.
+	  Thanks to Qifan Zhang, Palo Alto Networks, for the report.
+	- Fix to set zone is_secure to false when IXFR removes RRSIG DNSKEY.
+	  This stops an assertion failure. Also fix soa and ns rrset change in
+	  IXFR when packed rrsets are disabled.
+	  Thanks to Qifan Zhang, Palo Alto Networks, for the report.
+	- Fix to handle NSEC3 zones without space for hashes. Zones with a apex
+	  domain name length >= 223 bytes, that have a NSEC3PARAM must not be
+	  prehashed, since the hashed owner name would not fit.
+	  Thanks Qifan Zhang, Palo Alto Networks, for the report
+	- Fix to add hardening to zone_ixfr_remove_oldest, for IXFR processing.
+	  Thanks to Qifan Zhang, Palo Alto Networks, for the report.
+	- Fix for xfrd crash with too short response to a UDP SOA query
+	  Only for release builds and only when configured for XFR over UDP
+	  Thanks to Qifan Zhang, Palo Alto Networks, for the report.
+	- Fix that out-of-zone records are skipped from zone transfers.
+	  Otherwise such records could stick around after zone deletion and
+	  cause failures for DS queries.
+	  Thanks to Qifan Zhang, Palo Alto Networks, for the report.
+
 4.14.3
 ================
 FEATURES:
Index: simdzone/CHANGELOG.md
===================================================================
RCS file: /cvs/src/usr.sbin/nsd/simdzone/CHANGELOG.md,v
diff -u -p -r1.1.1.3 CHANGELOG.md
--- simdzone/CHANGELOG.md	21 Mar 2026 21:34:33 -0000	1.1.1.3
+++ simdzone/CHANGELOG.md	7 Jul 2026 10:12:26 -0000
@@ -5,6 +5,16 @@ All notable changes to simdzone will be 
 The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0),
 and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
 
+## [0.2.5] - 2026-07-07
+
+### Added
+
+- Add riscv fallback detection (#261)
+
+### Fixed
+
+- Fix to parse SVCB and HTTPS svcparam ech=0.
+
 ## [0.2.4] - 2025-12-04
 
 ### Added
Index: simdzone/README.md
===================================================================
RCS file: /cvs/src/usr.sbin/nsd/simdzone/README.md,v
diff -u -p -r1.1.1.1 README.md
--- simdzone/README.md	3 Sep 2025 18:44:23 -0000	1.1.1.1
+++ simdzone/README.md	7 Jul 2026 10:12:26 -0000
@@ -1,6 +1,7 @@
 ![Build Status](https://github.com/NLnetLabs/simdzone/actions/workflows/build-test.yml/badge.svg)
 [![Coverity Status](https://scan.coverity.com/projects/27509/badge.svg)](https://scan.coverity.com/projects/nlnetlabs-simdzone)
-[![Mastodon Follow](https://img.shields.io/mastodon/follow/109262826617293067?domain=https%3A%2F%2Ffosstodon.org&style=social)](https://fosstodon.org/@nlnetlabs)
+[![Discuss on Discourse](https://img.shields.io/badge/Discourse-NLnet_Labs-orange?logo=Discourse)](https://community.nlnetlabs.nl/c/dns-libraries-tools/12)
+[![Mastodon Follow](https://img.shields.io/mastodon/follow/114692612288811644?domain=social.nlnetlabs.nl&style=social)](https://social.nlnetlabs.nl/@nlnetlabs)
 
 # simdzone: Parsing zone files really fast
 
@@ -33,7 +34,7 @@ instructions for parsing structured text
 simdzone, whose name is a play on [simdjson][simdjson], aims to achieve a
 similar performance boost for parsing zone data.
 
-> Currently SSE4.2 and AVX2 are supported, a fallback is used otherwise.
+> Currently SSE4.2 and AVX2 are supported. RISC-V and other non-x86_64 targets use the fallback kernel until a dedicated SIMD backend is added.
 
 > simdzone copies some code from the [simdjson][simdjson] project, with
 > permission to use and distribute it under the terms of
Index: README.md
===================================================================
RCS file: /cvs/src/usr.sbin/nsd/README.md,v
diff -u -p -r1.4 README.md
--- README.md	21 Mar 2026 21:36:36 -0000	1.4
+++ README.md	7 Jul 2026 10:12:26 -0000
@@ -11,8 +11,7 @@ It has been developed for operations in 
 reliability, stability and security are of high importance.  If you
 have any feedback, we would love to hear from you. Don’t hesitate to
 [create an issue on Github](https://github.com/NLnetLabs/nsd/issues/new)
-or post a message on the
-[NSD mailing list](https://lists.nlnetlabs.nl/mailman/listinfo/nsd-users).
+or post a message on our [community forum](https://community.nlnetlabs.nl/).
 You can learn more about NSD by reading our
 [documentation](https://nsd.docs.nlnetlabs.nl/).
 
Index: axfr.c
===================================================================
RCS file: /cvs/src/usr.sbin/nsd/axfr.c,v
diff -u -p -r1.25 axfr.c
--- axfr.c	21 Mar 2026 21:36:36 -0000	1.25
+++ axfr.c	7 Jul 2026 10:12:26 -0000
@@ -79,7 +79,12 @@ query_axfr(struct nsd *nsd, struct query
 
 		query_add_compression_domain(query, qdomain, QHEADERSZ);
 
-		assert(query->axfr_zone->soa_rrset->rr_count == 1);
+		if(query->axfr_zone->soa_rrset->rr_count != 1) {
+			VERBOSITY(2, (LOG_INFO, "axfr: zone %s soa rr count %u (expected 1), servfail for AXFR-out", domain_to_string(query->axfr_zone->apex),
+			(unsigned)query->axfr_zone->soa_rrset->rr_count));
+			RCODE_SET(query->packet, RCODE_SERVFAIL);
+			return QUERY_PROCESSED;
+		}
 		added = packet_encode_rr(query,
 					 query->axfr_zone->apex,
 					 query->axfr_zone->soa_rrset->rrs[0],
@@ -151,7 +156,6 @@ query_axfr(struct nsd *nsd, struct query
 	}
 
 	/* Add terminating SOA RR.  */
-	assert(query->axfr_zone->soa_rrset->rr_count == 1);
 	added = packet_encode_rr(query,
 				 query->axfr_zone->apex,
 				 query->axfr_zone->soa_rrset->rrs[0],
Index: configure.ac
===================================================================
RCS file: /cvs/src/usr.sbin/nsd/configure.ac,v
diff -u -p -r1.64 configure.ac
--- configure.ac	26 Jun 2026 08:55:55 -0000	1.64
+++ configure.ac	7 Jul 2026 10:12:26 -0000
@@ -7,7 +7,7 @@ sinclude(dnstap/dnstap.m4)
 
 # autoconf-2.70 is needed for @runstatedir@
 AC_PREREQ([2.70])
-AC_INIT([NSD],[4.14.3],[https://github.com/NLnetLabs/nsd/issues or nsd-bugs@nlnetlabs.nl])
+AC_INIT([NSD],[4.15.0],[https://github.com/NLnetLabs/nsd/issues or nsd-bugs@nlnetlabs.nl])
 AC_CONFIG_HEADERS([config.h])
 
 #
Index: convert-release-notes.sh
===================================================================
RCS file: /cvs/src/usr.sbin/nsd/convert-release-notes.sh,v
diff -u -p -r1.1.1.1 convert-release-notes.sh
--- convert-release-notes.sh	21 Mar 2026 21:34:33 -0000	1.1.1.1
+++ convert-release-notes.sh	7 Jul 2026 10:12:26 -0000
@@ -48,11 +48,6 @@ error_too_many_args() {
 }
 
 extract_release_notes() {
-    # Find latest version if VERSION was not specified
-    if [[ -z "$VERSION" ]]; then
-        VERSION=$(grep -E -m1 -B1 "^=====+$" <"$RELNOTES_FILE" | head -n1)
-    fi
-
     sed -E -e "/^$VERSION/{ n; n; bfound }; d; bend" \
         -e ':found; /\n=====+$/bstrip_trailer; N; bfound' \
         -e ':strip_trailer; s/\n+([0-9]+\.[0-9]+\.[0-9]+)\n=====+$//' \
@@ -191,6 +186,11 @@ if ! [[ -f "$RELNOTES_FILE" ]]; then
 fi
 
 #### Generate text ####
+
+# Find latest version if VERSION was not specified
+if [[ -z "$VERSION" ]]; then
+    VERSION=$(grep -E -m1 -B1 "^=====+$" <"$RELNOTES_FILE" | head -n1)
+fi
 
 if [[ "$PRINT_EMAIL" == true ]]; then
     SHA256=""
Index: difffile.c
===================================================================
RCS file: /cvs/src/usr.sbin/nsd/difffile.c,v
diff -u -p -r1.25 difffile.c
--- difffile.c	21 Mar 2026 21:36:36 -0000	1.25
+++ difffile.c	7 Jul 2026 10:12:26 -0000
@@ -711,6 +711,16 @@ delete_RR(namedb_type* db, const dname_t
 	rrset_type* rrset_prev;
 #endif
 	const nsd_type_descriptor_type *descriptor = nsd_type_descriptor(type);
+	if (!dname_is_subdomain(dname, domain_dname(zone->apex))) {
+		char zname[MAXDOMAINLEN * 5];
+		domain_to_string_buf(zone->apex, zname);
+		VERBOSITY(2, (LOG_WARNING,
+			"out-of-zone record deletion in transfer for zone %s: "
+			"owner %s is outside zone; skipping",
+			zname, dname_to_string(dname, NULL)));
+		buffer_skip(packet, rdatalen);
+		return 1;
+	}
 	domain = domain_table_find(db->domains, dname);
 	if(!domain) {
 		log_msg(LOG_WARNING, "diff: domain %s does not exist",
@@ -735,6 +745,7 @@ delete_RR(namedb_type* db, const dname_t
 		domain_table_type *temptable;
 		int32_t rrnum, code;
 		struct rr *rr;
+		int was_rrsig_dnskey = 0;
 		temptable = domain_table_create(temp_region);
 		/* This will ensure that the dnames in rdata are
 		 * normalized, conform RFC 4035, section 6.2
@@ -745,6 +756,7 @@ delete_RR(namedb_type* db, const dname_t
 				"%s %s %s", dname_to_string(dname,0),
 				rrtype_to_string(type),
 				read_rdata_fail_str(code));
+			return 0;
 		}
 		rr->owner = domain;
 		rr->type = type;
@@ -773,6 +785,10 @@ delete_RR(namedb_type* db, const dname_t
 		/* process triggers for RR deletions */
 		nsec3_delete_rr_trigger(db, rrset->rrs[rrnum], zone);
 #endif
+		if(domain == zone->apex && type == TYPE_RRSIG &&
+			rr_rrsig_type_covered(rrset->rrs[rrnum])==TYPE_DNSKEY)
+			was_rrsig_dnskey = 1;
+
 		/* lower usage (possibly deleting other domains, and thus
 		 * invalidating the current RR's domain pointers) */
 		rr_lower_usage(db, rrset->rrs[rrnum]);
@@ -822,6 +838,8 @@ delete_RR(namedb_type* db, const dname_t
 			region_recycle(db->region, rrset_orig,
 				sizeof(rrset_type) +
 				rrset_orig->rr_count*sizeof(rr_type*));
+#endif /* PACKED_STRUCTS */
+			rrset->rr_count --;
 			if(domain == zone->apex) {
 				/* Because the rrset struct is reallocated,
 				 * a pointer to it may need to be set again. */
@@ -829,10 +847,23 @@ delete_RR(namedb_type* db, const dname_t
 					zone->soa_rrset = rrset;
 				} else if(type == TYPE_NS) {
 					zone->ns_rrset = rrset;
+				} else if(type == TYPE_RRSIG
+					&& was_rrsig_dnskey) {
+					/* See if the zone is still signed */
+					unsigned i;
+					int has_dnskey_rrsig = 0;
+					for (i = 0; i < rrset->rr_count; i++) {
+						if(rr_rrsig_type_covered(
+							rrset->rrs[i])==
+							TYPE_DNSKEY){
+							has_dnskey_rrsig = 1;
+							break;
+						}
+					}
+					if(!has_dnskey_rrsig)
+						zone->is_secure = 0;
 				}
 			}
-#endif /* PACKED_STRUCTS */
-			rrset->rr_count --;
 #ifdef NSEC3
 			/* for type nsec3, the domain may have become a
 			 * 'normal' domain with its remaining data now */
@@ -973,6 +1004,16 @@ add_RR(namedb_type* db, const dname_type
 		commit_RRset(db, zone, &collect_rrs2);
 		return 1;
 	}
+	if (!dname_is_subdomain(dname, domain_dname(zone->apex))) {
+		char zname[MAXDOMAINLEN * 5];
+		domain_to_string_buf(zone->apex, zname);
+		VERBOSITY(2, (LOG_WARNING,
+			"out-of-zone record in transfer for zone %s: "
+			"owner %s is outside zone; skipping",
+			zname, dname_to_string(dname, NULL)));
+		buffer_skip(packet, rdatalen);
+		return 1;
+	}
 	domain = domain_table_insert(db->domains, dname);
 	assert(domain);
 	if (domain != collect_rrs->domain || type != collect_rrs->type
@@ -1275,6 +1316,14 @@ apply_ixfr(nsd_type* nsd, FILE *in, uint
 			region_destroy(region);
 			return 0;
 		}
+		if (klass != CLASS_IN) {
+			log_msg(LOG_ERR, "bad xfr non-IN-class RR %s %s %s",
+				dname_to_string(owner,0),
+				rrclass_to_string(klass),
+				rrtype_to_string(type));
+			region_destroy(region);
+			return 0;
+		}
 
 		DEBUG(DEBUG_XFRD,2, (LOG_INFO, "diff: %s parsed count %d, ax %d, delmode %d",
 			domain_to_string(zone->apex), *rr_count, *is_axfr, *delete_mode));
@@ -1299,11 +1348,6 @@ apply_ixfr(nsd_type* nsd, FILE *in, uint
 			if (*rr_count == 0) {
 				assert(!*is_axfr);
 				assert(!*delete_mode);
-				if (klass != CLASS_IN) {
-					log_msg(LOG_ERR, "first RR not SOA IN");
-					region_destroy(region);
-					return 0;
-				}
 				if(dname_compare(domain_dname(zone->apex), owner) != 0) {
 					log_msg(LOG_ERR, "SOA dname not equal to zone %s",
 						domain_to_string(zone->apex));
@@ -1316,10 +1360,9 @@ apply_ixfr(nsd_type* nsd, FILE *in, uint
 					region_destroy(region);
 					return 0;
 				}
-				buffer_skip(packet, rrlen);
-
 				if(ixfr_store)
 					ixfr_store_add_newsoa(ixfr_store, ttl, packet, rrlen);
+				buffer_skip(packet, rrlen);
 
 				continue;
 			} else if (*rr_count == 1) {
@@ -1364,6 +1407,14 @@ apply_ixfr(nsd_type* nsd, FILE *in, uint
 				   just before soa - so it gets deleted and added too */
 				DEBUG(DEBUG_XFRD,2, (LOG_INFO, "diff: %s IXFRswapdel count %d, ax %d, delmode %d",
 					domain_to_string(zone->apex), *rr_count, *is_axfr, *delete_mode));
+			} else if(*is_axfr) {
+				if(!(seq_nr == seq_total-1 && i == ancount-1)) {
+					/* AXFR mode: a SOA at rr_count>=2
+					 * should not exist. Skip it rather
+					 * than passing it to add_RR. */
+					buffer_skip(packet, rrlen);
+					continue;
+				}
 			}
 		} else {
 			if (*rr_count == 0) {
@@ -2079,7 +2130,15 @@ task_process_add_zone(struct nsd* nsd, u
 		return;
 	}
 	/* create zone */
+#ifdef NSEC3
+	nsec3_superzone_clear_for_apex(nsd->db, zdname);
+#endif
 	z = find_or_create_zone(nsd->db, zdname, nsd->options, zname, pname);
+#ifdef NSEC3
+	/* If no z, it reinstates the content, if z created, it creates
+	 * the content around the new zone apex (created with zone create). */
+	nsec3_superzone_precompile_for_apex(nsd->db, zdname);
+#endif
 	if(!z) {
 		region_recycle(nsd->db->region, (void*)zdname,
 			dname_total_size(zdname));
@@ -2108,6 +2167,7 @@ task_process_del_zone(struct nsd* nsd, s
 		return;
 
 #ifdef NSEC3
+	nsec3_superzone_clear_for_apex(nsd->db, task->zname);
 	nsec3_clear_precompile(nsd->db, zone);
 	zone->nsec3_param = NULL;
 #endif
@@ -2116,6 +2176,9 @@ task_process_del_zone(struct nsd* nsd, s
 	/* remove from zonetree, apex, soa */
 	zopt = zone->opts;
 	namedb_zone_delete(nsd->db, zone);
+#ifdef NSEC3
+	nsec3_superzone_precompile_for_apex(nsd->db, task->zname);
+#endif
 	/* remove from options (zone_list already edited by xfrd) */
 	zone_options_delete(nsd->options, zopt);
 }
Index: difffile.h
===================================================================
RCS file: /cvs/src/usr.sbin/nsd/difffile.h,v
diff -u -p -r1.8 difffile.h
--- difffile.h	21 Mar 2026 21:36:36 -0000	1.8
+++ difffile.h	7 Jul 2026 10:12:26 -0000
@@ -125,7 +125,7 @@ struct task_list_d {
 	uint32_t oldserial, newserial;
 	/** general variable.  for some used to see if zname is present. */
 	uint64_t yesno;
-	struct dname zname[0];
+	struct dname zname[];
 };
 #define TASKLIST(ptr) ((struct task_list_d*)UDB_PTR(ptr))
 /** create udb for tasks */
Index: dname.c
===================================================================
RCS file: /cvs/src/usr.sbin/nsd/dname.c,v
diff -u -p -r1.18 dname.c
--- dname.c	21 Mar 2026 21:36:36 -0000	1.18
+++ dname.c	7 Jul 2026 10:12:26 -0000
@@ -470,7 +470,8 @@ dname_concatenate(region_type *region,
 {
 	uint8_t temp[MAXDOMAINLEN];
 
-	assert(left->name_size + right->name_size - 1 <= MAXDOMAINLEN);
+	if(left->name_size + right->name_size - 1 > MAXDOMAINLEN)
+		return NULL;
 
 	memcpy(temp, dname_name(left), left->name_size - 1);
 	memcpy(temp + left->name_size - 1, dname_name(right), right->name_size);
Index: ixfr.c
===================================================================
RCS file: /cvs/src/usr.sbin/nsd/ixfr.c,v
diff -u -p -r1.6 ixfr.c
--- ixfr.c	21 Mar 2026 21:36:36 -0000	1.6
+++ ixfr.c	7 Jul 2026 10:12:26 -0000
@@ -567,6 +567,7 @@ static struct ixfr_data* ixfr_data_prev(
 	struct ixfr_data* cur, size_t* prevcount)
 {
 	struct ixfr_data* prev;
+	int wrapped = 0;
 	if(!cur || cur == (struct ixfr_data*)RBTREE_NULL)
 		return NULL;
 	if(cur->oldserial == ixfr->oldest_serial)
@@ -600,6 +601,11 @@ static struct ixfr_data* ixfr_data_prev(
 			/* We hit the first element in the tree, go again
 			 * at the last one. Wrap around. */
 			prev = (struct ixfr_data*)rbtree_last(ixfr->data);
+			if(wrapped) {
+				/* The lookup wrapped again, this is a loop. */
+				return NULL;
+			}
+			wrapped = 1;
 		}
 	}
 	/* no elements in list */
@@ -611,8 +617,11 @@ static int connect_ixfrs(struct zone_ixf
 	uint32_t* end_serial)
 {
 	struct ixfr_data* p = data;
+	size_t count = 0;
 	while(p != NULL) {
 		struct ixfr_data* next = ixfr_data_next(ixfr, p);
+		if(count++ > ixfr->data->count + 12)
+			return 0; /* loop */
 		if(next) {
 			if(p->newserial != next->oldserial) {
 				/* These ixfrs are not connected,
@@ -1074,7 +1083,8 @@ void ixfr_store_finish(struct ixfr_store
 		ixfr_store_free(ixfr_store);
 		return;
 	}
-	zone_ixfr_add(ixfr_store->zone->ixfr, ixfr_store->data, 1);
+	zone_ixfr_add(ixfr_store->zone->ixfr, ixfr_store->data, 1,
+		ixfr_store->zone->opts->name);
 	ixfr_store->data = NULL;
 
 	/* free structure */
@@ -1180,6 +1190,12 @@ void ixfr_store_add_newsoa(struct ixfr_s
 	}
 	rdlen_uncompressed = primns_len + email_len + 4 + 4 + 4 + 4 + 4;
 
+	if(ixfr_store->data->oldsoa && ixfr_store->data->oldserial == serial) {
+		log_msg(LOG_ERR, "ixfr_store newsoa: duplicate serial number");
+		ixfr_store_cancel(ixfr_store);
+		buffer_set_position(packet, oldpos);
+		return;
+	}
 	ixfr_store->data->newserial = serial;
 
 	/* store the soa record */
@@ -1234,6 +1250,12 @@ void ixfr_store_add_oldsoa(struct ixfr_s
 	}
 	rdlen_uncompressed = primns_len + email_len + 4 + 4 + 4 + 4 + 4;
 
+	if(ixfr_store->data->newsoa && ixfr_store->data->newserial == serial) {
+		log_msg(LOG_ERR, "ixfr_store oldsoa: duplicate serial number");
+		ixfr_store_cancel(ixfr_store);
+		buffer_set_position(packet, oldpos);
+		return;
+	}
 	ixfr_store->data->oldserial = serial;
 
 	/* store the soa record */
@@ -1524,6 +1546,8 @@ static void zone_ixfr_remove_oldest(stru
 {
 	if(ixfr->data->count > 0) {
 		struct ixfr_data* oldest = ixfr_data_first(ixfr);
+		if(!oldest)
+			return; /* oldest_serial is stale, skip eviction */
 		if(ixfr->oldest_serial == oldest->oldserial) {
 			if(ixfr->data->count > 1) {
 				struct ixfr_data* next = ixfr_data_next(ixfr, oldest);
@@ -1589,10 +1613,20 @@ void zone_ixfr_remove(struct zone_ixfr* 
 	ixfr_data_free(data);
 }
 
-void zone_ixfr_add(struct zone_ixfr* ixfr, struct ixfr_data* data, int isnew)
+void zone_ixfr_add(struct zone_ixfr* ixfr, struct ixfr_data* data, int isnew,
+	const char* zname)
 {
 	memset(&data->node, 0, sizeof(data->node));
-	if(ixfr->data->count == 0) {
+	data->node.key = &data->oldserial;
+	if(rbtree_insert(ixfr->data, &data->node) == NULL) {
+		/* duplicate oldserial in IXFR stream - reject the chunk. */
+		log_msg(LOG_WARNING, "zone %s: chunk with duplicate "
+			"oldserial=%u discarded; broken journal chain prevented",
+			(zname?zname:"<unknown>"), (unsigned)data->oldserial);
+		ixfr_data_free(data);
+		return;
+	}
+	if(ixfr->data->count == 1) {
 		ixfr->oldest_serial = data->oldserial;
 		ixfr->newest_serial = data->oldserial;
 	} else if(isnew) {
@@ -1602,8 +1636,6 @@ void zone_ixfr_add(struct zone_ixfr* ixf
 		/* added older entry, before the others */
 		ixfr->oldest_serial = data->oldserial;
 	}
-	data->node.key = &data->oldserial;
-	rbtree_insert(ixfr->data, &data->node);
 	ixfr->total_size += ixfr_data_size(data);
 }
 
@@ -1844,7 +1876,7 @@ static int ixfr_rename_files(struct zone
 	int dest_num_files)
 {
 	struct ixfr_data* data, *startspot = NULL;
-	size_t prevcount = 0;
+	size_t prevcount = 0, count = 0;
 	int destnum;
 	if(!zone->ixfr || !zone->ixfr->data)
 		return 1;
@@ -1883,6 +1915,11 @@ static int ixfr_rename_files(struct zone
 		 * has been renamed to a temporary name */
 		startspot = data;
 		data = ixfr_data_next(zone->ixfr, data);
+		if(count++ > zone->ixfr->data->count+12) {
+			/* loop */
+			ixfr_delete_rest_files(zone, data, zfile, 1);
+			return 0;
+		}
 		destnum--;
 	}
 
@@ -2555,6 +2592,7 @@ static int ixfr_data_read(struct nsd* ns
 	const char* ixfrfile, uint32_t* dest_serial, int file_num)
 {
 	struct ixfr_data_state state = { 0 };
+	size_t ixfr_data_sz;
 
 	if(!zone->apex) {
 		return 0;
@@ -2634,9 +2672,11 @@ static int ixfr_data_read(struct nsd* ns
 		ixfr_data_free(state.data);
 		return 0;
 	}
-	zone_ixfr_add(zone->ixfr, state.data, 0);
+	ixfr_data_sz = ixfr_data_size(state.data); /* pick up size before
+		possible deletion of the item */
+	zone_ixfr_add(zone->ixfr, state.data, 0, zone->opts->name);
 	VERBOSITY(3, (LOG_INFO, "zone %s read %s IXFR data of %u bytes",
-		zone->opts->name, ixfrfile, (unsigned)ixfr_data_size(state.data)));
+		zone->opts->name, ixfrfile, (unsigned)ixfr_data_sz));
 	return 1;
 }
 
Index: ixfr.h
===================================================================
RCS file: /cvs/src/usr.sbin/nsd/ixfr.h,v
diff -u -p -r1.4 ixfr.h
--- ixfr.h	21 Mar 2026 21:36:36 -0000	1.4
+++ ixfr.h	7 Jul 2026 10:12:26 -0000
@@ -215,7 +215,8 @@ void zone_ixfr_make_space(struct zone_ix
 void zone_ixfr_remove(struct zone_ixfr* ixfr, struct ixfr_data* data);
 
 /* add ixfr data to the zone_ixfr */
-void zone_ixfr_add(struct zone_ixfr* ixfr, struct ixfr_data* data, int isnew);
+void zone_ixfr_add(struct zone_ixfr* ixfr, struct ixfr_data* data, int isnew,
+	const char* zname);
 
 /* find serial number in ixfr list, or NULL if not found */
 struct ixfr_data* zone_ixfr_find_serial(struct zone_ixfr* ixfr,
Index: metrics.c
===================================================================
RCS file: /cvs/src/usr.sbin/nsd/metrics.c,v
diff -u -p -r1.1.1.2 metrics.c
--- metrics.c	21 Mar 2026 21:34:32 -0000	1.1.1.2
+++ metrics.c	7 Jul 2026 10:12:26 -0000
@@ -349,49 +349,88 @@ metrics_http_callback(struct evhttp_requ
 }
 
 #ifdef BIND8_STATS
-/** Change disallowed characters, '.' ':' to underscores '_'. */
+#define METRIC_MAX_LABELS 2
+
+struct metrics_metric {
+	const char *prefix;
+	const char *name;
+	const char *type;
+	size_t label_count;
+	const char *label_names[METRIC_MAX_LABELS];
+	const char *label_values[METRIC_MAX_LABELS];
+};
+
 static void
-change_string_underscores(char* prefix)
-{
-	/* Prometheus does not want '.' in the metric names. But the zone
-	 * statistics could have then in their name.
-	 * Also ':' is not allowed. This routine enforeces that it
-	 * has letters,digits,underscores. */
-	char* s = prefix;
-	while(*s) {
-		if(!isalnum((unsigned char)*s) && *s != '_')
-			*s = '_';
-		s++;
-	}
+metric_init_with_prefix(struct metrics_metric *metric, const char *prefix) {
+	metric->prefix = prefix;
+	metric->name = "";
+	metric->label_count = 0;
 }
 
-/** print long number*/
-static int
-print_longnum(struct evbuffer *buf, char* desc, uint64_t x)
-{
-	if(x > (uint64_t)1024*1024*1024) {
-		/*more than a Gb*/
-		size_t front = (size_t)(x / (uint64_t)1000000);
-		size_t back = (size_t)(x % (uint64_t)1000000);
-		return evbuffer_add_printf(buf, "%s%lu%6.6lu\n", desc,
-			(unsigned long)front, (unsigned long)back);
+static void
+metric_set_name_and_type(struct metrics_metric *metric, const char *name, const char *type) {
+	metric->name = name;
+	metric->type = type;
+}
+
+/* Add a `name="value"` label to the metric.
+ * The value must not contain `\`, `\n`, or `"`. */
+static void
+metric_push_label(struct metrics_metric *metric, const char *name, const char *value) {
+	assert(metric->label_count < METRIC_MAX_LABELS);
+	metric->label_names[metric->label_count] = name;
+	metric->label_values[metric->label_count] = value;
+	metric->label_count++;
+}
+
+static void
+metric_pop_label(struct metrics_metric *metric) {
+	assert(metric->label_count > 0);
+	metric->label_count--;
+}
+
+static void
+metric_print(struct metrics_metric *metric, struct evbuffer *buf, uint64_t value) {
+	evbuffer_add_printf(buf, "%s%s", metric->prefix, metric->name);
+	for (size_t i = 0; i < metric->label_count; i++) {
+		evbuffer_add_printf(buf, "%c%s=\"%s\"",
+			i == 0 ? '{' : ',',
+			metric->label_names[i],
+			metric->label_values[i]);
+	}
+	if (metric->label_count > 0) {
+		evbuffer_add_printf(buf, "} %" PRIu64 "\n", value);
 	} else {
-		return evbuffer_add_printf(buf, "%s%lu\n", desc, (unsigned long)x);
+		evbuffer_add_printf(buf, " %" PRIu64 "\n", value);
 	}
 }
 
+/** Print a metric value of `integral + decimals_micro * 1e-6`. */
 static void
-print_metric_help_and_type(struct evbuffer *buf, char *prefix, char *name,
-						   char *help, char *type)
+metric_print_micros(struct metrics_metric *metric, struct evbuffer *buf,
+	unsigned long integral, unsigned long decimals_micro)
 {
+	assert(metric->label_count == 0
+		&& "metric_print_micros is not implemented for metrics with labels");
+	evbuffer_add_printf(buf, "%s%s %lu.%6.6lu\n",
+		metric->prefix, metric->name, integral, decimals_micro);
+}
+
+static void
+metric_print_pop(struct metrics_metric *metric, struct evbuffer *buf, uint64_t value) {
+	metric_print(metric, buf, value);
+	metric_pop_label(metric);
+}
+
+static void
+metric_print_help(struct metrics_metric *metric, struct evbuffer *buf, const char *help) {
 	evbuffer_add_printf(buf, "# HELP %s%s %s\n# TYPE %s%s %s\n",
-	                    prefix, name, help, prefix, name, type);
+		metric->prefix, metric->name, help,
+		metric->prefix, metric->name, metric->type);
 }
 
 static void
-print_stat_block(struct evbuffer *buf, struct nsdst* st,
-                  char *name)
-{
+print_stat_block(struct evbuffer *buf, struct nsdst* st, struct metrics_metric *metric) {
 	size_t i;
 
 	const char* rcstr[] = {"NOERROR", "FORMERR", "SERVFAIL", "NXDOMAIN",
@@ -400,141 +439,139 @@ print_stat_block(struct evbuffer *buf, s
 		"BADVERS"
 	};
 
-	char prefix[512] = {0};
-	if (name) {
-		snprintf(prefix, sizeof(prefix), "nsd_zonestats_%s_", name);
-		change_string_underscores(prefix);
-	} else {
-		snprintf(prefix, sizeof(prefix), "nsd_");
-	}
-
 	/* nsd_queries_by_type_total */
-	print_metric_help_and_type(buf, prefix, "queries_by_type_total",
-	                           "Total number of queries received by type.",
-	                           "counter");
+	metric_set_name_and_type(metric, "queries_by_type_total", "counter");
+	metric_print_help(metric, buf, "Total number of queries received by type.");
 	for(i=0; i<= 255; i++) {
 		if(metrics_inhibit_zero && st->qtype[i] == 0 &&
 			strncmp(rrtype_to_string(i), "TYPE", 4) == 0)
 			continue;
-		evbuffer_add_printf(buf, "%squeries_by_type_total{type=\"%s\"} %lu\n",
-			prefix, rrtype_to_string(i), (unsigned long)st->qtype[i]);
+		metric_push_label(metric, "type", rrtype_to_string(i));
+		metric_print_pop(metric, buf, (uint64_t)st->qtype[i]);
 	}
 
 	/* nsd_queries_by_class_total */
-	print_metric_help_and_type(buf, prefix, "queries_by_class_total",
-	                           "Total number of queries received by class.",
-	                           "counter");
+	metric_set_name_and_type(metric, "queries_by_class_total", "counter");
+	metric_print_help(metric, buf, "Total number of queries received by class.");
 	for(i=0; i<4; i++) {
 		if(metrics_inhibit_zero && st->qclass[i] == 0 && i != CLASS_IN)
 			continue;
-		evbuffer_add_printf(buf, "%squeries_by_class_total{class=\"%s\"} %lu\n",
-			prefix, rrclass_to_string(i), (unsigned long)st->qclass[i]);
+		metric_push_label(metric, "class", rrclass_to_string(i));
+		metric_print_pop(metric, buf, (uint64_t)st->qclass[i]);
 	}
 
 	/* nsd_queries_by_opcode_total */
-	print_metric_help_and_type(buf, prefix, "queries_by_opcode_total",
-	                           "Total number of queries received by opcode.",
-	                           "counter");
+	metric_set_name_and_type(metric, "queries_by_opcode_total", "counter");
+	metric_print_help(metric, buf, "Total number of queries received by opcode.");
 	for(i=0; i<6; i++) {
 		if(metrics_inhibit_zero && st->opcode[i] == 0 && i != OPCODE_QUERY)
 			continue;
-		evbuffer_add_printf(buf, "%squeries_by_opcode_total{opcode=\"%s\"} %lu\n",
-			prefix, opcode2str(i), (unsigned long)st->opcode[i]);
+		metric_push_label(metric, "opcode", opcode2str(i));
+		metric_print_pop(metric, buf, (uint64_t)st->opcode[i]);
 	}
 
 	/* nsd_queries_by_rcode_total */
-	print_metric_help_and_type(buf, prefix, "queries_by_rcode_total",
-	                           "Total number of queries received by rcode.",
-	                           "counter");
+	metric_set_name_and_type(metric, "queries_by_rcode_total", "counter");
+	metric_print_help(metric, buf, "Total number of queries received by rcode.");
 	for(i=0; i<17; i++) {
 		if(metrics_inhibit_zero && st->rcode[i] == 0 &&
 			i > RCODE_YXDOMAIN) /*NSD does not use larger*/
 			continue;
-		evbuffer_add_printf(buf, "%squeries_by_rcode_total{rcode=\"%s\"} %lu\n",
-			prefix, rcstr[i], (unsigned long)st->rcode[i]);
+		metric_push_label(metric, "rcode", rcstr[i]);
+		metric_print_pop(metric, buf, (uint64_t)st->rcode[i]);
 	}
 
 	/* nsd_queries_by_transport_total */
-	print_metric_help_and_type(buf, prefix, "queries_by_transport_total",
-		"Total number of queries received by transport.",
-		"counter");
-	evbuffer_add_printf(buf, "%squeries_by_transport_total{transport=\"udp\"} %lu\n", prefix, (unsigned long)st->qudp);
-	evbuffer_add_printf(buf, "%squeries_by_transport_total{transport=\"udp6\"} %lu\n", prefix, (unsigned long)st->qudp6);
+	metric_set_name_and_type(metric, "queries_by_transport_total", "counter");
+	metric_print_help(metric, buf, "Total number of queries received by transport.");
+	metric_push_label(metric, "transport", "udp");
+	metric_print_pop(metric, buf, (uint64_t)st->qudp);
+	metric_push_label(metric, "transport", "udp6");
+	metric_print_pop(metric, buf, (uint64_t)st->qudp6);
 
 	/* nsd_queries_with_edns_total */
-	print_metric_help_and_type(buf, prefix, "queries_with_edns_total",
-		"Total number of queries received with EDNS OPT.",
-		"counter");
-	evbuffer_add_printf(buf, "%squeries_with_edns_total %lu\n", prefix, (unsigned long)st->edns);
+	metric_set_name_and_type(metric, "queries_with_edns_total", "counter");
+	metric_print_help(metric, buf, "Total number of queries received with EDNS OPT.");
+	metric_print(metric, buf, (uint64_t)st->edns);
 
 	/* nsd_queries_with_edns_failed_total */
-	print_metric_help_and_type(buf, prefix, "queries_with_edns_failed_total",
-		"Total number of queries received with EDNS OPT where EDNS parsing failed.",
-		"counter");
-	evbuffer_add_printf(buf, "%squeries_with_edns_failed_total %lu\n", prefix, (unsigned long)st->ednserr);
+	metric_set_name_and_type(metric, "queries_with_edns_failed_total", "counter");
+	metric_print_help(metric, buf, "Total number of queries received with EDNS OPT where EDNS parsing failed.");
+	metric_print(metric, buf, (uint64_t)st->ednserr);
 
 	/* nsd_connections_total */
-	print_metric_help_and_type(buf, prefix, "connections_total",
-		"Total number of connections.",
-		"counter");
-	evbuffer_add_printf(buf, "%sconnections_total{transport=\"tcp\"} %lu\n", prefix, (unsigned long)st->ctcp);
-	evbuffer_add_printf(buf, "%sconnections_total{transport=\"tcp6\"} %lu\n", prefix, (unsigned long)st->ctcp6);
-	evbuffer_add_printf(buf, "%sconnections_total{transport=\"tls\"} %lu\n", prefix, (unsigned long)st->ctls);
-	evbuffer_add_printf(buf, "%sconnections_total{transport=\"tls6\"} %lu\n", prefix, (unsigned long)st->ctls6);
+	metric_set_name_and_type(metric, "connections_total", "counter");
+	metric_print_help(metric, buf, "Total number of connections.");
+	metric_push_label(metric, "transport", "tcp");
+	metric_print_pop(metric, buf, (uint64_t)st->ctcp);
+	metric_push_label(metric, "transport", "tcp6");
+	metric_print_pop(metric, buf, (uint64_t)st->ctcp6);
+	metric_push_label(metric, "transport", "tls");
+	metric_print_pop(metric, buf, (uint64_t)st->ctls);
+	metric_push_label(metric, "transport", "tls6");
+	metric_print_pop(metric, buf, (uint64_t)st->ctls6);
 
 	/* nsd_xfr_requests_served_total */
-	print_metric_help_and_type(buf, prefix, "xfr_requests_served_total",
-		"Total number of answered zone transfers.",
-		"counter");
-	evbuffer_add_printf(buf, "%sxfr_requests_served_total{xfrtype=\"AXFR\"} %lu\n", prefix, (unsigned long)st->raxfr);
-	evbuffer_add_printf(buf, "%sxfr_requests_served_total{xfrtype=\"IXFR\"} %lu\n", prefix, (unsigned long)st->rixfr);
+	metric_set_name_and_type(metric, "xfr_requests_served_total", "counter");
+	metric_print_help(metric, buf, "Total number of answered zone transfers.");
+	metric_push_label(metric, "xfrtype", "AXFR");
+	metric_print_pop(metric, buf, (uint64_t)st->raxfr);
+	metric_push_label(metric, "xfrtype", "IXFR");
+	metric_print_pop(metric, buf, (uint64_t)st->rixfr);
 
 	/* nsd_queries_dropped_total */
-	print_metric_help_and_type(buf, prefix, "queries_dropped_total",
-		"Total number of dropped queries.",
-		"counter");
-	evbuffer_add_printf(buf, "%squeries_dropped_total %lu\n", prefix, (unsigned long)st->dropped);
+	metric_set_name_and_type(metric, "queries_dropped_total", "counter");
+	metric_print_help(metric, buf, "Total number of dropped queries.");
+	metric_print(metric, buf, (uint64_t)st->dropped);
 
 	/* nsd_queries_rx_failed_total */
-	print_metric_help_and_type(buf, prefix, "queries_rx_failed_total",
-		"Total number of queries where receive failed.",
-		"counter");
-	evbuffer_add_printf(buf, "%squeries_rx_failed_total %lu\n", prefix, (unsigned long)st->rxerr);
+	metric_set_name_and_type(metric, "queries_rx_failed_total", "counter");
+	metric_print_help(metric, buf, "Total number of queries where receive failed.");
+	metric_print(metric, buf, (uint64_t)st->rxerr);
 
 	/* nsd_answers_tx_failed_total */
-	print_metric_help_and_type(buf, prefix, "answers_tx_failed_total",
-		"Total number of answers where transmit failed.",
-		"counter");
-	evbuffer_add_printf(buf, "%sanswers_tx_failed_total %lu\n", prefix, (unsigned long)st->txerr);
+	metric_set_name_and_type(metric, "answers_tx_failed_total", "counter");
+	metric_print_help(metric, buf, "Total number of answers where transmit failed.");
+	metric_print(metric, buf, (uint64_t)st->txerr);
 
 	/* nsd_answers_without_aa_total */
-	print_metric_help_and_type(buf, prefix, "answers_without_aa_total",
-		"Total number of NOERROR answers without AA flag set.",
-		"counter");
-	evbuffer_add_printf(buf, "%sanswers_without_aa_total %lu\n", prefix, (unsigned long)st->nona);
+	metric_set_name_and_type(metric, "answers_without_aa_total", "counter");
+	metric_print_help(metric, buf, "Total number of NOERROR answers without AA flag set.");
+	metric_print(metric, buf, (uint64_t)st->nona);
 
 	/* nsd_answers_truncated_total */
-	print_metric_help_and_type(buf, prefix, "answers_truncated_total",
-		"Total number of truncated answers.",
-		"counter");
-	evbuffer_add_printf(buf, "%sanswers_truncated_total %lu\n", prefix, (unsigned long)st->truncated);
+	metric_set_name_and_type(metric, "answers_truncated_total", "counter");
+	metric_print_help(metric, buf, "Total number of truncated answers.");
+	metric_print(metric, buf, (uint64_t)st->truncated);
 }
 
 #ifdef USE_ZONE_STATS
+
 void
 metrics_zonestat_print_one(struct evbuffer *buf, char *name,
                            struct nsdst *zst)
 {
-	char prefix[512] = {0};
-	snprintf(prefix, sizeof(prefix), "nsd_zonestats_%s_", name);
-	change_string_underscores(prefix);
-
-	print_metric_help_and_type(buf, prefix, "queries_total",
-		"Total number of queries received.", "counter");
-	evbuffer_add_printf(buf, "%squeries_total %lu\n", prefix,
-		(unsigned long)(zst->qudp + zst->qudp6 + zst->ctcp +
+	char* name_valid;
+	struct metrics_metric metric;
+	metric_init_with_prefix(&metric, "nsd_zonestats_");
+
+	/* The zonestat name can contain characters like '"' that would break the
+	 * label value; replace them. */
+	name_valid = strdup(name);
+	if (!name_valid) {
+		log_msg(LOG_ERR, "malloc failure");
+		return;
+	}
+	metrics_make_label_value_valid(name_valid);
+	metric_push_label(&metric, "zone", name_valid);
+
+	metric_set_name_and_type(&metric, "queries_total", "counter");
+	metric_print_help(&metric, buf, "Total number of queries received.");
+	metric_print(&metric, buf,
+		(uint64_t)(zst->qudp + zst->qudp6 + zst->ctcp +
 			zst->ctcp6 + zst->ctls + zst->ctls6));
-	print_stat_block(buf, zst, name);
+	print_stat_block(buf, zst, &metric);
+	free(name_valid);
 }
 #endif /*USE_ZONE_STATS*/
 
@@ -545,23 +582,28 @@ metrics_print_stats(struct evbuffer *buf
 {
 	size_t i;
 	struct timeval elapsed, uptime;
+	struct metrics_metric metric;
+	char server_str[16] = {0};
+
+	metric_init_with_prefix(&metric, "nsd_");
 
 	/* nsd_queries_total */
-	print_metric_help_and_type(buf, "nsd_", "queries_total",
-	                           "Total number of queries received.", "counter");
+	metric_set_name_and_type(&metric, "queries_total", "counter");
+	metric_print_help(&metric, buf, "Total number of queries received.");
 	/*per CPU and total*/
 	for(i=0; i<xfrd->nsd->child_count; i++) {
-		evbuffer_add_printf(buf, "nsd_queries_total{server=\"%d\"} %lu\n",
-			(int)i, (unsigned long)xfrd->nsd->children[i].query_count);
+		sprintf(server_str, "%d", (int)i);
+		metric_push_label(&metric, "server", server_str);
+		metric_print_pop(&metric, buf, (uint64_t)xfrd->nsd->children[i].query_count);
 	}
 
-	print_stat_block(buf, st, NULL);
+	print_stat_block(buf, st, &metric);
 
 	/* uptime (in seconds) */
 	timeval_subtract(&uptime, now, &xfrd->nsd->metrics->boot_time);
-	print_metric_help_and_type(buf, "nsd_", "time_up_seconds_total",
-	                           "Uptime since server boot in seconds.", "counter");
-	evbuffer_add_printf(buf, "nsd_time_up_seconds_total %lu.%6.6lu\n",
+	metric_set_name_and_type(&metric, "time_up_seconds_total", "counter");
+	metric_print_help(&metric, buf, "Uptime since server boot in seconds.");
+	metric_print_micros(&metric, buf,
 		(unsigned long)uptime.tv_sec, (unsigned long)uptime.tv_usec);
 
 	/* time elapsed since last nsd-control stats reset (in seconds) */
@@ -572,48 +614,43 @@ metrics_print_stats(struct evbuffer *buf
 	} else {
 		timeval_subtract(&elapsed, now, &xfrd->nsd->metrics->stats_time);
 	}
-	print_metric_help_and_type(buf, "nsd_", "time_elapsed_seconds",
-	                           "Time since last statistics printout and "
-	                           "reset (by nsd-control stats) in seconds.",
-	                           "untyped");
-	evbuffer_add_printf(buf, "nsd_time_elapsed_seconds %lu.%6.6lu\n",
+	metric_set_name_and_type(&metric, "time_elapsed_seconds", "untyped");
+	metric_print_help(&metric, buf,
+		"Time since last statistics printout and "
+	        "reset (by nsd-control stats) in seconds.");
+	metric_print_micros(&metric, buf,
 		(unsigned long)elapsed.tv_sec, (unsigned long)elapsed.tv_usec);
 
 	/*mem info, database on disksize*/
-	print_metric_help_and_type(buf, "nsd_", "size_db_on_disk_bytes",
-	                           "Size of DNS database on disk.", "gauge");
-	print_longnum(buf, "nsd_size_db_on_disk_bytes ", st->db_disk);
-
-	print_metric_help_and_type(buf, "nsd_", "size_db_in_mem_bytes",
-	                           "Size of DNS database in memory.", "gauge");
-	print_longnum(buf, "nsd_size_db_in_mem_bytes ", st->db_mem);
-
-	print_metric_help_and_type(buf, "nsd_", "size_xfrd_in_mem_bytes",
-	                           "Size of zone transfers and notifies in xfrd process, excluding TSIG data.",
-	                           "gauge");
-	print_longnum(buf, "nsd_size_xfrd_in_mem_bytes ", region_get_mem(xfrd->region));
-
-	print_metric_help_and_type(buf, "nsd_", "size_config_on_disk_bytes",
-	                           "Size of zonelist file on disk, excluding nsd.conf.",
-	                           "gauge");
-	print_longnum(buf, "nsd_size_config_on_disk_bytes ",
-		xfrd->nsd->options->zonelist_off);
-
-	print_metric_help_and_type(buf, "nsd_", "size_config_in_mem_bytes",
-	                           "Size of config data in memory.", "gauge");
-	print_longnum(buf, "nsd_size_config_in_mem_bytes ", region_get_mem(
-		xfrd->nsd->options->region));
+	metric_set_name_and_type(&metric, "size_db_on_disk_bytes", "gauge");
+	metric_print_help(&metric, buf, "Size of DNS database on disk.");
+	metric_print(&metric, buf, st->db_disk);
+
+	metric_set_name_and_type(&metric, "size_db_in_mem_bytes", "gauge");
+	metric_print_help(&metric, buf, "Size of DNS database in memory.");
+	metric_print(&metric, buf, st->db_mem);
+
+	metric_set_name_and_type(&metric, "size_xfrd_in_mem_bytes", "gauge");
+	metric_print_help(&metric, buf, "Size of zone transfers and notifies in xfrd process, excluding TSIG data.");
+	metric_print(&metric, buf, region_get_mem(xfrd->region));
+
+	metric_set_name_and_type(&metric, "size_config_on_disk_bytes", "gauge");
+	metric_print_help(&metric, buf, "Size of zonelist file on disk, excluding nsd.conf.");
+	metric_print(&metric, buf, xfrd->nsd->options->zonelist_off);
+
+	metric_set_name_and_type(&metric, "size_config_in_mem_bytes", "gauge");
+	metric_print_help(&metric, buf, "Size of config data in memory.");
+	metric_print(&metric, buf, region_get_mem(xfrd->nsd->options->region));
 
 	/* number of zones serverd */
-	print_metric_help_and_type(buf, "nsd_", "zones_primary",
-	                           "Number of primary zones served.", "gauge");
-	evbuffer_add_printf(buf, "nsd_zones_primary %lu\n",
-		(unsigned long)(xfrd->notify_zones->count - xfrd->zones->count));
-
-	print_metric_help_and_type(buf, "nsd_", "zones_secondary",
-	                           "Number of secondary zones served.", "gauge");
-	evbuffer_add_printf(buf, "nsd_zones_secondary %lu\n",
-		(unsigned long)xfrd->zones->count);
+	metric_set_name_and_type(&metric, "zones_primary", "gauge");
+	metric_print_help(&metric, buf, "Number of primary zones served.");
+	metric_print(&metric, buf,
+		(uint64_t)(xfrd->notify_zones->count - xfrd->zones->count));
+
+	metric_set_name_and_type(&metric, "zones_secondary", "gauge");
+	metric_print_help(&metric, buf, "Number of secondary zones served.");
+	metric_print(&metric, buf, (uint64_t)xfrd->zones->count);
 
 #ifdef USE_ZONE_STATS
 	zonestat_print(NULL, buf, xfrd, clear, zonestats); /*per-zone statistics*/
Index: metrics.h
===================================================================
RCS file: /cvs/src/usr.sbin/nsd/metrics.h,v
diff -u -p -r1.1.1.1 metrics.h
--- metrics.h	6 Sep 2025 17:38:33 -0000	1.1.1.1
+++ metrics.h	7 Jul 2026 10:12:26 -0000
@@ -60,6 +60,7 @@ int daemon_metrics_open_ports(struct dae
 void daemon_metrics_attach(struct daemon_metrics* m, struct xfrd_state* xfrd);
 
 #ifdef BIND8_STATS
+
 /**
  * Print stats as prometheus metrics to HTTP buffer
  * @param buf: the HTTP buffer to write to
@@ -77,6 +78,35 @@ void metrics_print_stats(struct evbuffer
                          struct timeval *rc_stats_time);
 
 #ifdef USE_ZONE_STATS
+
+/**
+ * Replace characters disallowed in Prometheus label values with '_'.
+ *
+ * According to [1], label values can be any UTF-8 characters, but backslash,
+ * double-quote, and line feed must be escaped. We could escape them but that
+ * changes the length of the string, and in practice for zonestats names you
+ * don't need these characters anyway so we just replace them.
+ * [1]: https://prometheus.io/docs/instrumenting/exposition_formats/#comments-help-text-and-type-information>
+ *
+ * @param value: the label value to edit.
+ * @return 1 if any changes were needed, 0 if the value was already valid.
+ */
+static inline int metrics_make_label_value_valid(char* value) {
+	int made_changes = 0;
+	char* s = value;
+	while(*s) {
+		switch (*s) {
+			case '\\':
+			case '"':
+			case '\n':
+				*s = '_';
+				made_changes = 1;
+		}
+		s++;
+	}
+	return made_changes;
+}
+
 /**
  * Print zonestat metrics for a single zonestats object
  * @param buf: the HTTP buffer to write to
Index: namedb.c
===================================================================
RCS file: /cvs/src/usr.sbin/nsd/namedb.c,v
diff -u -p -r1.17 namedb.c
--- namedb.c	21 Mar 2026 21:36:36 -0000	1.17
+++ namedb.c	7 Jul 2026 10:12:26 -0000
@@ -226,20 +226,36 @@ do_deldomain(namedb_type* db, domain_typ
 
 	/* see if nsec3-nodes are used */
 	if(domain->nsec3) {
-		if(domain->nsec3->nsec3_node.key)
-			zone_del_domain_in_hash_tree(nsec3_tree_zone(db, domain)
-				->nsec3tree, &domain->nsec3->nsec3_node);
+		if(domain->nsec3->nsec3_node.key) {
+			zone_type* nsec3zone = nsec3_tree_zone(db, domain);
+			if(nsec3zone)
+				zone_del_domain_in_hash_tree(
+					nsec3zone->nsec3tree,
+					&domain->nsec3->nsec3_node);
+		}
 		if(domain->nsec3->hash_wc) {
-			if(domain->nsec3->hash_wc->hash.node.key)
-				zone_del_domain_in_hash_tree(nsec3_tree_zone(db, domain)
-					->hashtree, &domain->nsec3->hash_wc->hash.node);
-			if(domain->nsec3->hash_wc->wc.node.key)
-				zone_del_domain_in_hash_tree(nsec3_tree_zone(db, domain)
-					->wchashtree, &domain->nsec3->hash_wc->wc.node);
+			if(domain->nsec3->hash_wc->hash.node.key) {
+				zone_type* hzone = nsec3_tree_zone(db, domain);
+				if(hzone)
+					zone_del_domain_in_hash_tree(
+						hzone->hashtree,
+						&domain->nsec3->hash_wc->hash.node);
+			}
+			if(domain->nsec3->hash_wc->wc.node.key) {
+				zone_type* wczone = nsec3_tree_zone(db, domain);
+				if(wczone)
+					zone_del_domain_in_hash_tree(
+						wczone->wchashtree,
+						&domain->nsec3->hash_wc->wc.node);
+			}
+		}
+		if(domain->nsec3->ds_parent_hash && domain->nsec3->ds_parent_hash->node.key) {
+			zone_type* dszone = nsec3_tree_dszone(db, domain);
+			if(dszone)
+				zone_del_domain_in_hash_tree(
+					dszone->dshashtree,
+					&domain->nsec3->ds_parent_hash->node);
 		}
-		if(domain->nsec3->ds_parent_hash && domain->nsec3->ds_parent_hash->node.key)
-			zone_del_domain_in_hash_tree(nsec3_tree_dszone(db, domain)
-				->dshashtree, &domain->nsec3->ds_parent_hash->node);
 		if(domain->nsec3->hash_wc) {
 			region_recycle(db->domains->region,
 				domain->nsec3->hash_wc,
Index: nsec3.c
===================================================================
RCS file: /cvs/src/usr.sbin/nsd/nsec3.c,v
diff -u -p -r1.30 nsec3.c
--- nsec3.c	21 Mar 2026 21:36:36 -0000	1.30
+++ nsec3.c	7 Jul 2026 10:12:26 -0000
@@ -123,6 +123,7 @@ nsec3_hash_and_store(zone_type* zone, co
 	detect_nsec3_params(zone->nsec3_param, &nsec3_salt,
 		&nsec3_saltlength, &nsec3_iterations);
 	assert(nsec3_iterations >= 0 && nsec3_iterations <= 65536);
+	assert(dname);
 	iterated_hash((unsigned char*)store, nsec3_salt, nsec3_saltlength,
 		dname_name(dname), dname->name_size, nsec3_iterations);
 }
@@ -144,9 +145,11 @@ nsec3_lookup_hash_and_wc(region_type* re
 	domain->nsec3->hash_wc->hash.node.key = NULL;
 	domain->nsec3->hash_wc->wc.node.key = NULL;
 	nsec3_hash_and_store(zone, dname, domain->nsec3->hash_wc->hash.hash);
-	wcard = dname_parse(tmpregion, "*");
-	wcard = dname_concatenate(tmpregion, wcard, dname);
-	nsec3_hash_and_store(zone, wcard, domain->nsec3->hash_wc->wc.hash);
+	if(dname->name_size + 2 <= MAXDOMAINLEN) {
+		wcard = dname_parse(tmpregion, "*");
+		wcard = dname_concatenate(tmpregion, wcard, dname);
+		nsec3_hash_and_store(zone, wcard, domain->nsec3->hash_wc->wc.hash);
+	}
 }
 
 static void
@@ -201,6 +204,23 @@ check_apex_soa(namedb_type* namedb, zone
 	nsec3_hash_and_store(zone, dname, h);
 	tmpregion = region_create(xalloc, free);
 	hashed_apex = nsec3_b32_create(tmpregion, zone, h);
+	if(!hashed_apex) {
+		if(!nolog) {
+			if((int)domain_dname(zone->apex)->name_size >= 223) {
+				log_msg( LOG_ERR
+				       , "apex %s too long for NSEC3 hash label"
+				       , dname_to_string(
+					       domain_dname(zone->apex), NULL));
+			} else {
+				log_msg( LOG_ERR
+				       , "cannot create NSEC3 hash label at %s"
+				       , dname_to_string(
+					       domain_dname(zone->apex), NULL));
+			}
+		}
+		region_destroy(tmpregion);
+		return NULL;
+	}
 	domain = domain_table_find(namedb->domains, hashed_apex);
 	if(!domain) {
 		if(!nolog) {
@@ -327,6 +347,8 @@ nsec3_rr_uses_params(rr_type* rr, zone_t
 {
 	if(!rr || rr->rdlength < 6)
 		return 0;
+	if(dname_name(domain_dname_const(rr->owner))[0] != 32)
+		return 0; /* owner label not valid base32hex SHA-1 hash */
 	return nsec3_rdata_params_ok(zone->nsec3_param, rr);
 }
 
@@ -387,6 +409,89 @@ hash_tree_clear(rbtree_type* tree)
 	tree->root = RBTREE_NULL;
 }
 
+/* Clear nsec3 precompile for walked to domain */
+static void
+nsec3_clear_precompile_walk(struct namedb* db, zone_type* zone,
+	domain_type* walk)
+{
+	if(walk->nsec3) {
+		if(nsec3_condition_hash(walk, zone)) {
+			walk->nsec3->nsec3_node.key = NULL;
+			walk->nsec3->nsec3_cover = NULL;
+			walk->nsec3->nsec3_wcard_child_cover = NULL;
+			walk->nsec3->nsec3_is_exact = 0;
+			if (walk->nsec3->hash_wc) {
+				region_recycle(db->domains->region,
+					walk->nsec3->hash_wc,
+					sizeof(nsec3_hash_wc_node_type));
+				walk->nsec3->hash_wc = NULL;
+			}
+		}
+		if(nsec3_condition_dshash(walk, zone)) {
+			walk->nsec3->nsec3_ds_parent_cover = NULL;
+			walk->nsec3->nsec3_ds_parent_is_exact = 0;
+			if (walk->nsec3->ds_parent_hash) {
+				region_recycle(db->domains->region,
+					walk->nsec3->ds_parent_hash,
+					sizeof(nsec3_hash_node_type));
+				walk->nsec3->ds_parent_hash = NULL;
+			}
+		}
+	}
+}
+
+/* Find the zone above apex (that is the apex of a zone), NULL if none. */
+static struct zone*
+find_superzone_of(struct namedb* db, const dname_type* apex)
+{
+	struct domain* apex_domain = domain_table_find(db->domains, apex);
+	if(apex_domain && apex_domain->parent)
+		return domain_find_zone(db, apex_domain->parent);
+	return NULL;
+}
+
+void
+nsec3_superzone_clear_for_apex(struct namedb* db, const dname_type* apex)
+{
+	domain_type* apex_domain, *walk;
+	struct zone* zone; /* the super zone of apex */
+	zone = find_superzone_of(db, apex);
+	if(!zone) return; /* no super zone above the apex */
+	if(!zone->nsec3_param) return; /* super is not an NSEC3 zone */
+
+	apex_domain = domain_table_find(db->domains, apex);
+	if(!domain_is_subdomain(apex_domain, zone->apex))
+		return; /* robustness check */
+	walk = apex_domain;
+	while(walk && domain_is_subdomain(walk, apex_domain)) {
+		if(walk->nsec3) {
+			if(nsec3_condition_hash(walk, zone)) {
+				zone_del_domain_in_hash_tree(zone->nsec3tree,
+					&walk->nsec3->nsec3_node);
+				if(walk->nsec3->hash_wc) {
+					zone_del_domain_in_hash_tree(
+						zone->hashtree,
+						&walk->nsec3->hash_wc->hash.node);
+					zone_del_domain_in_hash_tree(
+						zone->wchashtree,
+						&walk->nsec3->hash_wc->wc.node);
+				}
+			}
+			if(nsec3_condition_dshash(walk, zone)) {
+				if(walk->nsec3->ds_parent_hash) {
+					zone_del_domain_in_hash_tree(zone->dshashtree,
+						&walk->nsec3->ds_parent_hash->node);
+				}
+			}
+		}
+		nsec3_clear_precompile_walk(db, zone, walk);
+		walk = domain_next(walk);
+	}
+	/* clear nsec3_last if that was cleared */
+	zone->nsec3_last = ((zone->nsec3tree && rbtree_last(zone->nsec3tree) != RBTREE_NULL)?
+		(domain_type*)rbtree_last(zone->nsec3tree)->key:NULL);
+}
+
 void
 nsec3_clear_precompile(struct namedb* db, zone_type* zone)
 {
@@ -403,30 +508,7 @@ nsec3_clear_precompile(struct namedb* db
 	/* wipe precompile */
 	walk = zone->apex;
 	while(walk && domain_is_subdomain(walk, zone->apex)) {
-		if(walk->nsec3) {
-			if(nsec3_condition_hash(walk, zone)) {
-				walk->nsec3->nsec3_node.key = NULL;
-				walk->nsec3->nsec3_cover = NULL;
-				walk->nsec3->nsec3_wcard_child_cover = NULL;
-				walk->nsec3->nsec3_is_exact = 0;
-				if (walk->nsec3->hash_wc) {
-					region_recycle(db->domains->region,
-						walk->nsec3->hash_wc,
-						sizeof(nsec3_hash_wc_node_type));
-					walk->nsec3->hash_wc = NULL;
-				}
-			}
-			if(nsec3_condition_dshash(walk, zone)) {
-				walk->nsec3->nsec3_ds_parent_cover = NULL;
-				walk->nsec3->nsec3_ds_parent_is_exact = 0;
-				if (walk->nsec3->ds_parent_hash) {
-					region_recycle(db->domains->region,
-						walk->nsec3->ds_parent_hash,
-						sizeof(nsec3_hash_node_type));
-					walk->nsec3->ds_parent_hash = NULL;
-				}
-			}
-		}
+		nsec3_clear_precompile_walk(db, zone, walk);
 		walk = domain_next(walk);
 	}
 	zone->nsec3_last = NULL;
@@ -559,8 +641,6 @@ nsec3_precompile_domain(struct namedb* d
 	/* add into tree */
 	zone_add_domain_in_hash_tree(db->region, &zone->hashtree,
 		cmp_hash_tree, domain, &domain->nsec3->hash_wc->hash.node);
-	zone_add_domain_in_hash_tree(db->region, &zone->wchashtree,
-		cmp_wchash_tree, domain, &domain->nsec3->hash_wc->wc.node);
 
 	/* lookup in tree cover ptr (or exact) */
 	exact = nsec3_find_cover(zone, domain->nsec3->hash_wc->hash.hash,
@@ -570,10 +650,23 @@ nsec3_precompile_domain(struct namedb* d
 		domain->nsec3->nsec3_is_exact = 1;
 	else	domain->nsec3->nsec3_is_exact = 0;
 
-	/* find cover for *.domain for wildcard denial */
-	(void)nsec3_find_cover(zone, domain->nsec3->hash_wc->wc.hash,
-		sizeof(domain->nsec3->hash_wc->wc.hash), &result);
-	domain->nsec3->nsec3_wcard_child_cover = result;
+	/* If the wildcard (*.domain) fits within MAXDOMAINLEN, then add it to
+	 * the wildcard hashtree and find the cover for it. Note that, in this 
+	 * case, its hash value has been computed (nsec3_lookup_hash_and_wc()).
+	 */
+	if(domain_dname(domain)->name_size + 2 <= MAXDOMAINLEN) {
+		zone_add_domain_in_hash_tree(db->region, &zone->wchashtree,
+			cmp_wchash_tree, domain, &domain->nsec3->hash_wc->wc.node);
+		(void)nsec3_find_cover(zone, domain->nsec3->hash_wc->wc.hash,
+			sizeof(domain->nsec3->hash_wc->wc.hash), &result);
+		domain->nsec3->nsec3_wcard_child_cover = result;
+	} else {
+		/* Setting to NULL is safe, because nsec3_add_rrset() is the
+		 * only usage of nsec3_wcard_child_cover, and simply doesn't
+		 * try to add anythin if it is NULL
+		 */
+		domain->nsec3->nsec3_wcard_child_cover = NULL;
+	}
 }
 
 void
@@ -627,6 +720,46 @@ nsec3_precompile_nsec3rr(namedb_type* db
 	}
 }
 
+/* nsec3 precompile for walked to domain */
+static void
+nsec3_precompile_walk(struct namedb* db, zone_type* zone, domain_type* walk,
+	struct region* tmpregion)
+{
+	if(nsec3_condition_hash(walk, zone)) {
+		nsec3_precompile_domain(db, walk, zone, tmpregion);
+		region_free_all(tmpregion);
+	}
+	if(nsec3_condition_dshash(walk, zone))
+		nsec3_precompile_domain_ds(db, walk, zone);
+}
+
+void
+nsec3_superzone_precompile_for_apex(struct namedb* db, const dname_type* apex)
+{
+	region_type* tmpregion;
+	domain_type* apex_domain, *walk;
+	struct zone* zone; /* the super zone of apex */
+	zone = find_superzone_of(db, apex);
+	if(!zone) return; /* no super zone above the apex */
+	if(!zone->nsec3_param) return; /* super is not an NSEC3 zone */
+
+	apex_domain = domain_table_find(db->domains, apex);
+	if(!domain_is_subdomain(apex_domain, zone->apex))
+		return; /* robustness check */
+	tmpregion = region_create(xalloc, free);
+	for(walk=apex_domain; walk && domain_is_subdomain(walk, apex_domain);
+		walk = domain_next(walk)) {
+		if(nsec3_in_chain_count(walk, zone) != 0) {
+			nsec3_precompile_nsec3rr(db, walk, zone);
+		}
+	}
+	for(walk=apex_domain; walk && domain_is_subdomain(walk, apex_domain);
+		walk = domain_next(walk)) {
+		nsec3_precompile_walk(db, zone, walk, tmpregion);
+	}
+	region_destroy(tmpregion);
+}
+
 void
 nsec3_precompile_newparam(namedb_type* db, zone_type* zone)
 {
@@ -646,12 +779,7 @@ nsec3_precompile_newparam(namedb_type* d
 	/* hash and precompile zone */
 	for(walk=zone->apex; walk && domain_is_subdomain(walk, zone->apex);
 		walk = domain_next(walk)) {
-		if(nsec3_condition_hash(walk, zone)) {
-			nsec3_precompile_domain(db, walk, zone, tmpregion);
-			region_free_all(tmpregion);
-		}
-		if(nsec3_condition_dshash(walk, zone))
-			nsec3_precompile_domain_ds(db, walk, zone);
+		nsec3_precompile_walk(db, zone, walk, tmpregion);
 		if(++c % ZONEC_PCT_COUNT == 0 && time(NULL) > s + ZONEC_PCT_TIME) {
 			s = time(NULL);
 			VERBOSITY(1, (LOG_INFO, "nsec3 %s %d %%",
Index: nsec3.h
===================================================================
RCS file: /cvs/src/usr.sbin/nsd/nsec3.h,v
diff -u -p -r1.4 nsec3.h
--- nsec3.h	20 Dec 2023 17:29:01 -0000	1.4
+++ nsec3.h	7 Jul 2026 10:12:26 -0000
@@ -104,6 +104,12 @@ void nsec3_precompile_nsec3rr(struct nam
 	struct zone* zone);
 /* precompile entire zone, assumes all is null at start */
 void nsec3_precompile_newparam(struct namedb* db, struct zone* zone);
+/* clear super zone of apex, for names subdomain of apex. */
+void nsec3_superzone_clear_for_apex(struct namedb* db,
+	const struct dname* apex);
+/* precompile super zone of apex, for names subdomain of apex. */
+void nsec3_superzone_precompile_for_apex(struct namedb* db,
+	const struct dname* apex);
 /* create b32.zone for a hash, allocated in the region */
 const struct dname* nsec3_b32_create(struct region* region, struct zone* zone,
 	unsigned char* hash);
Index: options.c
===================================================================
RCS file: /cvs/src/usr.sbin/nsd/options.c,v
diff -u -p -r1.34 options.c
--- options.c	26 Jun 2026 08:31:25 -0000	1.34
+++ options.c	7 Jul 2026 10:12:26 -0000
@@ -29,6 +29,7 @@
 #include "rrl.h"
 #include "bitset.h"
 #include "xfrd.h"
+#include "metrics.h"
 
 #include "configparser.h"
 config_parser_state_type* cfg_parser = 0;
@@ -2971,12 +2972,30 @@ unsigned getzonestatid(struct nsd_option
 {
 #ifdef USE_ZONE_STATS
 	const char* statname;
+	char* statname_valid;
+	int name_was_modified;
 	struct zonestatname* n;
 	rbnode_type* res;
 	/* try to find the instantiated zonestat name */
 	if(!zopt->pattern->zonestats || zopt->pattern->zonestats[0]==0)
 		return 0; /* no zone stats */
 	statname = config_cook_string(zopt, zopt->pattern->zonestats);
+
+	#ifdef USE_METRICS
+	/* warn when we will lossily change the zonestat name in metrics */
+	statname_valid = strdup(statname);
+	if(!statname_valid) {
+		log_msg(LOG_ERR, "malloc failed: %s", strerror(errno));
+		exit(1);
+	}
+	name_was_modified = metrics_make_label_value_valid(statname_valid);
+	if (name_was_modified) {
+		log_msg(LOG_WARNING, "zonestats name \"%s\" contains disallowed characters, using \"%s\" in metrics",
+			statname, statname_valid);
+	}
+	free(statname_valid);
+	#endif /* USE_METRICS */
+
 	res = rbtree_search(opt->zonestatnames, statname);
 	if(res)
 		return ((struct zonestatname*)res)->id;
Index: query.c
===================================================================
RCS file: /cvs/src/usr.sbin/nsd/query.c,v
diff -u -p -r1.45 query.c
--- query.c	21 Mar 2026 21:36:36 -0000	1.45
+++ query.c	7 Jul 2026 10:12:26 -0000
@@ -497,6 +497,7 @@ answer_notify(struct nsd* nsd, struct qu
 	{
 		int s = nsd->serve2xfrd_fd_send[nsd->this_child->child_num];
 		uint16_t sz;
+		uint32_t sz32;
 		uint32_t acl_send = htonl(acl_num);
 		uint32_t acl_xfr;
 		size_t pos;
@@ -517,8 +518,11 @@ answer_notify(struct nsd* nsd, struct qu
 			return query_error(query, NSD_RC_SERVFAIL);
 		/* forward to xfrd for processing
 		   Note. Blocking IPC I/O, but acl is OK. */
-		sz = buffer_limit(query->packet)
+		sz32 = buffer_limit(query->packet)
 		   + sizeof(acl_send) + sizeof(acl_xfr);
+		if(sz32 > 0xFFFF)
+			return query_error(query, NSD_RC_SERVFAIL);
+		sz = (uint16_t)sz32;
 		sz = htons(sz);
 		if(!write_socket(s, &sz, sizeof(sz)) ||
 			!write_socket(s, buffer_begin(query->packet),
Index: rdata.c
===================================================================
RCS file: /cvs/src/usr.sbin/nsd/rdata.c,v
diff -u -p -r1.21 rdata.c
--- rdata.c	26 Jun 2026 08:31:25 -0000	1.21
+++ rdata.c	7 Jul 2026 10:12:26 -0000
@@ -137,7 +137,7 @@ print_name_literal(struct buffer *output
 {
 	const uint8_t *name, *label, *limit;
 	assert(rdlength >= *offset);
-	if (rdlength - *offset == 0)
+	if (rdlength < *offset || rdlength - *offset == 0)
 		return 0;
 
 	name = rdata + *offset;
@@ -181,7 +181,7 @@ print_domain(struct buffer *output, uint
 {
 	const struct dname *dname;
 	struct domain *domain;
-	if(rdlength - *offset < (uint16_t)sizeof(void*))
+	if(rdlength < *offset || rdlength - *offset < (uint16_t)sizeof(void*))
 		return 0;
 	memcpy(&domain, rdata+*offset, sizeof(void*));
 	dname = domain_dname(domain);
@@ -195,7 +195,7 @@ static inline int32_t
 skip_string(struct buffer* output, uint16_t rdlength, uint16_t* offset)
 {
 	int32_t length;
-	if (rdlength - *offset < 1)
+	if (rdlength < *offset || rdlength - *offset < 1)
 		return -1;
 	length = buffer_read_u8(output);
 	if (length + 1 > rdlength - *offset)
@@ -236,7 +236,7 @@ print_string(struct buffer *output, uint
 	if(rdlength - *offset < 1)
 		return 0;
 	n = rdata[*offset];
-	if((size_t)rdlength - *offset < 1 + n)
+	if(rdlength < *offset || (size_t)rdlength - *offset < 1 + n)
 		return 0;
 	buffer_printf(output, "\"");
 	for (size_t i = 1; i <= n; i++) {
@@ -285,7 +285,7 @@ print_unquoted(buffer_type *output, uint
 	uint8_t len;
 	size_t i;
 
-	if(rdlength - *offset < 1)
+	if(rdlength < *offset || rdlength - *offset < 1)
 		return 0;
 	len = rdata[*offset];
 	if(((size_t)len) + 1 > (size_t)rdlength - *offset)
@@ -336,7 +336,6 @@ print_ip4(struct buffer *output, size_t 
 	uint16_t *offset)
 {
 	char str[INET_ADDRSTRLEN + 1];
-	assert(rdlength >= *offset);
 	if(((size_t)*offset) + 4 > rdlength)
 		return 0;
 	if(!inet_ntop(AF_INET, rdata + *offset, str, sizeof(str)))
@@ -360,8 +359,7 @@ print_ip6(struct buffer *output, size_t 
 	uint16_t *offset)
 {
 	char str[INET6_ADDRSTRLEN + 1];
-	assert(rdlength >= *offset);
-	if (rdlength - *offset < 16)
+	if (rdlength < *offset || rdlength - *offset < 16)
 		return 0;
 	if (!inet_ntop(AF_INET6, rdata + *offset, str, sizeof(str)))
 		return 0;
@@ -384,8 +382,7 @@ print_ilnp64(struct buffer *output, uint
 	uint16_t *offset)
 {
 	uint16_t a1, a2, a3, a4;
-	assert(rdlength >= *offset);
-	if (rdlength - *offset < 8)
+	if (rdlength < *offset || rdlength - *offset < 8)
 		return 0;
 	a1 = read_uint16(rdata + *offset);
 	a2 = read_uint16(rdata + *offset + 2);
@@ -442,8 +439,7 @@ print_time(struct buffer *output, uint16
 	struct tm* tm;
 	char buf[15];
 
-	assert(rdlength >= *offset);
-	if (rdlength - *offset < 4)
+	if (rdlength < *offset || rdlength - *offset < 4)
 		return 0;
 	time = (time_t)read_uint32(rdata + *offset);
 	tm = gmtime_r(&time, &tmbuf);
@@ -469,7 +465,7 @@ print_base32(struct buffer *output, uint
 {
 	size_t size;
 	int length;
-	if(rdlength - *offset == 0)
+	if(rdlength < *offset || rdlength - *offset == 0)
 		return 0;
 	size = rdata[*offset];
 	if (rdlength - ((size_t)*offset) < 1 + size)
@@ -506,6 +502,8 @@ print_base64(struct buffer *output, uint
 {
 	int length;
 	size_t size = rdlength - *offset;
+	if(rdlength < *offset)
+		return 0;
 	if(size == 0) {
 		/* single zero represents empty buffer */
 		buffer_write(output, "0", 1);
@@ -552,6 +550,8 @@ print_base16(struct buffer *output, uint
 	uint16_t *offset)
 {
 	size_t size = rdlength - *offset;
+	if(rdlength < *offset)
+		return 0;
 	if(size == 0) {
 		/* single zero represents empty buffer, such as CDS deletes */
 		buffer_write(output, "0", 1);
@@ -577,8 +577,7 @@ print_salt(struct buffer *output, uint16
 	uint16_t *offset)
 {
 	uint8_t length;
-	assert(rdlength >= *offset);
-	if (rdlength - *offset == 0)
+	if (rdlength < *offset || rdlength - *offset == 0)
 		return 0;
 
 	length = rdata[*offset];
@@ -637,6 +636,8 @@ print_nsec_bitmap(struct buffer *output,
 {
 	int insert_space = 0;
 
+	if(rdlength < *offset)
+		return 0;
 	rdata += *offset;
 	while(rdlength - *offset > 0) {
 		uint8_t window, bitmap_size;
@@ -701,7 +702,7 @@ svcparam_must_not_have_value(uint16_t sv
 		break;
 	}
 	return 0;
-};
+}
 
 /*
  * Skip over the svcparams in the packet. Moves position.
@@ -967,8 +968,7 @@ print_svcparam(struct buffer *output, ui
 	const uint8_t* dp;
 	unsigned i;
 
-	assert(rdlength >= *offset);
-	if (rdlength - *offset < 4)
+	if (rdlength < *offset || rdlength - *offset < 4)
 		return 0;
 
 	key = read_uint16(rdata + *offset);
@@ -2266,7 +2266,7 @@ print_nxt_rdata(struct buffer *output, c
 	int bitmap_size;
 	const uint8_t* bitmap;
 
-	assert(rr->rdlength > sizeof(void*));
+	assert(rr->rdlength >= sizeof(void*));
 	if (!print_domain(output, rr->rdlength, rr->rdata, &length))
 		return 0;
 
@@ -2593,7 +2593,7 @@ print_apl(struct buffer *output, size_t 
 	char text_address[INET6_ADDRSTRLEN + 1];
 	uint8_t address[16];
 
-	if (size < 4)
+	if (rdlength < *offset || size < 4)
 		return 0;
 
 	address_family = read_uint16(rdata + *offset);
@@ -3134,6 +3134,8 @@ print_hip_rdata(struct buffer *output, c
 	hit_length = rr->rdata[0];
 	pk_algorithm = rr->rdata[1];
 	pk_length = read_uint16(rr->rdata+2);
+	if(4 + (uint32_t)hit_length + (uint32_t)pk_length > (uint32_t)rr->rdlength)
+		return 0;
 	buffer_printf(output, "%" PRIu8 " ", pk_algorithm);
 	if(!print_base16(output, length+hit_length, rr->rdata, &length))
 		return 0;
Index: remote.c
===================================================================
RCS file: /cvs/src/usr.sbin/nsd/remote.c,v
diff -u -p -r1.30 remote.c
--- remote.c	21 Mar 2026 21:36:36 -0000	1.30
+++ remote.c	7 Jul 2026 10:12:26 -0000
@@ -2407,6 +2407,7 @@ do_assoc_tsig(RES* ssl, xfrd_state_type*
 	char* arg2 = NULL;
 	struct zone_options* zone;
 	struct key_options* key_opt;
+	struct xfrd_zone* xzone;
 
 	if(*arg == '\0') {
 		(void)ssl_printf(ssl, "error: missing argument (zonename)\n");
@@ -2429,6 +2430,23 @@ do_assoc_tsig(RES* ssl, xfrd_state_type*
 		return;
 	}
 
+	/* Abort any in-flight transfer for this zone before mutating its ACL
+	 * so that xfr->tsig stays consistent with zone->master->key_options. */
+	xzone = xfrd_find_zone(xfrd, (dname_type*)zone->node.key);
+	if(xzone && xzone->tcp_conn != -1) {
+		xfrd_tcp_release(xfrd->tcp_set, xzone);
+		/* probe the current target again, if possible. */
+		if(xzone->next_master == -1)
+			xzone->next_master = xzone->master_num;
+		xfrd_set_refresh_now(xzone);
+	} else if(xzone && xzone->zone_handler.ev_fd != -1) {
+		/* Also UDP can use the TSIG for signature. */
+		xfrd_udp_release(xzone);
+		if(xzone->next_master == -1)
+			xzone->next_master = xzone->master_num;
+		xfrd_set_refresh_now(xzone);
+	}
+
 	zopt_set_acl_to_tsig(zone->pattern->allow_notify, region, arg2,
 		key_opt);
 	zopt_set_acl_to_tsig(zone->pattern->notify, region, arg2, key_opt);
@@ -2476,6 +2494,7 @@ do_del_tsig(RES* ssl, xfrd_state_type* x
 	}
 	RBTREE_FOR(zone, struct zone_options*, xfrd->nsd->options->zone_options)
 	{
+		xfrd_zone_type* xzone;
 		if(acl_contains_tsig_key(zone->pattern->allow_notify, arg) ||
 		   acl_contains_tsig_key(zone->pattern->notify, arg) ||
 		   acl_contains_tsig_key(zone->pattern->request_xfr, arg) ||
@@ -2487,6 +2506,15 @@ do_del_tsig(RES* ssl, xfrd_state_type* x
 			used_key = 1;
 			break;
 		}
+		xzone = xfrd_find_zone(xfrd, (dname_type*)zone->node.key);
+		if(xzone && xzone->latest_xfr &&
+			xzone->latest_xfr->tsig.key == key_opt->tsig_key) {
+			if(!ssl_printf(ssl, "zone %s uses key %s\n",
+				zone->name, arg))
+				return;
+			used_key = 1;
+			break;
+		}
 	}
 
 	if(used_key) {
@@ -2838,8 +2866,17 @@ handle_req(struct daemon_remote* rc, str
 		(void)ssl_printf(res, "error version mismatch\n");
 		return;
 	}
-	/* always log control commands */
-	VERBOSITY(0, (LOG_INFO, "control cmd: %s", buf));
+	/* always log control command 'verbosity', others at 2, so
+	 * they can be squelched if needed. */
+	if(verbosity < 2) {
+		/* only the 'verbosity' command. */
+		if(strncmp(skipwhite(buf), "verbosity", 9) == 0) {
+			VERBOSITY(0, (LOG_INFO, "control cmd: %s", buf));
+		}
+	} else {
+		/* always log every control command. */
+		VERBOSITY(2, (LOG_INFO, "control cmd: %s", buf));
+	}
 
 	/* figure out what to do */
 	execute_cmd(rc, res, buf);
Index: server.c
===================================================================
RCS file: /cvs/src/usr.sbin/nsd/server.c,v
diff -u -p -r1.57 server.c
--- server.c	26 Jun 2026 08:31:25 -0000	1.57
+++ server.c	7 Jul 2026 10:12:26 -0000
@@ -3221,7 +3221,9 @@ server_main(struct nsd *nsd)
 	}
 
 #ifdef USE_XDP
-	xdp_server_cleanup(&nsd->xdp.xdp_server);
+	if (nsd->options->xdp_interface) {
+		xdp_server_cleanup(&nsd->xdp.xdp_server);
+	}
 #endif
 
 #ifdef MEMCLEAN /* OS collects memory pages */
@@ -4096,6 +4098,10 @@ consume_pp2_header(struct buffer* buf, s
 			{
 			struct sockaddr_in* addr =
 				(struct sockaddr_in*)&q->client_addr;
+			if(ntohs(header->len) < PP2_HEADER_LEN_INET) {
+				VERBOSITY(4, (LOG_ERR, "proxy_protocol: header too short for IPv4 address"));
+				return 0;
+			}
 			addr->sin_family = AF_INET;
 			memmove(&addr->sin_addr.s_addr,
 				&header->addr.addr4.src_addr, 4);
@@ -4111,6 +4117,10 @@ consume_pp2_header(struct buffer* buf, s
 			{
 			struct sockaddr_in6* addr =
 				(struct sockaddr_in6*)&q->client_addr;
+			if(ntohs(header->len) < PP2_HEADER_LEN_INET6) {
+				VERBOSITY(4, (LOG_ERR, "proxy_protocol: header too short for IPv6 address"));
+				return 0;
+			}
 			memset(addr, 0, sizeof(*addr));
 			addr->sin6_family = AF_INET6;
 			memmove(&addr->sin6_addr,
Index: udb.h
===================================================================
RCS file: /cvs/src/usr.sbin/nsd/udb.h,v
diff -u -p -r1.6 udb.h
--- udb.h	20 Dec 2023 17:29:02 -0000	1.6
+++ udb.h	7 Jul 2026 10:12:26 -0000
@@ -213,7 +213,6 @@ struct udb_base {
 	int useful_compact;
 };
 
-typedef enum udb_chunk_type udb_chunk_type;
 /** chunk type enum, setting these types help recovery and debug */
 enum udb_chunk_type {
 	udb_chunk_type_free = 0,
@@ -221,6 +220,7 @@ enum udb_chunk_type {
 	udb_chunk_type_task,
 	udb_chunk_type_internal
 };
+typedef enum udb_chunk_type udb_chunk_type;
 
 typedef struct udb_chunk_d udb_chunk_d;
 /**
@@ -242,7 +242,7 @@ struct udb_chunk_d {
 	 * In the free chunk this is the previous pointer. */
 	udb_void ptrlist;
 	/* user data space starts here, 64-bit aligned */
-	uint8_t data[0];
+	uint8_t data[];
 	/* last octet: exp of chunk */
 };
 
@@ -287,7 +287,7 @@ struct udb_xl_chunk_d {
 	/** size of this chunk in bytes */
 	uint64_t size;
 	/** data of the XL chunk */
-	uint8_t data[0];
+	uint8_t data[];
 	/* uint64_t endsize: before last octet the size again. */
 	/* uint8_t pad[7]: padding to make last octet last. */
 	/* last octet: exp of chunk: special XL value */
Index: verify.c
===================================================================
RCS file: /cvs/src/usr.sbin/nsd/verify.c,v
diff -u -p -r1.5 verify.c
--- verify.c	6 Sep 2025 17:41:37 -0000	1.5
+++ verify.c	7 Jul 2026 10:12:26 -0000
@@ -371,11 +371,13 @@ verify_handle_command(int fd, short even
 	sig_atomic_t mode;
 
 	assert(nsd != NULL);
-	assert((event & (EV_READ
+	{
+		short ev_read = EV_READ;
 #ifdef EV_CLOSED
-	| EV_CLOSED
+		ev_read |= EV_CLOSED;
 #endif
-	)));
+		assert((event & ev_read));
+	}
 
 	if((len = read(fd, &mode, sizeof(mode))) == -1) {
 		log_msg(LOG_ERR, "verify: verify_handle_command: read: %s",
Index: xfrd-catalog-zones.c
===================================================================
RCS file: /cvs/src/usr.sbin/nsd/xfrd-catalog-zones.c,v
diff -u -p -r1.4 xfrd-catalog-zones.c
--- xfrd-catalog-zones.c	21 Mar 2026 21:36:36 -0000	1.4
+++ xfrd-catalog-zones.c	7 Jul 2026 10:12:26 -0000
@@ -582,6 +582,7 @@ retry_adding:
 		int valid_group_values;
 		struct pattern_options *pattern = NULL;
 		struct catalog_member_zone* to_add;
+		const dname_type* group_dname;
 
 		if (domain_dname(member_id)->label_count > dname->label_count+2
 		||  !(rrset = domain_find_rrset(member_id, zone, TYPE_PTR)))
@@ -610,8 +611,12 @@ retry_adding:
 
 		valid_group_values = 0;
 		/* Lookup group.<member_id> TXT for matching patterns  */
-		if(!namedb_lookup(xfrd->nsd->db, label_plus_dname("group",
-						domain_dname(member_id)),
+		group_dname = label_plus_dname("group",
+			domain_dname(member_id));
+		/* If group_dname is NULL, then the group name is too long,
+		 * and group properties are skipped for this member. */
+		if(!group_dname
+		|| !namedb_lookup(xfrd->nsd->db, group_dname,
 					&group, &closest_encloser)
 		|| !(rrset = domain_find_rrset(group, zone, TYPE_TXT))) {
 			; /* pass */
@@ -973,13 +978,26 @@ xfrd_add_catalog_producer_member(struct 
 	producer_name = producer_zone->node.key;
 	while(!cmz->member_id) {
 		/* Make new member_id with this catalog producer */
+		const dname_type* zones_name;
 		char id_label[sizeof(uint32_t)*2+1];
 		uint32_t new_id = (uint32_t)random_generate(0x7fffffff);
 
 		hex_ntop((void*)&new_id, sizeof(uint32_t), id_label, sizeof(id_label));
 		id_label[sizeof(uint32_t)*2] = 0;
-		cmz->member_id = label_plus_dname(id_label,
-				label_plus_dname("zones", producer_name));
+		zones_name = label_plus_dname("zones", producer_name);
+		if(!zones_name) {
+			log_msg(LOG_ERR, "catalog producer: producer zone name "
+				"is too long, to add zones label. "
+				"Skipping addition of member zone");
+			return;
+		}
+		cmz->member_id = label_plus_dname(id_label, zones_name);
+		if(!cmz->member_id) {
+			log_msg(LOG_ERR, "catalog producer: producer zone name "
+				"is too long, for member_id.zones labels. "
+				"Skipping addition of member zone");
+			return;
+		}
 		DEBUG(DEBUG_XFRD, 1, (LOG_INFO, "does member_id %s exist?",
 			dname_to_string(cmz->member_id, NULL)));
 		if (!rbtree_search(&producer_zone->member_ids, cmz)) {
@@ -1185,6 +1203,19 @@ xfrd_process_catalog_producer_zone(
 		return; /* No changes */
 
 	producer_name = (dname_type*)producer_zone->node.key;
+	if (producer_name->name_size > 234) {
+		/* For "group".<8char member id>."zones".apex.
+		 * that is (1+5)+(1+8)+(1+5)+apex.
+		 * 255 - (6+9+6) = 234 */
+		log_msg(LOG_ERR, "catalog producer: name too long of "
+			"producer zone %s", dname_to_string(producer_name,0));
+		return;
+	}
+	if (producer_name->label_count > 124) {
+		log_msg(LOG_ERR, "catalog producer: too many labels in name of "
+			"producer zone %s", dname_to_string(producer_name,0));
+		return;
+	}
 	xfr_writer_init(&xw, producer_zone);
 	xfr_writer_add_SOA(&xw, producer_name, xw.new_serial);
 
@@ -1201,6 +1232,7 @@ xfrd_process_catalog_producer_zone(
 	/* IXFR */
 	xfr_writer_add_SOA(&xw, producer_name, xw.old_serial);
 	while(producer_zone->to_delete) {
+		const dname_type* group_owner;
 		struct xfrd_producer_member* to_delete =
 			producer_zone->to_delete;
 
@@ -1208,14 +1240,45 @@ xfrd_process_catalog_producer_zone(
 		producer_zone->to_delete = to_delete->next;
 		to_delete->next = NULL;
 
+		if((size_t)to_delete->member_id->name_size > 249) {
+			log_msg(LOG_ERR, "catalog producer: member_id "
+				"name_size %d too long for group property "
+				"owner; skipping delete of member zone %s",
+				(int)to_delete->member_id->name_size,
+				dname_to_string(to_delete->member_zone_name,0));
+			region_recycle( xfrd->nsd->options->region
+				      , (void *)to_delete->member_id
+				      , dname_total_size(to_delete->member_id));
+			region_recycle( xfrd->region /* allocated in perform_delzone */
+				      , (void *)to_delete->member_zone_name
+				      , dname_total_size(to_delete->member_zone_name));
+			region_recycle( xfrd->region, to_delete, sizeof(*to_delete));
+			continue;
+		}
+
 		/* Write <member_id> PTR <member_name> */
 		xfr_writer_add_PTR(&xw, to_delete->member_id
 				      , to_delete->member_zone_name);
 
 		/* Write group.<member_id> TXT <pattern> */
+		group_owner = label_plus_dname("group", to_delete->member_id);
+		if(!group_owner) {
+			log_msg(LOG_ERR, "catalog producer: member_id "
+				"name_size %d too long for group property "
+				"owner; skipping delete of member zone %s",
+				(int)to_delete->member_id->name_size,
+				dname_to_string(to_delete->member_zone_name,0));
+			region_recycle( xfrd->nsd->options->region
+				      , (void *)to_delete->member_id
+				      , dname_total_size(to_delete->member_id));
+			region_recycle( xfrd->region /* allocated in perform_delzone */
+				      , (void *)to_delete->member_zone_name
+				      , dname_total_size(to_delete->member_zone_name));
+			region_recycle( xfrd->region, to_delete, sizeof(*to_delete));
+			continue;
+		}
 		xfr_writer_add_TXT( &xw
-				  , label_plus_dname("group"
-						    , to_delete->member_id)
+				  , group_owner
 				  , to_delete->group_name);
 
 		region_recycle( xfrd->nsd->options->region
@@ -1232,19 +1295,38 @@ xfrd_process_catalog_producer_zone(
 add_member_zones:
 	while(producer_zone->to_add) {
 		struct xfrd_producer_member* to_add = producer_zone->to_add;
+		const dname_type* group_owner;
 
 		/* Pop to_add from stack */
 		producer_zone->to_add = to_add->next;
 		to_add->next = NULL;
 
+		if((size_t)to_add->member_id->name_size > 249) {
+			log_msg(LOG_ERR, "catalog producer: member_id "
+				"name_size %d too long for group property "
+				"owner; skipping member zone %s",
+				(int)to_add->member_id->name_size,
+				dname_to_string(to_add->member_zone_name,0));
+			region_recycle(xfrd->region, to_add, sizeof(*to_add));
+			continue;
+		}
+
 		/* Write <member_id> PTR <member_name> */
 		xfr_writer_add_PTR(&xw, to_add->member_id,
 				to_add->member_zone_name);
 
 		/* Write group.<member_id> TXT <pattern> */
+		group_owner = label_plus_dname("group", to_add->member_id);
+		if(!group_owner) {
+			log_msg(LOG_ERR, "catalog producer: member_id too long "
+				"to construct group owner (name_size=%d); "
+				"skipping group property for member zone",
+				(int)to_add->member_id->name_size);
+			region_recycle(xfrd->region, to_add, sizeof(*to_add));
+			continue;
+		}
 		xfr_writer_add_TXT( &xw
-				  , label_plus_dname("group"
-						    , to_add->member_id)
+				  , group_owner
 				  , to_add->group_name);
 
 		/* Don't recycle any of the struct attributes as they come
Index: xfrd-tcp.c
===================================================================
RCS file: /cvs/src/usr.sbin/nsd/xfrd-tcp.c,v
diff -u -p -r1.32 xfrd-tcp.c
--- xfrd-tcp.c	6 Sep 2025 17:41:37 -0000	1.32
+++ xfrd-tcp.c	7 Jul 2026 10:12:26 -0000
@@ -321,7 +321,7 @@ void pick_id_values(uint16_t* array, int
 	for(j = max-num; j<max; j++) {
 		/* random generate creates from 0..arg-1 */
 		int t;
-		if(j+1 <= 1)
+		if(j < 1)
 			t = 0;
 		else	t = random_generate(j+1);
 		if(!inserted[t]) {
Index: xfrd.c
===================================================================
RCS file: /cvs/src/usr.sbin/nsd/xfrd.c,v
diff -u -p -r1.36 xfrd.c
--- xfrd.c	21 Mar 2026 21:36:36 -0000	1.36
+++ xfrd.c	7 Jul 2026 10:12:26 -0000
@@ -1629,6 +1629,9 @@ xfrd_udp_read_packet(buffer_type* packet
 		log_msg(LOG_ERR, "xfrd: recvfrom failed: %s",
 			strerror(errno));
 		return 0;
+	} else if(received < QHEADERSZ) {
+		log_msg(LOG_ERR, "xfrd: UDP packet too small");
+		return 0;
 	}
 	buffer_set_limit(packet, received);
 	return 1;
@@ -1984,6 +1987,8 @@ static int xfrd_parse_soa_info(buffer_ty
 	{
 		return 0;
 	}
+	if(!buffer_available(packet, 20))
+		return 0;
 	soa->serial = htonl(buffer_read_u32(packet));
 	soa->refresh = htonl(buffer_read_u32(packet));
 	soa->retry = htonl(buffer_read_u32(packet));
@@ -2008,12 +2013,13 @@ xfrd_xfr_check_rrs(xfrd_zone_type* zone,
 	/* first RR has already been checked */
 	const struct nsd_type_descriptor *descriptor;
 	uint32_t tmp_serial = 0;
-	uint16_t type, rrlen;
+	uint16_t type, klass, rrlen;
 	size_t i, soapos, mempos;
 	const dname_type* dname;
 	struct rr* rr;
 	int32_t code;
 	domain_table_type* owners;
+	enum { DELETING_RRs = 0, ADDING_RRs } ixfr_state = DELETING_RRs;
 
 	for(i=0; i<count; ++i,++zone->latest_xfr->msg_rr_count)
 	{
@@ -2038,7 +2044,15 @@ xfrd_xfr_check_rrs(xfrd_zone_type* zone,
 		}
 		soapos = buffer_position(packet);
 		type = buffer_read_u16(packet);
-		(void)buffer_read_u16(packet); /* class */
+		klass = buffer_read_u16(packet);
+		if(klass != CLASS_IN && type != TYPE_OPT) {
+			log_msg(LOG_ERR, "xfrd: zone %s xfr "
+				"non-IN-class RR (%s type=%s class=%s), rejected",
+				zone->apex_str, dname_to_string(dname,0),
+				rrtype_to_string(type),
+				rrclass_to_string(klass));
+			return 0;
+		}
 		(void)buffer_read_u32(packet); /* ttl */
 		rrlen = buffer_read_u16(packet);
 		if(!buffer_available(packet, rrlen)) {
@@ -2082,6 +2096,7 @@ xfrd_xfr_check_rrs(xfrd_zone_type* zone,
 				}
 				zone->latest_xfr->msg_old_serial = ntohl(soa->serial);
 				tmp_serial = ntohl(soa->serial);
+				ixfr_state = DELETING_RRs;
 			}
 			else if(ntohl(soa->serial) == zone->latest_xfr->msg_new_serial) {
 				/* saw another SOA of new serial. */
@@ -2104,13 +2119,44 @@ xfrd_xfr_check_rrs(xfrd_zone_type* zone,
 						"serial decreasing not allowed", zone->apex_str));
 					return 0; /* middle serial decreases in IXFR */
 				}
+				if(ntohl(soa->serial) == tmp_serial) {
+					if(ixfr_state == DELETING_RRs) {
+						DEBUG(DEBUG_XFRD,1, ( LOG_ERR, "xfrd: zone %s xfr serial duplicate "
+							  "not allowed for serial %"PRIu32" while %s",
+							  zone->apex_str, tmp_serial,
+							  ( ixfr_state == DELETING_RRs
+							  ? "deleting RRs" : "adding RRs")));
+						return 0; /* middle serial is the same as the previous in IXFR */
+					}
+					ixfr_state = DELETING_RRs;
+				} else {
+					assert(ntohl(soa->serial) > tmp_serial);
+					ixfr_state = ADDING_RRs;
+				}
 				/* serial ok, update tmp serial */
 				tmp_serial = ntohl(soa->serial);
 			}
+			else {
+				/* AXFR mode, rr_count>1, serial!=new_serial,
+				 * RFC 5936 s2.2 forbids SOA in a non-terminal
+				 * position with a different serial. Reject
+				 * the stream. */
+				DEBUG(DEBUG_XFRD,1, (LOG_ERR, "xfrd: zone %s axfr "
+					"unexpected mid-stream SOA serial %u",
+					zone->apex_str,
+					(unsigned)ntohl(soa->serial)));
+				return 0; /* SOA in middle of AXFR */
+			}
 		}
 		buffer_set_position(packet, mempos);
 		buffer_skip(packet, rrlen);
 	}
+	if(buffer_position(packet) != buffer_limit(packet)) {
+		DEBUG(DEBUG_XFRD,1, (LOG_ERR, "xfrd: zone %s xfr bad, "
+			"trailing data %d bytes", zone->apex_str,
+			(int)(buffer_limit(packet)-buffer_position(packet))));
+		return 0; /* trailing data */
+	}
 	/* packet seems to have a valid DNS RR structure */
 	return 1;
 }
@@ -2730,6 +2776,12 @@ xfrd_handle_notify_and_start_xfr(xfrd_zo
 		if(zone->soa_disk_acquired == 0)
 			zone->fresh_xfr_timeout = XFRD_TRANSFER_TIMEOUT_START;
 	}
+}
+
+struct xfrd_zone*
+xfrd_find_zone(xfrd_state_type* xfrd, const dname_type* dname)
+{
+	return (xfrd_zone_type*)rbtree_search(xfrd->zones, dname);
 }
 
 void
Index: xfrd.h
===================================================================
RCS file: /cvs/src/usr.sbin/nsd/xfrd.h,v
diff -u -p -r1.15 xfrd.h
--- xfrd.h	21 Mar 2026 21:36:36 -0000	1.15
+++ xfrd.h	7 Jul 2026 10:12:26 -0000
@@ -488,4 +488,8 @@ xfrd_xfr_type *xfrd_prepare_zone_xfr(xfr
 
 void xfrd_delete_zone_xfr(xfrd_zone_type *zone, xfrd_xfr_type *xfr);
 
+/* Find zone by name. */
+struct xfrd_zone* xfrd_find_zone(xfrd_state_type* xfrd,
+	const dname_type* dname);
+
 #endif /* XFRD_H */
Index: simdzone/configure.ac
===================================================================
RCS file: /cvs/src/usr.sbin/nsd/simdzone/configure.ac,v
diff -u -p -r1.1.1.3 configure.ac
--- simdzone/configure.ac	21 Mar 2026 21:34:33 -0000	1.1.1.3
+++ simdzone/configure.ac	7 Jul 2026 10:12:26 -0000
@@ -10,7 +10,7 @@
 # platform not supported by NSD here is undesirable. Builds for standalone use
 # or development/testing are required to use CMake.
 
-AC_INIT([simdzone],[0.2.4],[https://github.com/NLnetLabs/simdzone/issues])
+AC_INIT([simdzone],[0.2.5],[https://github.com/NLnetLabs/simdzone/issues])
 
 AC_CONFIG_HEADERS([config.h])
 AC_CONFIG_FILES([Makefile])
Index: simdzone/src/isadetection.h
===================================================================
RCS file: /cvs/src/usr.sbin/nsd/simdzone/src/isadetection.h,v
diff -u -p -r1.1.1.2 isadetection.h
--- simdzone/src/isadetection.h	6 Sep 2025 17:38:34 -0000	1.1.1.2
+++ simdzone/src/isadetection.h	7 Jul 2026 10:12:26 -0000
@@ -107,6 +107,12 @@ static inline uint32_t detect_supported_
 
 #endif
 
+#elif defined(__riscv)
+
+static inline uint32_t detect_supported_architectures(void) {
+  return DEFAULT;
+}
+
 #elif defined(__x86_64__) || defined(_M_AMD64) // x64
 
 // Can be found on Intel ISA Reference for CPUID
Index: simdzone/src/generic/svcb.h
===================================================================
RCS file: /cvs/src/usr.sbin/nsd/simdzone/src/generic/svcb.h,v
diff -u -p -r1.1.1.1 svcb.h
--- simdzone/src/generic/svcb.h	3 Sep 2025 18:44:23 -0000	1.1.1.1
+++ simdzone/src/generic/svcb.h	7 Jul 2026 10:12:26 -0000
@@ -239,6 +239,10 @@ static int32_t parse_ech(
   (void)key;
   (void)param;
 
+  if(token->length == 1 && token->data[0] == '0') {
+	  /* single 0 represents empty buffer */
+	  return 0;
+  }
   if (token->length / 4 > size / 3)
     SYNTAX_ERROR(parser, "maximum size exceeded");
 
Index: util/proxy_protocol.c
===================================================================
RCS file: /cvs/src/usr.sbin/nsd/util/proxy_protocol.c,v
diff -u -p -r1.1 proxy_protocol.c
--- util/proxy_protocol.c	20 Dec 2023 17:29:02 -0000	1.1
+++ util/proxy_protocol.c	7 Jul 2026 10:12:26 -0000
@@ -184,14 +184,23 @@ pp2_read_header(uint8_t* buf, size_t buf
 		(header->ver_cmd & 0xF) != PP2_CMD_PROXY) {
 		return PP_PARSE_UNKNOWN_CMD;
 	}
-	/* Check for supported family and protocol */
-	if(header->fam_prot != PP2_UNSPEC_UNSPEC &&
-		header->fam_prot != PP2_INET_STREAM &&
-		header->fam_prot != PP2_INET_DGRAM &&
-		header->fam_prot != PP2_INET6_STREAM &&
-		header->fam_prot != PP2_INET6_DGRAM &&
-		header->fam_prot != PP2_UNIX_STREAM &&
-		header->fam_prot != PP2_UNIX_DGRAM) {
+	/* Check for supported family and protocol, and that len covers
+	 * the per-family address block (proxy-protocol.txt s2.2). */
+	switch(header->fam_prot) {
+	case PP2_UNSPEC_UNSPEC:
+		break;
+	case PP2_INET_STREAM:
+	case PP2_INET_DGRAM:
+		if(ntohs(header->len) < PP2_HEADER_LEN_INET)
+			return PP_PARSE_SIZE;
+		break;
+	case PP2_INET6_STREAM:
+	case PP2_INET6_DGRAM:
+		if(ntohs(header->len) < PP2_HEADER_LEN_INET6)
+			return PP_PARSE_SIZE;
+		break;
+	default:
+		/* PP2_UNIX_STREAM, PP2_UNIX_DGRAM, others. */
 		return PP_PARSE_UNKNOWN_FAM_PROT;
 	}
 	/* We have a correct header */
Index: util/proxy_protocol.h
===================================================================
RCS file: /cvs/src/usr.sbin/nsd/util/proxy_protocol.h,v
diff -u -p -r1.1 proxy_protocol.h
--- util/proxy_protocol.h	20 Dec 2023 17:29:02 -0000	1.1
+++ util/proxy_protocol.h	7 Jul 2026 10:12:26 -0000
@@ -54,6 +54,15 @@
 /** PROXYv2 version (protocol value) */
 #define PP2_VERSION 0x2
 
+/** PROXYv2 minimum header.len value for TCP/UDP over IPv4 */
+#define PP2_HEADER_LEN_INET 12
+
+/** PROXYv2 minimum header.len value for TCP/UDP over IPv6 */
+#define PP2_HEADER_LEN_INET6 36
+
+/** PROXYv2 minimum header.len value for TCP/UDP over AF_UNIX */
+#define PP2_HEADER_LEN_UNIX 216
+
 /**
  * PROXYv2 command (protocol value).
  */
Index: simdzone/configure
===================================================================
RCS file: /cvs/src/usr.sbin/nsd/simdzone/configure,v
diff -u -p -r1.2 configure
--- simdzone/configure	26 Jun 2026 08:55:55 -0000	1.2
+++ simdzone/configure	7 Jul 2026 10:12:26 -0000
@@ -1,11 +1,11 @@
 #! /bin/sh
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.72 for simdzone 0.2.4.
+# Generated by GNU Autoconf 2.71 for simdzone 0.2.5.
 #
 # Report bugs to <https://github.com/NLnetLabs/simdzone/issues>.
 #
 #
-# Copyright (C) 1992-1996, 1998-2017, 2020-2023 Free Software Foundation,
+# Copyright (C) 1992-1996, 1998-2017, 2020-2021 Free Software Foundation,
 # Inc.
 #
 #
@@ -17,6 +17,7 @@
 
 # Be more Bourne compatible
 DUALCASE=1; export DUALCASE # for MKS sh
+as_nop=:
 if test ${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1
 then :
   emulate sh
@@ -25,13 +26,12 @@ then :
   # is contrary to our usage.  Disable this feature.
   alias -g '${1+"$@"}'='"$@"'
   setopt NO_GLOB_SUBST
-else case e in #(
-  e) case `(set -o) 2>/dev/null` in #(
+else $as_nop
+  case `(set -o) 2>/dev/null` in #(
   *posix*) :
     set -o posix ;; #(
   *) :
      ;;
-esac ;;
 esac
 fi
 
@@ -103,7 +103,7 @@ IFS=$as_save_IFS
 
      ;;
 esac
-# We did not find ourselves, most probably we were run as 'sh COMMAND'
+# We did not find ourselves, most probably we were run as `sh COMMAND'
 # in which case we are not to be found in the path.
 if test "x$as_myself" = x; then
   as_myself=$0
@@ -133,14 +133,15 @@ case $- in # ((((
 esac
 exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
 # Admittedly, this is quite paranoid, since all the known shells bail
-# out after a failed 'exec'.
+# out after a failed `exec'.
 printf "%s\n" "$0: could not re-execute with $CONFIG_SHELL" >&2
 exit 255
   fi
   # We don't want this to propagate to other subprocesses.
           { _as_can_reexec=; unset _as_can_reexec;}
 if test "x$CONFIG_SHELL" = x; then
-  as_bourne_compatible="if test \${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1
+  as_bourne_compatible="as_nop=:
+if test \${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1
 then :
   emulate sh
   NULLCMD=:
@@ -148,13 +149,12 @@ then :
   # is contrary to our usage.  Disable this feature.
   alias -g '\${1+\"\$@\"}'='\"\$@\"'
   setopt NO_GLOB_SUBST
-else case e in #(
-  e) case \`(set -o) 2>/dev/null\` in #(
+else \$as_nop
+  case \`(set -o) 2>/dev/null\` in #(
   *posix*) :
     set -o posix ;; #(
   *) :
      ;;
-esac ;;
 esac
 fi
 "
@@ -172,9 +172,8 @@ as_fn_ret_failure && { exitcode=1; echo 
 if ( set x; as_fn_ret_success y && test x = \"\$1\" )
 then :
 
-else case e in #(
-  e) exitcode=1; echo positional parameters were not saved. ;;
-esac
+else \$as_nop
+  exitcode=1; echo positional parameters were not saved.
 fi
 test x\$exitcode = x0 || exit 1
 blah=\$(echo \$(echo blah))
@@ -187,15 +186,14 @@ test -x / || exit 1"
   if (eval "$as_required") 2>/dev/null
 then :
   as_have_required=yes
-else case e in #(
-  e) as_have_required=no ;;
-esac
+else $as_nop
+  as_have_required=no
 fi
   if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null
 then :
 
-else case e in #(
-  e) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+else $as_nop
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
 as_found=false
 for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
 do
@@ -228,13 +226,12 @@ IFS=$as_save_IFS
 if $as_found
 then :
 
-else case e in #(
-  e) if { test -f "$SHELL" || test -f "$SHELL.exe"; } &&
+else $as_nop
+  if { test -f "$SHELL" || test -f "$SHELL.exe"; } &&
 	      as_run=a "$SHELL" -c "$as_bourne_compatible""$as_required" 2>/dev/null
 then :
   CONFIG_SHELL=$SHELL as_have_required=yes
-fi ;;
-esac
+fi
 fi
 
 
@@ -256,7 +253,7 @@ case $- in # ((((
 esac
 exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
 # Admittedly, this is quite paranoid, since all the known shells bail
-# out after a failed 'exec'.
+# out after a failed `exec'.
 printf "%s\n" "$0: could not re-execute with $CONFIG_SHELL" >&2
 exit 255
 fi
@@ -276,8 +273,7 @@ $0: message. Then install a modern shell
 $0: the script under such a shell if you do have one."
   fi
   exit 1
-fi ;;
-esac
+fi
 fi
 fi
 SHELL=${CONFIG_SHELL-/bin/sh}
@@ -316,6 +312,14 @@ as_fn_exit ()
   as_fn_set_status $1
   exit $1
 } # as_fn_exit
+# as_fn_nop
+# ---------
+# Do nothing but, unlike ":", preserve the value of $?.
+as_fn_nop ()
+{
+  return $?
+}
+as_nop=as_fn_nop
 
 # as_fn_mkdir_p
 # -------------
@@ -384,12 +388,11 @@ then :
   {
     eval $1+=\$2
   }'
-else case e in #(
-  e) as_fn_append ()
+else $as_nop
+  as_fn_append ()
   {
     eval $1=\$$1\$2
-  } ;;
-esac
+  }
 fi # as_fn_append
 
 # as_fn_arith ARG...
@@ -403,14 +406,21 @@ then :
   {
     as_val=$(( $* ))
   }'
-else case e in #(
-  e) as_fn_arith ()
+else $as_nop
+  as_fn_arith ()
   {
     as_val=`expr "$@" || test $? -eq 1`
-  } ;;
-esac
+  }
 fi # as_fn_arith
 
+# as_fn_nop
+# ---------
+# Do nothing but, unlike ":", preserve the value of $?.
+as_fn_nop ()
+{
+  return $?
+}
+as_nop=as_fn_nop
 
 # as_fn_error STATUS ERROR [LINENO LOG_FD]
 # ----------------------------------------
@@ -484,8 +494,6 @@ as_cr_alnum=$as_cr_Letters$as_cr_digits
     /[$]LINENO/=
   ' <$as_myself |
     sed '
-      t clear
-      :clear
       s/[$]LINENO.*/&-/
       t lineno
       b
@@ -534,6 +542,7 @@ esac
 as_echo='printf %s\n'
 as_echo_n='printf %s'
 
+
 rm -f conf$$ conf$$.exe conf$$.file
 if test -d conf$$.dir; then
   rm -f conf$$.dir/conf$$.file
@@ -545,9 +554,9 @@ if (echo >conf$$.file) 2>/dev/null; then
   if ln -s conf$$.file conf$$ 2>/dev/null; then
     as_ln_s='ln -s'
     # ... but there are two gotchas:
-    # 1) On MSYS, both 'ln -s file dir' and 'ln file dir' fail.
-    # 2) DJGPP < 2.04 has no symlinks; 'ln -s' creates a wrapper executable.
-    # In both cases, we have to default to 'cp -pR'.
+    # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+    # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+    # In both cases, we have to default to `cp -pR'.
     ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
       as_ln_s='cp -pR'
   elif ln conf$$.file conf$$ 2>/dev/null; then
@@ -572,12 +581,10 @@ as_test_x='test -x'
 as_executable_p=as_fn_executable_p
 
 # Sed expression to map a string onto a valid CPP name.
-as_sed_cpp="y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g"
-as_tr_cpp="eval sed '$as_sed_cpp'" # deprecated
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
 
 # Sed expression to map a string onto a valid variable name.
-as_sed_sh="y%*+%pp%;s%[^_$as_cr_alnum]%_%g"
-as_tr_sh="eval sed '$as_sed_sh'" # deprecated
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
 
 
 test -n "$DJDIR" || exec 7<&0 </dev/null
@@ -603,8 +610,8 @@ MAKEFLAGS=
 # Identity of this package.
 PACKAGE_NAME='simdzone'
 PACKAGE_TARNAME='simdzone'
-PACKAGE_VERSION='0.2.4'
-PACKAGE_STRING='simdzone 0.2.4'
+PACKAGE_VERSION='0.2.5'
+PACKAGE_STRING='simdzone 0.2.5'
 PACKAGE_BUGREPORT='https://github.com/NLnetLabs/simdzone/issues'
 PACKAGE_URL=''
 
@@ -827,7 +834,7 @@ do
     ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
     # Reject names that are not valid shell variable names.
     expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
-      as_fn_error $? "invalid feature name: '$ac_useropt'"
+      as_fn_error $? "invalid feature name: \`$ac_useropt'"
     ac_useropt_orig=$ac_useropt
     ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'`
     case $ac_user_opts in
@@ -853,7 +860,7 @@ do
     ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
     # Reject names that are not valid shell variable names.
     expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
-      as_fn_error $? "invalid feature name: '$ac_useropt'"
+      as_fn_error $? "invalid feature name: \`$ac_useropt'"
     ac_useropt_orig=$ac_useropt
     ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'`
     case $ac_user_opts in
@@ -1066,7 +1073,7 @@ do
     ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
     # Reject names that are not valid shell variable names.
     expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
-      as_fn_error $? "invalid package name: '$ac_useropt'"
+      as_fn_error $? "invalid package name: \`$ac_useropt'"
     ac_useropt_orig=$ac_useropt
     ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'`
     case $ac_user_opts in
@@ -1082,7 +1089,7 @@ do
     ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'`
     # Reject names that are not valid shell variable names.
     expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
-      as_fn_error $? "invalid package name: '$ac_useropt'"
+      as_fn_error $? "invalid package name: \`$ac_useropt'"
     ac_useropt_orig=$ac_useropt
     ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'`
     case $ac_user_opts in
@@ -1112,8 +1119,8 @@ do
   | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
     x_libraries=$ac_optarg ;;
 
-  -*) as_fn_error $? "unrecognized option: '$ac_option'
-Try '$0 --help' for more information"
+  -*) as_fn_error $? "unrecognized option: \`$ac_option'
+Try \`$0 --help' for more information"
     ;;
 
   *=*)
@@ -1121,7 +1128,7 @@ Try '$0 --help' for more information"
     # Reject names that are not valid shell variable names.
     case $ac_envvar in #(
       '' | [0-9]* | *[!_$as_cr_alnum]* )
-      as_fn_error $? "invalid variable name: '$ac_envvar'" ;;
+      as_fn_error $? "invalid variable name: \`$ac_envvar'" ;;
     esac
     eval $ac_envvar=\$ac_optarg
     export $ac_envvar ;;
@@ -1171,7 +1178,7 @@ do
   as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val"
 done
 
-# There might be people who depend on the old broken behavior: '$host'
+# There might be people who depend on the old broken behavior: `$host'
 # used to hold the argument of --host etc.
 # FIXME: To remove some day.
 build=$build_alias
@@ -1239,7 +1246,7 @@ if test ! -r "$srcdir/$ac_unique_file"; 
   test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .."
   as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir"
 fi
-ac_msg="sources are in $srcdir, but 'cd $srcdir' does not work"
+ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work"
 ac_abs_confdir=`(
 	cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg"
 	pwd)`
@@ -1267,7 +1274,7 @@ if test "$ac_init_help" = "long"; then
   # Omit some internal or obsolete options to make the list less imposing.
   # This message is too long to be a string in the A/UX 3.1 sh.
   cat <<_ACEOF
-'configure' configures simdzone 0.2.4 to adapt to many kinds of systems.
+\`configure' configures simdzone 0.2.5 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1281,11 +1288,11 @@ Configuration:
       --help=short        display options specific to this package
       --help=recursive    display the short help of all the included packages
   -V, --version           display version information and exit
-  -q, --quiet, --silent   do not print 'checking ...' messages
+  -q, --quiet, --silent   do not print \`checking ...' messages
       --cache-file=FILE   cache test results in FILE [disabled]
-  -C, --config-cache      alias for '--cache-file=config.cache'
+  -C, --config-cache      alias for \`--cache-file=config.cache'
   -n, --no-create         do not create output files
-      --srcdir=DIR        find the sources in DIR [configure dir or '..']
+      --srcdir=DIR        find the sources in DIR [configure dir or \`..']
 
 Installation directories:
   --prefix=PREFIX         install architecture-independent files in PREFIX
@@ -1293,10 +1300,10 @@ Installation directories:
   --exec-prefix=EPREFIX   install architecture-dependent files in EPREFIX
                           [PREFIX]
 
-By default, 'make install' will install all the files in
-'$ac_default_prefix/bin', '$ac_default_prefix/lib' etc.  You can specify
-an installation prefix other than '$ac_default_prefix' using '--prefix',
-for instance '--prefix=\$HOME'.
+By default, \`make install' will install all the files in
+\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc.  You can specify
+an installation prefix other than \`$ac_default_prefix' using \`--prefix',
+for instance \`--prefix=\$HOME'.
 
 For better control, use the options below.
 
@@ -1334,7 +1341,7 @@ fi
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of simdzone 0.2.4:";;
+     short | recursive ) echo "Configuration of simdzone 0.2.5:";;
    esac
   cat <<\_ACEOF
 
@@ -1356,7 +1363,7 @@ Some influential environment variables:
   CPPFLAGS    (Objective) C/C++ preprocessor flags, e.g. -I<include dir> if
               you have headers in a nonstandard directory <include dir>
 
-Use these variables to override the choices made by 'configure' or to help
+Use these variables to override the choices made by `configure' or to help
 it to find libraries and programs with nonstandard names/locations.
 
 Report bugs to <https://github.com/NLnetLabs/simdzone/issues>.
@@ -1423,10 +1430,10 @@ fi
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-simdzone configure 0.2.4
-generated by GNU Autoconf 2.72
+simdzone configure 0.2.5
+generated by GNU Autoconf 2.71
 
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2021 Free Software Foundation, Inc.
 This configure script is free software; the Free Software Foundation
 gives unlimited permission to copy, distribute and modify it.
 _ACEOF
@@ -1465,12 +1472,11 @@ printf "%s\n" "$ac_try_echo"; } >&5
        } && test -s conftest.$ac_objext
 then :
   ac_retval=0
-else case e in #(
-  e) printf "%s\n" "$as_me: failed program was:" >&5
+else $as_nop
+  printf "%s\n" "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-	ac_retval=1 ;;
-esac
+	ac_retval=1
 fi
   eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
   as_fn_set_status $ac_retval
@@ -1508,12 +1514,11 @@ printf "%s\n" "$ac_try_echo"; } >&5
        }
 then :
   ac_retval=0
-else case e in #(
-  e) printf "%s\n" "$as_me: failed program was:" >&5
+else $as_nop
+  printf "%s\n" "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-	ac_retval=1 ;;
-esac
+	ac_retval=1
 fi
   # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information
   # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would
@@ -1537,8 +1542,8 @@ printf %s "checking for $2... " >&6; }
 if eval test \${$3+y}
 then :
   printf %s "(cached) " >&6
-else case e in #(
-  e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+else $as_nop
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 $4
 #include <$2>
@@ -1546,12 +1551,10 @@ _ACEOF
 if ac_fn_c_try_compile "$LINENO"
 then :
   eval "$3=yes"
-else case e in #(
-  e) eval "$3=no" ;;
-esac
+else $as_nop
+  eval "$3=no"
 fi
-rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;;
-esac
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
 fi
 eval ac_res=\$$3
 	       { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
@@ -1573,8 +1576,8 @@ printf %s "checking whether $as_decl_nam
 if eval test \${$3+y}
 then :
   printf %s "(cached) " >&6
-else case e in #(
-  e) as_decl_use=`echo $2|sed -e 's/(/((/' -e 's/)/) 0&/' -e 's/,/) 0& (/g'`
+else $as_nop
+  as_decl_use=`echo $2|sed -e 's/(/((/' -e 's/)/) 0&/' -e 's/,/) 0& (/g'`
   eval ac_save_FLAGS=\$$6
   as_fn_append $6 " $5"
   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -1598,14 +1601,12 @@ _ACEOF
 if ac_fn_c_try_compile "$LINENO"
 then :
   eval "$3=yes"
-else case e in #(
-  e) eval "$3=no" ;;
-esac
+else $as_nop
+  eval "$3=no"
 fi
 rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
   eval $6=\$ac_save_FLAGS
- ;;
-esac
+
 fi
 eval ac_res=\$$3
 	       { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
@@ -1625,15 +1626,15 @@ printf %s "checking for $2... " >&6; }
 if eval test \${$3+y}
 then :
   printf %s "(cached) " >&6
-else case e in #(
-  e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+else $as_nop
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 /* Define $2 to an innocuous variant, in case <limits.h> declares $2.
    For example, HP-UX 11i <limits.h> declares gettimeofday.  */
 #define $2 innocuous_$2
 
 /* System header to define __stub macros and hopefully few prototypes,
-   which can conflict with char $2 (void); below.  */
+   which can conflict with char $2 (); below.  */
 
 #include <limits.h>
 #undef $2
@@ -1644,7 +1645,7 @@ else case e in #(
 #ifdef __cplusplus
 extern "C"
 #endif
-char $2 (void);
+char $2 ();
 /* The GNU C library defines this for functions which it implements
     to always fail with ENOSYS.  Some functions are actually named
     something starting with __ and the normal name is an alias.  */
@@ -1663,13 +1664,11 @@ _ACEOF
 if ac_fn_c_try_link "$LINENO"
 then :
   eval "$3=yes"
-else case e in #(
-  e) eval "$3=no" ;;
-esac
+else $as_nop
+  eval "$3=no"
 fi
 rm -f core conftest.err conftest.$ac_objext conftest.beam \
-    conftest$ac_exeext conftest.$ac_ext ;;
-esac
+    conftest$ac_exeext conftest.$ac_ext
 fi
 eval ac_res=\$$3
 	       { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
@@ -1701,8 +1700,8 @@ cat >config.log <<_ACEOF
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
-It was created by simdzone $as_me 0.2.4, which was
-generated by GNU Autoconf 2.72.  Invocation command line was
+It was created by simdzone $as_me 0.2.5, which was
+generated by GNU Autoconf 2.71.  Invocation command line was
 
   $ $0$ac_configure_args_raw
 
@@ -1948,10 +1947,10 @@ esac
 printf "%s\n" "$as_me: loading site script $ac_site_file" >&6;}
     sed 's/^/| /' "$ac_site_file" >&5
     . "$ac_site_file" \
-      || { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5
-printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;}
+      || { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
 as_fn_error $? "failed to load site script $ac_site_file
-See 'config.log' for more details" "$LINENO" 5; }
+See \`config.log' for more details" "$LINENO" 5; }
   fi
 done
 
@@ -1987,7 +1986,9 @@ struct stat;
 /* Most of the following tests are stolen from RCS 5.7 src/conf.sh.  */
 struct buf { int x; };
 struct buf * (*rcsopen) (struct buf *, struct stat *, int);
-static char *e (char **p, int i)
+static char *e (p, i)
+     char **p;
+     int i;
 {
   return p[i];
 }
@@ -2001,21 +2002,6 @@ static char *f (char * (*g) (char **, in
   return s;
 }
 
-/* C89 style stringification. */
-#define noexpand_stringify(a) #a
-const char *stringified = noexpand_stringify(arbitrary+token=sequence);
-
-/* C89 style token pasting.  Exercises some of the corner cases that
-   e.g. old MSVC gets wrong, but not very hard. */
-#define noexpand_concat(a,b) a##b
-#define expand_concat(a,b) noexpand_concat(a,b)
-extern int vA;
-extern int vbee;
-#define aye A
-#define bee B
-int *pvA = &expand_concat(v,aye);
-int *pvbee = &noexpand_concat(v,bee);
-
 /* OSF 4.0 Compaq cc is some sort of almost-ANSI by default.  It has
    function prototypes and stuff, but not \xHH hex character constants.
    These do not provoke an error unfortunately, instead are silently treated
@@ -2043,19 +2029,16 @@ ok |= (argc == 0 || f (e, argv, 0) != ar
 
 # Test code for whether the C compiler supports C99 (global declarations)
 ac_c_conftest_c99_globals='
-/* Does the compiler advertise C99 conformance? */
+// Does the compiler advertise C99 conformance?
 #if !defined __STDC_VERSION__ || __STDC_VERSION__ < 199901L
 # error "Compiler does not advertise C99 conformance"
 #endif
 
-// See if C++-style comments work.
-
 #include <stdbool.h>
 extern int puts (const char *);
 extern int printf (const char *, ...);
 extern int dprintf (int, const char *, ...);
 extern void *malloc (size_t);
-extern void free (void *);
 
 // Check varargs macros.  These examples are taken from C99 6.10.3.5.
 // dprintf is used instead of fprintf to avoid needing to declare
@@ -2105,6 +2088,7 @@ typedef const char *ccp;
 static inline int
 test_restrict (ccp restrict text)
 {
+  // See if C++-style comments work.
   // Iterate through items via the restricted pointer.
   // Also check for declarations in for loops.
   for (unsigned int i = 0; *(text+i) != '\''\0'\''; ++i)
@@ -2170,8 +2154,6 @@ ac_c_conftest_c99_main='
   ia->datasize = 10;
   for (int i = 0; i < ia->datasize; ++i)
     ia->data[i] = i * 1.234;
-  // Work around memory leak warnings.
-  free (ia);
 
   // Check named initializers.
   struct named_init ni = {
@@ -2193,7 +2175,7 @@ ac_c_conftest_c99_main='
 
 # Test code for whether the C compiler supports C11 (global declarations)
 ac_c_conftest_c11_globals='
-/* Does the compiler advertise C11 conformance? */
+// Does the compiler advertise C11 conformance?
 #if !defined __STDC_VERSION__ || __STDC_VERSION__ < 201112L
 # error "Compiler does not advertise C11 conformance"
 #endif
@@ -2385,9 +2367,8 @@ IFS=$as_save_IFS
 if $as_found
 then :
 
-else case e in #(
-  e) as_fn_error $? "cannot find required auxiliary files:$ac_missing_aux_files" "$LINENO" 5 ;;
-esac
+else $as_nop
+  as_fn_error $? "cannot find required auxiliary files:$ac_missing_aux_files" "$LINENO" 5
 fi
 
 
@@ -2415,12 +2396,12 @@ for ac_var in $ac_precious_vars; do
   eval ac_new_val=\$ac_env_${ac_var}_value
   case $ac_old_set,$ac_new_set in
     set,)
-      { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: '$ac_var' was set to '$ac_old_val' in the previous run" >&5
-printf "%s\n" "$as_me: error: '$ac_var' was set to '$ac_old_val' in the previous run" >&2;}
+      { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+printf "%s\n" "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
       ac_cache_corrupted=: ;;
     ,set)
-      { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: '$ac_var' was not set in the previous run" >&5
-printf "%s\n" "$as_me: error: '$ac_var' was not set in the previous run" >&2;}
+      { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5
+printf "%s\n" "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
       ac_cache_corrupted=: ;;
     ,);;
     *)
@@ -2429,18 +2410,18 @@ printf "%s\n" "$as_me: error: '$ac_var' 
 	ac_old_val_w=`echo x $ac_old_val`
 	ac_new_val_w=`echo x $ac_new_val`
 	if test "$ac_old_val_w" != "$ac_new_val_w"; then
-	  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: '$ac_var' has changed since the previous run:" >&5
-printf "%s\n" "$as_me: error: '$ac_var' has changed since the previous run:" >&2;}
+	  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5
+printf "%s\n" "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
 	  ac_cache_corrupted=:
 	else
-	  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in '$ac_var' since the previous run:" >&5
-printf "%s\n" "$as_me: warning: ignoring whitespace changes in '$ac_var' since the previous run:" >&2;}
+	  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5
+printf "%s\n" "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;}
 	  eval $ac_var=\$ac_old_val
 	fi
-	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}:   former value:  '$ac_old_val'" >&5
-printf "%s\n" "$as_me:   former value:  '$ac_old_val'" >&2;}
-	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}:   current value: '$ac_new_val'" >&5
-printf "%s\n" "$as_me:   current value: '$ac_new_val'" >&2;}
+	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}:   former value:  \`$ac_old_val'" >&5
+printf "%s\n" "$as_me:   former value:  \`$ac_old_val'" >&2;}
+	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}:   current value: \`$ac_new_val'" >&5
+printf "%s\n" "$as_me:   current value: \`$ac_new_val'" >&2;}
       fi;;
   esac
   # Pass precious variables to config.status.
@@ -2456,11 +2437,11 @@ printf "%s\n" "$as_me:   current value: 
   fi
 done
 if $ac_cache_corrupted; then
-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5
-printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;}
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
   { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5
 printf "%s\n" "$as_me: error: changes in the environment can compromise the build" >&2;}
-  as_fn_error $? "run '${MAKE-make} distclean' and/or 'rm $cache_file'
+  as_fn_error $? "run \`${MAKE-make} distclean' and/or \`rm $cache_file'
 	    and start over" "$LINENO" 5
 fi
 ## -------------------- ##
@@ -2773,8 +2754,8 @@ printf %s "checking for $ac_word... " >&
 if test ${ac_cv_prog_CC+y}
 then :
   printf %s "(cached) " >&6
-else case e in #(
-  e) if test -n "$CC"; then
+else $as_nop
+  if test -n "$CC"; then
   ac_cv_prog_CC="$CC" # Let the user override the test.
 else
 as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
@@ -2796,8 +2777,7 @@ done
   done
 IFS=$as_save_IFS
 
-fi ;;
-esac
+fi
 fi
 CC=$ac_cv_prog_CC
 if test -n "$CC"; then
@@ -2819,8 +2799,8 @@ printf %s "checking for $ac_word... " >&
 if test ${ac_cv_prog_ac_ct_CC+y}
 then :
   printf %s "(cached) " >&6
-else case e in #(
-  e) if test -n "$ac_ct_CC"; then
+else $as_nop
+  if test -n "$ac_ct_CC"; then
   ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
 else
 as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
@@ -2842,8 +2822,7 @@ done
   done
 IFS=$as_save_IFS
 
-fi ;;
-esac
+fi
 fi
 ac_ct_CC=$ac_cv_prog_ac_ct_CC
 if test -n "$ac_ct_CC"; then
@@ -2878,8 +2857,8 @@ printf %s "checking for $ac_word... " >&
 if test ${ac_cv_prog_CC+y}
 then :
   printf %s "(cached) " >&6
-else case e in #(
-  e) if test -n "$CC"; then
+else $as_nop
+  if test -n "$CC"; then
   ac_cv_prog_CC="$CC" # Let the user override the test.
 else
 as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
@@ -2901,8 +2880,7 @@ done
   done
 IFS=$as_save_IFS
 
-fi ;;
-esac
+fi
 fi
 CC=$ac_cv_prog_CC
 if test -n "$CC"; then
@@ -2924,8 +2902,8 @@ printf %s "checking for $ac_word... " >&
 if test ${ac_cv_prog_CC+y}
 then :
   printf %s "(cached) " >&6
-else case e in #(
-  e) if test -n "$CC"; then
+else $as_nop
+  if test -n "$CC"; then
   ac_cv_prog_CC="$CC" # Let the user override the test.
 else
   ac_prog_rejected=no
@@ -2964,8 +2942,7 @@ if test $ac_prog_rejected = yes; then
     ac_cv_prog_CC="$as_dir$ac_word${1+' '}$@"
   fi
 fi
-fi ;;
-esac
+fi
 fi
 CC=$ac_cv_prog_CC
 if test -n "$CC"; then
@@ -2989,8 +2966,8 @@ printf %s "checking for $ac_word... " >&
 if test ${ac_cv_prog_CC+y}
 then :
   printf %s "(cached) " >&6
-else case e in #(
-  e) if test -n "$CC"; then
+else $as_nop
+  if test -n "$CC"; then
   ac_cv_prog_CC="$CC" # Let the user override the test.
 else
 as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
@@ -3012,8 +2989,7 @@ done
   done
 IFS=$as_save_IFS
 
-fi ;;
-esac
+fi
 fi
 CC=$ac_cv_prog_CC
 if test -n "$CC"; then
@@ -3039,8 +3015,8 @@ printf %s "checking for $ac_word... " >&
 if test ${ac_cv_prog_ac_ct_CC+y}
 then :
   printf %s "(cached) " >&6
-else case e in #(
-  e) if test -n "$ac_ct_CC"; then
+else $as_nop
+  if test -n "$ac_ct_CC"; then
   ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
 else
 as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
@@ -3062,8 +3038,7 @@ done
   done
 IFS=$as_save_IFS
 
-fi ;;
-esac
+fi
 fi
 ac_ct_CC=$ac_cv_prog_ac_ct_CC
 if test -n "$ac_ct_CC"; then
@@ -3101,8 +3076,8 @@ printf %s "checking for $ac_word... " >&
 if test ${ac_cv_prog_CC+y}
 then :
   printf %s "(cached) " >&6
-else case e in #(
-  e) if test -n "$CC"; then
+else $as_nop
+  if test -n "$CC"; then
   ac_cv_prog_CC="$CC" # Let the user override the test.
 else
 as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
@@ -3124,8 +3099,7 @@ done
   done
 IFS=$as_save_IFS
 
-fi ;;
-esac
+fi
 fi
 CC=$ac_cv_prog_CC
 if test -n "$CC"; then
@@ -3147,8 +3121,8 @@ printf %s "checking for $ac_word... " >&
 if test ${ac_cv_prog_ac_ct_CC+y}
 then :
   printf %s "(cached) " >&6
-else case e in #(
-  e) if test -n "$ac_ct_CC"; then
+else $as_nop
+  if test -n "$ac_ct_CC"; then
   ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
 else
 as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
@@ -3170,8 +3144,7 @@ done
   done
 IFS=$as_save_IFS
 
-fi ;;
-esac
+fi
 fi
 ac_ct_CC=$ac_cv_prog_ac_ct_CC
 if test -n "$ac_ct_CC"; then
@@ -3200,10 +3173,10 @@ fi
 fi
 
 
-test -z "$CC" && { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5
-printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;}
+test -z "$CC" && { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
 as_fn_error $? "no acceptable C compiler found in \$PATH
-See 'config.log' for more details" "$LINENO" 5; }
+See \`config.log' for more details" "$LINENO" 5; }
 
 # Provide some information about the compiler.
 printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5
@@ -3275,8 +3248,8 @@ printf "%s\n" "$ac_try_echo"; } >&5
   printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
   test $ac_status = 0; }
 then :
-  # Autoconf-2.13 could set the ac_cv_exeext variable to 'no'.
-# So ignore a value of 'no', otherwise this would lead to 'EXEEXT = no'
+  # Autoconf-2.13 could set the ac_cv_exeext variable to `no'.
+# So ignore a value of `no', otherwise this would lead to `EXEEXT = no'
 # in a Makefile.  We should not override ac_cv_exeext if it was cached,
 # so that the user can short-circuit this test for compilers unknown to
 # Autoconf.
@@ -3296,7 +3269,7 @@ do
 	   ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
 	fi
 	# We set ac_cv_exeext here because the later test for it is not
-	# safe: cross compilers may not add the suffix if given an '-o'
+	# safe: cross compilers may not add the suffix if given an `-o'
 	# argument, so we may need to know it at that point already.
 	# Even if this section looks crufty: it has the advantage of
 	# actually working.
@@ -3307,9 +3280,8 @@ do
 done
 test "$ac_cv_exeext" = no && ac_cv_exeext=
 
-else case e in #(
-  e) ac_file='' ;;
-esac
+else $as_nop
+  ac_file=''
 fi
 if test -z "$ac_file"
 then :
@@ -3318,14 +3290,13 @@ printf "%s\n" "no" >&6; }
 printf "%s\n" "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5
-printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;}
+{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
 as_fn_error 77 "C compiler cannot create executables
-See 'config.log' for more details" "$LINENO" 5; }
-else case e in #(
-  e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-printf "%s\n" "yes" >&6; } ;;
-esac
+See \`config.log' for more details" "$LINENO" 5; }
+else $as_nop
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
 fi
 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5
 printf %s "checking for C compiler default output file name... " >&6; }
@@ -3349,10 +3320,10 @@ printf "%s\n" "$ac_try_echo"; } >&5
   printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
   test $ac_status = 0; }
 then :
-  # If both 'conftest.exe' and 'conftest' are 'present' (well, observable)
-# catch 'conftest.exe'.  For instance with Cygwin, 'ls conftest' will
-# work properly (i.e., refer to 'conftest.exe'), while it won't with
-# 'rm'.
+  # If both `conftest.exe' and `conftest' are `present' (well, observable)
+# catch `conftest.exe'.  For instance with Cygwin, `ls conftest' will
+# work properly (i.e., refer to `conftest.exe'), while it won't with
+# `rm'.
 for ac_file in conftest.exe conftest conftest.*; do
   test -f "$ac_file" || continue
   case $ac_file in
@@ -3362,12 +3333,11 @@ for ac_file in conftest.exe conftest con
     * ) break;;
   esac
 done
-else case e in #(
-  e) { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5
-printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;}
+else $as_nop
+  { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
 as_fn_error $? "cannot compute suffix of executables: cannot compile and link
-See 'config.log' for more details" "$LINENO" 5; } ;;
-esac
+See \`config.log' for more details" "$LINENO" 5; }
 fi
 rm -f conftest conftest$ac_cv_exeext
 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5
@@ -3383,8 +3353,6 @@ int
 main (void)
 {
 FILE *f = fopen ("conftest.out", "w");
- if (!f)
-  return 1;
  return ferror (f) || fclose (f) != 0;
 
   ;
@@ -3424,27 +3392,26 @@ printf "%s\n" "$ac_try_echo"; } >&5
     if test "$cross_compiling" = maybe; then
 	cross_compiling=yes
     else
-	{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5
-printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;}
+	{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
 as_fn_error 77 "cannot run C compiled programs.
-If you meant to cross compile, use '--host'.
-See 'config.log' for more details" "$LINENO" 5; }
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details" "$LINENO" 5; }
     fi
   fi
 fi
 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5
 printf "%s\n" "$cross_compiling" >&6; }
 
-rm -f conftest.$ac_ext conftest$ac_cv_exeext \
-  conftest.o conftest.obj conftest.out
+rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out
 ac_clean_files=$ac_clean_files_save
 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5
 printf %s "checking for suffix of object files... " >&6; }
 if test ${ac_cv_objext+y}
 then :
   printf %s "(cached) " >&6
-else case e in #(
-  e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+else $as_nop
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
 int
@@ -3476,18 +3443,16 @@ then :
        break;;
   esac
 done
-else case e in #(
-  e) printf "%s\n" "$as_me: failed program was:" >&5
+else $as_nop
+  printf "%s\n" "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5
-printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;}
+{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
 as_fn_error $? "cannot compute suffix of object files: cannot compile
-See 'config.log' for more details" "$LINENO" 5; } ;;
-esac
+See \`config.log' for more details" "$LINENO" 5; }
 fi
-rm -f conftest.$ac_cv_objext conftest.$ac_ext ;;
-esac
+rm -f conftest.$ac_cv_objext conftest.$ac_ext
 fi
 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5
 printf "%s\n" "$ac_cv_objext" >&6; }
@@ -3498,8 +3463,8 @@ printf %s "checking whether the compiler
 if test ${ac_cv_c_compiler_gnu+y}
 then :
   printf %s "(cached) " >&6
-else case e in #(
-  e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+else $as_nop
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
 int
@@ -3516,14 +3481,12 @@ _ACEOF
 if ac_fn_c_try_compile "$LINENO"
 then :
   ac_compiler_gnu=yes
-else case e in #(
-  e) ac_compiler_gnu=no ;;
-esac
+else $as_nop
+  ac_compiler_gnu=no
 fi
 rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
 ac_cv_c_compiler_gnu=$ac_compiler_gnu
- ;;
-esac
+
 fi
 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5
 printf "%s\n" "$ac_cv_c_compiler_gnu" >&6; }
@@ -3541,8 +3504,8 @@ printf %s "checking whether $CC accepts 
 if test ${ac_cv_prog_cc_g+y}
 then :
   printf %s "(cached) " >&6
-else case e in #(
-  e) ac_save_c_werror_flag=$ac_c_werror_flag
+else $as_nop
+  ac_save_c_werror_flag=$ac_c_werror_flag
    ac_c_werror_flag=yes
    ac_cv_prog_cc_g=no
    CFLAGS="-g"
@@ -3560,8 +3523,8 @@ _ACEOF
 if ac_fn_c_try_compile "$LINENO"
 then :
   ac_cv_prog_cc_g=yes
-else case e in #(
-  e) CFLAGS=""
+else $as_nop
+  CFLAGS=""
       cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
@@ -3576,8 +3539,8 @@ _ACEOF
 if ac_fn_c_try_compile "$LINENO"
 then :
 
-else case e in #(
-  e) ac_c_werror_flag=$ac_save_c_werror_flag
+else $as_nop
+  ac_c_werror_flag=$ac_save_c_werror_flag
 	 CFLAGS="-g"
 	 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
@@ -3594,15 +3557,12 @@ if ac_fn_c_try_compile "$LINENO"
 then :
   ac_cv_prog_cc_g=yes
 fi
-rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;;
-esac
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
 fi
-rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;;
-esac
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
 fi
 rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
-   ac_c_werror_flag=$ac_save_c_werror_flag ;;
-esac
+   ac_c_werror_flag=$ac_save_c_werror_flag
 fi
 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5
 printf "%s\n" "$ac_cv_prog_cc_g" >&6; }
@@ -3629,8 +3589,8 @@ printf %s "checking for $CC option to en
 if test ${ac_cv_prog_cc_c11+y}
 then :
   printf %s "(cached) " >&6
-else case e in #(
-  e) ac_cv_prog_cc_c11=no
+else $as_nop
+  ac_cv_prog_cc_c11=no
 ac_save_CC=$CC
 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
@@ -3647,28 +3607,25 @@ rm -f core conftest.err conftest.$ac_obj
   test "x$ac_cv_prog_cc_c11" != "xno" && break
 done
 rm -f conftest.$ac_ext
-CC=$ac_save_CC ;;
-esac
+CC=$ac_save_CC
 fi
 
 if test "x$ac_cv_prog_cc_c11" = xno
 then :
   { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
 printf "%s\n" "unsupported" >&6; }
-else case e in #(
-  e) if test "x$ac_cv_prog_cc_c11" = x
+else $as_nop
+  if test "x$ac_cv_prog_cc_c11" = x
 then :
   { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
 printf "%s\n" "none needed" >&6; }
-else case e in #(
-  e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c11" >&5
+else $as_nop
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c11" >&5
 printf "%s\n" "$ac_cv_prog_cc_c11" >&6; }
-     CC="$CC $ac_cv_prog_cc_c11" ;;
-esac
+     CC="$CC $ac_cv_prog_cc_c11"
 fi
   ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c11
-  ac_prog_cc_stdc=c11 ;;
-esac
+  ac_prog_cc_stdc=c11
 fi
 fi
 if test x$ac_prog_cc_stdc = xno
@@ -3678,8 +3635,8 @@ printf %s "checking for $CC option to en
 if test ${ac_cv_prog_cc_c99+y}
 then :
   printf %s "(cached) " >&6
-else case e in #(
-  e) ac_cv_prog_cc_c99=no
+else $as_nop
+  ac_cv_prog_cc_c99=no
 ac_save_CC=$CC
 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
@@ -3696,28 +3653,25 @@ rm -f core conftest.err conftest.$ac_obj
   test "x$ac_cv_prog_cc_c99" != "xno" && break
 done
 rm -f conftest.$ac_ext
-CC=$ac_save_CC ;;
-esac
+CC=$ac_save_CC
 fi
 
 if test "x$ac_cv_prog_cc_c99" = xno
 then :
   { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
 printf "%s\n" "unsupported" >&6; }
-else case e in #(
-  e) if test "x$ac_cv_prog_cc_c99" = x
+else $as_nop
+  if test "x$ac_cv_prog_cc_c99" = x
 then :
   { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
 printf "%s\n" "none needed" >&6; }
-else case e in #(
-  e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c99" >&5
+else $as_nop
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c99" >&5
 printf "%s\n" "$ac_cv_prog_cc_c99" >&6; }
-     CC="$CC $ac_cv_prog_cc_c99" ;;
-esac
+     CC="$CC $ac_cv_prog_cc_c99"
 fi
   ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c99
-  ac_prog_cc_stdc=c99 ;;
-esac
+  ac_prog_cc_stdc=c99
 fi
 fi
 if test x$ac_prog_cc_stdc = xno
@@ -3727,8 +3681,8 @@ printf %s "checking for $CC option to en
 if test ${ac_cv_prog_cc_c89+y}
 then :
   printf %s "(cached) " >&6
-else case e in #(
-  e) ac_cv_prog_cc_c89=no
+else $as_nop
+  ac_cv_prog_cc_c89=no
 ac_save_CC=$CC
 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
@@ -3745,28 +3699,25 @@ rm -f core conftest.err conftest.$ac_obj
   test "x$ac_cv_prog_cc_c89" != "xno" && break
 done
 rm -f conftest.$ac_ext
-CC=$ac_save_CC ;;
-esac
+CC=$ac_save_CC
 fi
 
 if test "x$ac_cv_prog_cc_c89" = xno
 then :
   { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
 printf "%s\n" "unsupported" >&6; }
-else case e in #(
-  e) if test "x$ac_cv_prog_cc_c89" = x
+else $as_nop
+  if test "x$ac_cv_prog_cc_c89" = x
 then :
   { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
 printf "%s\n" "none needed" >&6; }
-else case e in #(
-  e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5
+else $as_nop
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5
 printf "%s\n" "$ac_cv_prog_cc_c89" >&6; }
-     CC="$CC $ac_cv_prog_cc_c89" ;;
-esac
+     CC="$CC $ac_cv_prog_cc_c89"
 fi
   ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c89
-  ac_prog_cc_stdc=c89 ;;
-esac
+  ac_prog_cc_stdc=c89
 fi
 fi
 
@@ -3787,8 +3738,8 @@ cache=`echo g | sed 'y%.=/+-%___p_%'`
 if eval test \${cv_prog_cc_flag_$cache+y}
 then :
   printf %s "(cached) " >&6
-else case e in #(
-  e)
+else $as_nop
+
 echo 'void f(void){}' >conftest.c
 if test -z "`$CC $CPPFLAGS $CFLAGS -g -c conftest.c 2>&1`"; then
 eval "cv_prog_cc_flag_$cache=yes"
@@ -3796,8 +3747,7 @@ else
 eval "cv_prog_cc_flag_$cache=no"
 fi
 rm -f conftest conftest.o conftest.c
- ;;
-esac
+
 fi
 
 if eval "test \"`echo '$cv_prog_cc_flag_'$cache`\" = yes"; then
@@ -3820,8 +3770,8 @@ cache=`echo O2 | sed 'y%.=/+-%___p_%'`
 if eval test \${cv_prog_cc_flag_$cache+y}
 then :
   printf %s "(cached) " >&6
-else case e in #(
-  e)
+else $as_nop
+
 echo 'void f(void){}' >conftest.c
 if test -z "`$CC $CPPFLAGS $CFLAGS -O2 -c conftest.c 2>&1`"; then
 eval "cv_prog_cc_flag_$cache=yes"
@@ -3829,8 +3779,7 @@ else
 eval "cv_prog_cc_flag_$cache=no"
 fi
 rm -f conftest conftest.o conftest.c
- ;;
-esac
+
 fi
 
 if eval "test \"`echo '$cv_prog_cc_flag_'$cache`\" = yes"; then
@@ -3886,10 +3835,9 @@ printf "%s\n" "yes" >&6; }
 	    fi
 	    rm -f conftest conftest.c conftest.o
 
-else case e in #(
-  e) LDFLAGS="$BAKLDFLAGS" ; CFLAGS="$BAKCFLAGS" ; { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
-printf "%s\n" "no" >&6; } ;;
-esac
+else $as_nop
+  LDFLAGS="$BAKLDFLAGS" ; CFLAGS="$BAKCFLAGS" ; { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
 fi
 rm -f core conftest.err conftest.$ac_objext conftest.beam \
     conftest$ac_exeext conftest.$ac_ext
@@ -3947,8 +3895,8 @@ printf %s "checking for $CC options need
 if test ${ac_cv_c_undeclared_builtin_options+y}
 then :
   printf %s "(cached) " >&6
-else case e in #(
-  e) ac_save_CFLAGS=$CFLAGS
+else $as_nop
+  ac_save_CFLAGS=$CFLAGS
    ac_cv_c_undeclared_builtin_options='cannot detect'
    for ac_arg in '' -fno-builtin; do
      CFLAGS="$ac_save_CFLAGS $ac_arg"
@@ -3967,8 +3915,8 @@ _ACEOF
 if ac_fn_c_try_compile "$LINENO"
 then :
 
-else case e in #(
-  e) # This test program should compile successfully.
+else $as_nop
+  # This test program should compile successfully.
         # No library function is consistently available on
         # freestanding implementations, so test against a dummy
         # declaration.  Include always-available headers on the
@@ -3996,29 +3944,26 @@ then :
   if test x"$ac_arg" = x
 then :
   ac_cv_c_undeclared_builtin_options='none needed'
-else case e in #(
-  e) ac_cv_c_undeclared_builtin_options=$ac_arg ;;
-esac
+else $as_nop
+  ac_cv_c_undeclared_builtin_options=$ac_arg
 fi
           break
 fi
-rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;;
-esac
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
 fi
 rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
     done
     CFLAGS=$ac_save_CFLAGS
-   ;;
-esac
+
 fi
 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_undeclared_builtin_options" >&5
 printf "%s\n" "$ac_cv_c_undeclared_builtin_options" >&6; }
   case $ac_cv_c_undeclared_builtin_options in #(
   'cannot detect') :
-    { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5
-printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;}
+    { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
 as_fn_error $? "cannot make $CC report undeclared builtins
-See 'config.log' for more details" "$LINENO" 5; } ;; #(
+See \`config.log' for more details" "$LINENO" 5; } ;; #(
   'none needed') :
     ac_c_undeclared_builtin_options='' ;; #(
   *) :
@@ -4038,9 +3983,8 @@ $ac_includes_default
 if test "x$ac_cv_have_decl_bswap16" = xyes
 then :
   ac_have_decl=1
-else case e in #(
-  e) ac_have_decl=0 ;;
-esac
+else $as_nop
+  ac_have_decl=0
 fi
 printf "%s\n" "#define HAVE_DECL_BSWAP16 $ac_have_decl" >>confdefs.h
 ac_fn_check_decl "$LINENO" "bswap32" "ac_cv_have_decl_bswap32" "
@@ -4056,9 +4000,8 @@ $ac_includes_default
 if test "x$ac_cv_have_decl_bswap32" = xyes
 then :
   ac_have_decl=1
-else case e in #(
-  e) ac_have_decl=0 ;;
-esac
+else $as_nop
+  ac_have_decl=0
 fi
 printf "%s\n" "#define HAVE_DECL_BSWAP32 $ac_have_decl" >>confdefs.h
 ac_fn_check_decl "$LINENO" "bswap64" "ac_cv_have_decl_bswap64" "
@@ -4074,9 +4017,8 @@ $ac_includes_default
 if test "x$ac_cv_have_decl_bswap64" = xyes
 then :
   ac_have_decl=1
-else case e in #(
-  e) ac_have_decl=0 ;;
-esac
+else $as_nop
+  ac_have_decl=0
 fi
 printf "%s\n" "#define HAVE_DECL_BSWAP64 $ac_have_decl" >>confdefs.h
 
@@ -4109,8 +4051,8 @@ printf %s "checking whether C compiler a
 if test ${ax_cv_check_cflags___MMD+y}
 then :
   printf %s "(cached) " >&6
-else case e in #(
-  e)
+else $as_nop
+
   ax_check_save_flags=$CFLAGS
   CFLAGS="$CFLAGS  -MMD"
   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -4127,22 +4069,19 @@ _ACEOF
 if ac_fn_c_try_compile "$LINENO"
 then :
   ax_cv_check_cflags___MMD=yes
-else case e in #(
-  e) ax_cv_check_cflags___MMD=no ;;
-esac
+else $as_nop
+  ax_cv_check_cflags___MMD=no
 fi
 rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
-  CFLAGS=$ax_check_save_flags ;;
-esac
+  CFLAGS=$ax_check_save_flags
 fi
 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___MMD" >&5
 printf "%s\n" "$ax_cv_check_cflags___MMD" >&6; }
 if test "x$ax_cv_check_cflags___MMD" = xyes
 then :
   DEPFLAGS="-MMD -MP"
-else case e in #(
-  e) : ;;
-esac
+else $as_nop
+  :
 fi
 
 # Oracle Developer Studio (no -MP)
@@ -4151,8 +4090,8 @@ printf %s "checking whether C compiler a
 if test ${ax_cv_check_cflags___xMMD+y}
 then :
   printf %s "(cached) " >&6
-else case e in #(
-  e)
+else $as_nop
+
   ax_check_save_flags=$CFLAGS
   CFLAGS="$CFLAGS  -xMMD"
   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -4169,22 +4108,19 @@ _ACEOF
 if ac_fn_c_try_compile "$LINENO"
 then :
   ax_cv_check_cflags___xMMD=yes
-else case e in #(
-  e) ax_cv_check_cflags___xMMD=no ;;
-esac
+else $as_nop
+  ax_cv_check_cflags___xMMD=no
 fi
 rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
-  CFLAGS=$ax_check_save_flags ;;
-esac
+  CFLAGS=$ax_check_save_flags
 fi
 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___xMMD" >&5
 printf "%s\n" "$ax_cv_check_cflags___xMMD" >&6; }
 if test "x$ax_cv_check_cflags___xMMD" = xyes
 then :
   DEPFLAGS="-xMMD"
-else case e in #(
-  e) : ;;
-esac
+else $as_nop
+  :
 fi
 
 
@@ -4203,16 +4139,15 @@ printf %s "checking build system type...
 if test ${ac_cv_build+y}
 then :
   printf %s "(cached) " >&6
-else case e in #(
-  e) ac_build_alias=$build_alias
+else $as_nop
+  ac_build_alias=$build_alias
 test "x$ac_build_alias" = x &&
   ac_build_alias=`$SHELL "${ac_aux_dir}config.guess"`
 test "x$ac_build_alias" = x &&
   as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5
 ac_cv_build=`$SHELL "${ac_aux_dir}config.sub" $ac_build_alias` ||
   as_fn_error $? "$SHELL ${ac_aux_dir}config.sub $ac_build_alias failed" "$LINENO" 5
- ;;
-esac
+
 fi
 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5
 printf "%s\n" "$ac_cv_build" >&6; }
@@ -4239,15 +4174,14 @@ printf %s "checking host system type... 
 if test ${ac_cv_host+y}
 then :
   printf %s "(cached) " >&6
-else case e in #(
-  e) if test "x$host_alias" = x; then
+else $as_nop
+  if test "x$host_alias" = x; then
   ac_cv_host=$ac_cv_build
 else
   ac_cv_host=`$SHELL "${ac_aux_dir}config.sub" $host_alias` ||
     as_fn_error $? "$SHELL ${ac_aux_dir}config.sub $host_alias failed" "$LINENO" 5
 fi
- ;;
-esac
+
 fi
 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5
 printf "%s\n" "$ac_cv_host" >&6; }
@@ -4274,15 +4208,14 @@ printf %s "checking target system type..
 if test ${ac_cv_target+y}
 then :
   printf %s "(cached) " >&6
-else case e in #(
-  e) if test "x$target_alias" = x; then
+else $as_nop
+  if test "x$target_alias" = x; then
   ac_cv_target=$ac_cv_host
 else
   ac_cv_target=`$SHELL "${ac_aux_dir}config.sub" $target_alias` ||
     as_fn_error $? "$SHELL ${ac_aux_dir}config.sub $target_alias failed" "$LINENO" 5
 fi
- ;;
-esac
+
 fi
 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_target" >&5
 printf "%s\n" "$ac_cv_target" >&6; }
@@ -4336,8 +4269,8 @@ printf %s "checking whether C compiler a
 if test ${ax_cv_check_cflags__Werror__march_westmere+y}
 then :
   printf %s "(cached) " >&6
-else case e in #(
-  e)
+else $as_nop
+
   ax_check_save_flags=$CFLAGS
   CFLAGS="$CFLAGS -Werror -march=westmere"
   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -4354,22 +4287,19 @@ _ACEOF
 if ac_fn_c_try_compile "$LINENO"
 then :
   ax_cv_check_cflags__Werror__march_westmere=yes
-else case e in #(
-  e) ax_cv_check_cflags__Werror__march_westmere=no ;;
-esac
+else $as_nop
+  ax_cv_check_cflags__Werror__march_westmere=no
 fi
 rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
-  CFLAGS=$ax_check_save_flags ;;
-esac
+  CFLAGS=$ax_check_save_flags
 fi
 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags__Werror__march_westmere" >&5
 printf "%s\n" "$ax_cv_check_cflags__Werror__march_westmere" >&6; }
 if test "x$ax_cv_check_cflags__Werror__march_westmere" = xyes
 then :
   :
-else case e in #(
-  e) : ;;
-esac
+else $as_nop
+  :
 fi
 
   { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -march=haswell" >&5
@@ -4377,8 +4307,8 @@ printf %s "checking whether C compiler a
 if test ${ax_cv_check_cflags__Werror__march_haswell+y}
 then :
   printf %s "(cached) " >&6
-else case e in #(
-  e)
+else $as_nop
+
   ax_check_save_flags=$CFLAGS
   CFLAGS="$CFLAGS -Werror -march=haswell"
   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -4395,22 +4325,19 @@ _ACEOF
 if ac_fn_c_try_compile "$LINENO"
 then :
   ax_cv_check_cflags__Werror__march_haswell=yes
-else case e in #(
-  e) ax_cv_check_cflags__Werror__march_haswell=no ;;
-esac
+else $as_nop
+  ax_cv_check_cflags__Werror__march_haswell=no
 fi
 rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
-  CFLAGS=$ax_check_save_flags ;;
-esac
+  CFLAGS=$ax_check_save_flags
 fi
 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags__Werror__march_haswell" >&5
 printf "%s\n" "$ax_cv_check_cflags__Werror__march_haswell" >&6; }
 if test "x$ax_cv_check_cflags__Werror__march_haswell" = xyes
 then :
   :
-else case e in #(
-  e) : ;;
-esac
+else $as_nop
+  :
 fi
 
 
@@ -4449,12 +4376,11 @@ printf "%s\n" "#define HAVE_WESTMERE 1" 
     { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
 printf "%s\n" "yes" >&6; }
 
-else case e in #(
-  e)
+else $as_nop
+
     { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
 printf "%s\n" "no" >&6; }
- ;;
-esac
+
 fi
 rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
     CFLAGS="$BAKCFLAGS"
@@ -4495,12 +4421,11 @@ printf "%s\n" "#define HAVE_HASWELL 1" >
     { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
 printf "%s\n" "yes" >&6; }
 
-else case e in #(
-  e)
+else $as_nop
+
     { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
 printf "%s\n" "no" >&6; }
- ;;
-esac
+
 fi
 rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
     CFLAGS="$BAKCFLAGS"
@@ -4515,9 +4440,8 @@ if test "x$ac_cv_func_realpath" = xyes
 then :
   printf "%s\n" "#define HAVE_REALPATH 1" >>confdefs.h
 
-else case e in #(
-  e) as_fn_error $? "realpath is not available" "$LINENO" 5 ;;
-esac
+else $as_nop
+  as_fn_error $? "realpath is not available" "$LINENO" 5
 fi
 
 done
@@ -4538,8 +4462,8 @@ cat >confcache <<\_ACEOF
 # config.status only pays attention to the cache file if you give it
 # the --recheck option to rerun configure.
 #
-# 'ac_cv_env_foo' variables (set or unset) will be overridden when
-# loading this file, other *unset* 'ac_cv_foo' will be assigned the
+# `ac_cv_env_foo' variables (set or unset) will be overridden when
+# loading this file, other *unset* `ac_cv_foo' will be assigned the
 # following values.
 
 _ACEOF
@@ -4569,14 +4493,14 @@ printf "%s\n" "$as_me: WARNING: cache va
   (set) 2>&1 |
     case $as_nl`(ac_space=' '; set) 2>&1` in #(
     *${as_nl}ac_space=\ *)
-      # 'set' does not quote correctly, so add quotes: double-quote
+      # `set' does not quote correctly, so add quotes: double-quote
       # substitution turns \\\\ into \\, and sed turns \\ into \.
       sed -n \
 	"s/'/'\\\\''/g;
 	  s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
       ;; #(
     *)
-      # 'set' quotes correctly as required by POSIX, so do not add quotes.
+      # `set' quotes correctly as required by POSIX, so do not add quotes.
       sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
       ;;
     esac |
@@ -4666,6 +4590,7 @@ cat >>$CONFIG_STATUS <<\_ASEOF || as_wri
 
 # Be more Bourne compatible
 DUALCASE=1; export DUALCASE # for MKS sh
+as_nop=:
 if test ${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1
 then :
   emulate sh
@@ -4674,13 +4599,12 @@ then :
   # is contrary to our usage.  Disable this feature.
   alias -g '${1+"$@"}'='"$@"'
   setopt NO_GLOB_SUBST
-else case e in #(
-  e) case `(set -o) 2>/dev/null` in #(
+else $as_nop
+  case `(set -o) 2>/dev/null` in #(
   *posix*) :
     set -o posix ;; #(
   *) :
      ;;
-esac ;;
 esac
 fi
 
@@ -4752,7 +4676,7 @@ IFS=$as_save_IFS
 
      ;;
 esac
-# We did not find ourselves, most probably we were run as 'sh COMMAND'
+# We did not find ourselves, most probably we were run as `sh COMMAND'
 # in which case we are not to be found in the path.
 if test "x$as_myself" = x; then
   as_myself=$0
@@ -4781,6 +4705,7 @@ as_fn_error ()
 } # as_fn_error
 
 
+
 # as_fn_set_status STATUS
 # -----------------------
 # Set $? to STATUS, without forking.
@@ -4820,12 +4745,11 @@ then :
   {
     eval $1+=\$2
   }'
-else case e in #(
-  e) as_fn_append ()
+else $as_nop
+  as_fn_append ()
   {
     eval $1=\$$1\$2
-  } ;;
-esac
+  }
 fi # as_fn_append
 
 # as_fn_arith ARG...
@@ -4839,12 +4763,11 @@ then :
   {
     as_val=$(( $* ))
   }'
-else case e in #(
-  e) as_fn_arith ()
+else $as_nop
+  as_fn_arith ()
   {
     as_val=`expr "$@" || test $? -eq 1`
-  } ;;
-esac
+  }
 fi # as_fn_arith
 
 
@@ -4927,9 +4850,9 @@ if (echo >conf$$.file) 2>/dev/null; then
   if ln -s conf$$.file conf$$ 2>/dev/null; then
     as_ln_s='ln -s'
     # ... but there are two gotchas:
-    # 1) On MSYS, both 'ln -s file dir' and 'ln file dir' fail.
-    # 2) DJGPP < 2.04 has no symlinks; 'ln -s' creates a wrapper executable.
-    # In both cases, we have to default to 'cp -pR'.
+    # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+    # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+    # In both cases, we have to default to `cp -pR'.
     ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
       as_ln_s='cp -pR'
   elif ln conf$$.file conf$$ 2>/dev/null; then
@@ -5010,12 +4933,10 @@ as_test_x='test -x'
 as_executable_p=as_fn_executable_p
 
 # Sed expression to map a string onto a valid CPP name.
-as_sed_cpp="y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g"
-as_tr_cpp="eval sed '$as_sed_cpp'" # deprecated
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
 
 # Sed expression to map a string onto a valid variable name.
-as_sed_sh="y%*+%pp%;s%[^_$as_cr_alnum]%_%g"
-as_tr_sh="eval sed '$as_sed_sh'" # deprecated
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
 
 
 exec 6>&1
@@ -5030,8 +4951,8 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_wri
 # report actual input values of CONFIG_FILES etc. instead of their
 # values after options handling.
 ac_log="
-This file was extended by simdzone $as_me 0.2.4, which was
-generated by GNU Autoconf 2.72.  Invocation command line was
+This file was extended by simdzone $as_me 0.2.5, which was
+generated by GNU Autoconf 2.71.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
   CONFIG_HEADERS  = $CONFIG_HEADERS
@@ -5062,7 +4983,7 @@ _ACEOF
 
 cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
 ac_cs_usage="\
-'$as_me' instantiates files and other configuration actions
+\`$as_me' instantiates files and other configuration actions
 from templates according to the current configuration.  Unless the files
 and actions are specified as TAGs, all are instantiated by default.
 
@@ -5094,11 +5015,11 @@ ac_cs_config_escaped=`printf "%s\n" "$ac
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 ac_cs_config='$ac_cs_config_escaped'
 ac_cs_version="\\
-simdzone config.status 0.2.4
-configured by $0, generated by GNU Autoconf 2.72,
+simdzone config.status 0.2.5
+configured by $0, generated by GNU Autoconf 2.71,
   with options \\"\$ac_cs_config\\"
 
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2021 Free Software Foundation, Inc.
 This config.status script is free software; the Free Software Foundation
 gives unlimited permission to copy, distribute and modify it."
 
@@ -5157,8 +5078,8 @@ do
     ac_need_defaults=false;;
   --he | --h)
     # Conflict between --help and --header
-    as_fn_error $? "ambiguous option: '$1'
-Try '$0 --help' for more information.";;
+    as_fn_error $? "ambiguous option: \`$1'
+Try \`$0 --help' for more information.";;
   --help | --hel | -h )
     printf "%s\n" "$ac_cs_usage"; exit ;;
   -q | -quiet | --quiet | --quie | --qui | --qu | --q \
@@ -5166,8 +5087,8 @@ Try '$0 --help' for more information.";;
     ac_cs_silent=: ;;
 
   # This is an error.
-  -*) as_fn_error $? "unrecognized option: '$1'
-Try '$0 --help' for more information." ;;
+  -*) as_fn_error $? "unrecognized option: \`$1'
+Try \`$0 --help' for more information." ;;
 
   *) as_fn_append ac_config_targets " $1"
      ac_need_defaults=false ;;
@@ -5218,7 +5139,7 @@ do
     "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;;
     "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
 
-  *) as_fn_error $? "invalid argument: '$ac_config_target'" "$LINENO" 5;;
+  *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
   esac
 done
 
@@ -5237,7 +5158,7 @@ fi
 # creating and moving files from /tmp can sometimes cause problems.
 # Hook for its removal unless debugging.
 # Note that there is a small window in which the directory will not be cleaned:
-# after its creation but before its name has been assigned to '$tmp'.
+# after its creation but before its name has been assigned to `$tmp'.
 $debug ||
 {
   tmp= ac_tmp=
@@ -5261,7 +5182,7 @@ ac_tmp=$tmp
 
 # Set up the scripts for CONFIG_FILES section.
 # No need to generate them if there are no CONFIG_FILES.
-# This happens for instance with './config.status config.h'.
+# This happens for instance with `./config.status config.h'.
 if test -n "$CONFIG_FILES"; then
 
 
@@ -5419,13 +5340,13 @@ fi # test -n "$CONFIG_FILES"
 
 # Set up the scripts for CONFIG_HEADERS section.
 # No need to generate them if there are no CONFIG_HEADERS.
-# This happens for instance with './config.status Makefile'.
+# This happens for instance with `./config.status Makefile'.
 if test -n "$CONFIG_HEADERS"; then
 cat >"$ac_tmp/defines.awk" <<\_ACAWK ||
 BEGIN {
 _ACEOF
 
-# Transform confdefs.h into an awk script 'defines.awk', embedded as
+# Transform confdefs.h into an awk script `defines.awk', embedded as
 # here-document in config.status, that substitutes the proper values into
 # config.h.in to produce config.h.
 
@@ -5535,7 +5456,7 @@ do
   esac
   case $ac_mode$ac_tag in
   :[FHL]*:*);;
-  :L* | :C*:*) as_fn_error $? "invalid tag '$ac_tag'" "$LINENO" 5;;
+  :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;;
   :[FH]-) ac_tag=-:-;;
   :[FH]*) ac_tag=$ac_tag:$ac_tag.in;;
   esac
@@ -5557,19 +5478,19 @@ do
       -) ac_f="$ac_tmp/stdin";;
       *) # Look for the file first in the build tree, then in the source tree
 	 # (if the path is not absolute).  The absolute path cannot be DOS-style,
-	 # because $ac_f cannot contain ':'.
+	 # because $ac_f cannot contain `:'.
 	 test -f "$ac_f" ||
 	   case $ac_f in
 	   [\\/$]*) false;;
 	   *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";;
 	   esac ||
-	   as_fn_error 1 "cannot find input file: '$ac_f'" "$LINENO" 5;;
+	   as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;;
       esac
       case $ac_f in *\'*) ac_f=`printf "%s\n" "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac
       as_fn_append ac_file_inputs " '$ac_f'"
     done
 
-    # Let's still pretend it is 'configure' which instantiates (i.e., don't
+    # Let's still pretend it is `configure' which instantiates (i.e., don't
     # use $as_me), people would be surprised to read:
     #    /* config.h.  Generated by config.status.  */
     configure_input='Generated from '`
@@ -5693,7 +5614,7 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_writ
 esac
 _ACEOF
 
-# Neutralize VPATH when '$srcdir' = '.'.
+# Neutralize VPATH when `$srcdir' = `.'.
 # Shell code in configure.ac might set extrasub.
 # FIXME: do we really want to maintain this feature?
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
@@ -5722,9 +5643,9 @@ test -z "$ac_datarootdir_hack$ac_dataroo
   { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } &&
   { ac_out=`sed -n '/^[	 ]*datarootdir[	 ]*:*=/p' \
       "$ac_tmp/out"`; test -z "$ac_out"; } &&
-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable 'datarootdir'
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir'
 which seems to be undefined.  Please make sure it is defined" >&5
-printf "%s\n" "$as_me: WARNING: $ac_file contains a reference to the variable 'datarootdir'
+printf "%s\n" "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
 which seems to be undefined.  Please make sure it is defined" >&2;}
 
   rm -f "$ac_tmp/stdin"
Index: configure
===================================================================
RCS file: /cvs/src/usr.sbin/nsd/configure,v
diff -u -p -r1.65 configure
--- configure	26 Jun 2026 08:55:55 -0000	1.65
+++ configure	7 Jul 2026 10:12:26 -0000
@@ -1,6 +1,6 @@
 #! /bin/sh
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.71 for NSD 4.14.3.
+# Generated by GNU Autoconf 2.71 for NSD 4.15.0.
 #
 # Report bugs to <https://github.com/NLnetLabs/nsd/issues or nsd-bugs@nlnetlabs.nl>.
 #
@@ -612,8 +612,8 @@ MAKEFLAGS=
 # Identity of this package.
 PACKAGE_NAME='NSD'
 PACKAGE_TARNAME='nsd'
-PACKAGE_VERSION='4.14.3'
-PACKAGE_STRING='NSD 4.14.3'
+PACKAGE_VERSION='4.15.0'
+PACKAGE_STRING='NSD 4.15.0'
 PACKAGE_BUGREPORT='https://github.com/NLnetLabs/nsd/issues or nsd-bugs@nlnetlabs.nl'
 PACKAGE_URL=''
 
@@ -1381,7 +1381,7 @@ if test "$ac_init_help" = "long"; then
   # Omit some internal or obsolete options to make the list less imposing.
   # This message is too long to be a string in the A/UX 3.1 sh.
   cat <<_ACEOF
-\`configure' configures NSD 4.14.3 to adapt to many kinds of systems.
+\`configure' configures NSD 4.15.0 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1447,7 +1447,7 @@ fi
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of NSD 4.14.3:";;
+     short | recursive ) echo "Configuration of NSD 4.15.0:";;
    esac
   cat <<\_ACEOF
 
@@ -1635,7 +1635,7 @@ fi
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-NSD configure 4.14.3
+NSD configure 4.15.0
 generated by GNU Autoconf 2.71
 
 Copyright (C) 2021 Free Software Foundation, Inc.
@@ -2292,7 +2292,7 @@ cat >config.log <<_ACEOF
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
-It was created by NSD $as_me 4.14.3, which was
+It was created by NSD $as_me 4.15.0, which was
 generated by GNU Autoconf 2.71.  Invocation command line was
 
   $ $0$ac_configure_args_raw
@@ -13165,7 +13165,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_wri
 # report actual input values of CONFIG_FILES etc. instead of their
 # values after options handling.
 ac_log="
-This file was extended by NSD $as_me 4.14.3, which was
+This file was extended by NSD $as_me 4.15.0, which was
 generated by GNU Autoconf 2.71.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -13229,7 +13229,7 @@ ac_cs_config_escaped=`printf "%s\n" "$ac
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 ac_cs_config='$ac_cs_config_escaped'
 ac_cs_version="\\
-NSD config.status 4.14.3
+NSD config.status 4.15.0
 configured by $0, generated by GNU Autoconf 2.71,
   with options \\"\$ac_cs_config\\"
 
Index: nsd-checkconf.8.in
===================================================================
RCS file: /cvs/src/usr.sbin/nsd/nsd-checkconf.8.in,v
diff -u -p -r1.47 nsd-checkconf.8.in
--- nsd-checkconf.8.in	26 Jun 2026 08:55:55 -0000	1.47
+++ nsd-checkconf.8.in	7 Jul 2026 10:12:26 -0000
@@ -1,4 +1,4 @@
-.TH "nsd\-checkconf" "8" "jun 24, 2026" "NLnet Labs" "nsd 4.14.3"
+.TH "nsd\-checkconf" "8" "jul  7, 2026" "NLnet Labs" "nsd 4.15.0"
 .\" Copyright (c) 2001\-2024, NLnet Labs. All rights reserved.
 .\" See LICENSE for the license.
 .SH "NAME"
Index: nsd-checkzone.8.in
===================================================================
RCS file: /cvs/src/usr.sbin/nsd/nsd-checkzone.8.in,v
diff -u -p -r1.31 nsd-checkzone.8.in
--- nsd-checkzone.8.in	26 Jun 2026 08:55:55 -0000	1.31
+++ nsd-checkzone.8.in	7 Jul 2026 10:12:26 -0000
@@ -1,4 +1,4 @@
-.TH "nsd\-checkzone" "8" "jun 24, 2026" "NLnet Labs" "nsd 4.14.3"
+.TH "nsd\-checkzone" "8" "jul  7, 2026" "NLnet Labs" "nsd 4.15.0"
 .\" Copyright (c) 2014-2024, NLnet Labs. All rights reserved.
 .\" See LICENSE for the license.
 .SH "NAME"
Index: nsd-control.8.in
===================================================================
RCS file: /cvs/src/usr.sbin/nsd/nsd-control.8.in,v
diff -u -p -r1.35 nsd-control.8.in
--- nsd-control.8.in	26 Jun 2026 08:55:55 -0000	1.35
+++ nsd-control.8.in	7 Jul 2026 10:12:26 -0000
@@ -1,4 +1,4 @@
-.TH "nsd\-control" "8" "jun 24, 2026" "NLnet Labs" "nsd 4.14.3"
+.TH "nsd\-control" "8" "jul  7, 2026" "NLnet Labs" "nsd 4.15.0"
 .\" Copyright (c) 2011-2024, NLnet Labs. All rights reserved.
 .\" See LICENSE for the license.
 .SH "NAME"
Index: nsd.8.in
===================================================================
RCS file: /cvs/src/usr.sbin/nsd/nsd.8.in,v
diff -u -p -r1.49 nsd.8.in
--- nsd.8.in	26 Jun 2026 08:55:55 -0000	1.49
+++ nsd.8.in	7 Jul 2026 10:12:26 -0000
@@ -1,9 +1,9 @@
-.TH "NSD" "8" "jun 24, 2026" "NLnet Labs" "NSD 4.14.3"
+.TH "NSD" "8" "jul  7, 2026" "NLnet Labs" "NSD 4.15.0"
 .\" Copyright (c) 2001\-2024, NLnet Labs. All rights reserved.
 .\" See LICENSE for the license.
 .SH "NAME"
 .B nsd
-\- Name Server Daemon (NSD) version 4.14.3.
+\- Name Server Daemon (NSD) version 4.15.0.
 .SH "SYNOPSIS"
 .B nsd
 .RB [ \-4 ]