Skip to content

Merge develop branch into master (Engine)#1540

Merged
matsduf merged 69 commits into
masterfrom
develop
Jun 29, 2026
Merged

Merge develop branch into master (Engine)#1540
matsduf merged 69 commits into
masterfrom
develop

Conversation

@matsduf

@matsduf matsduf commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

Purpose

This PR is step https://github.com/zonemaster/zonemaster/blob/develop/docs/internal/maintenance/ReleaseProcess-release.md#15-merge-develop-branch-into-master

How to test this PR

"No reviewer or approval is required for this update."

MichaelTimbert and others added 30 commits February 24, 2026 15:45
Merge master branch into develop (zonemaster-engine)
The IP address bound to a.root-servers.net is now in over 30 ASNs
simultaneously, so let’s use K-root instead, whose address is still in
one AS. Until we find a better way.
Parts of this unit tests relies on live data from the Internet that
cannot be guaranteed to stay the same. As of now (2026-03-25), the data
on www.wiccainfo.se cannot be recorded anymore.

These parts are essentially made obsolete by t/recursor-A.t, which
exercises the Zonemaster::Engine::Recursor much more thoroughly by means
of the test scenario framework.

However, we cannot delete the entire file without negatively affecting
test coverage in some small parts of the codebase. Best to be careful
and not just go around deleting too many things in one go.
Whoever owned 001.tf dropped the domain, but fortunately 001.re exists
and has the same problem, namely having all its name servers in the
same AS.
Thanks to scanning the entire .fr zone with Zonemaster, I was able to
find other domains that had the same problems as those that were
previously in the test file, even removing a TODO block in the process.
Two unit tests, t/Test-zone01-{A,B}.t, had incorrect fake delegations
that prevented correct rerecording of the unit tests, given how the
zones are currently set up.

And in t/undelegated.t, an update was necessary for the fake delegations
so that they’d trigger FAKE_DELEGATION_IN_ZONE_NO_IP again.

The reason why t/undelegated.t needed fixing is not quite clear to me
yet. It might be because in the real world, the name servers names of
nic.se are no longer all subdomains of nic.se.
At the end of t/nameserver.t, there are attempts to send queries to a
fake nameserver whose IPv4 address lies in 192.0.2.0/24 (TEST-NET-1), a
range that should not be routable on the public Internet, in order to
elicit a guaranteed resolution failure.

However, the test is flawed and should only work when it is run under
ZONEMASTER_RECORD=1. Here’s why.

The test expects a resolution failure to generate two messages, a
LOOKUP_ERROR message and a BLACKLISTING message. However, looking at the
logic in Zonemaster::Engine::Nameserver, these messages are only
generated if the query was actually sent out on the network; in other
words, if the Nameserver object is returning a cached resolution
failure, these messages will not be generated. Therefore, if running
offline (without ZONEMASTER_RECORD=1), we *should not* have these two
messages and their presence arguably indicates a bug with the cache.

Because of that flawed logic in t/nameserver.t, after rerecording the
t/nameserver.data file with:

  $ ZONEMASTER_RECORD=1 prove -l t/nameserver.t

then running the test again in offline mode with:

  $ prove -l t/nameserver.t

the test stops passing.

This commit changes the test’s logic so that if we run offline, we
ensure that LOOKUP_ERROR and BLACKLISTING are *not* generated. The
previous logic is only run if running with ZONEMASTER_RECORD=1.
The latest version of Perl is now 5.42. Let’s bump the topmost version
in the list of Perls tested against in CI to that.
…enance

Update unit tests depending on real-world data
Add a small function in Zonemaster::Engine::Util named “escape”, that
can be used for escaping non-ASCII or non-printable characters in
strings so that they do not cause problems.

The code trades off some space and some style for significant speed
improvements compared to more naive solutions. On my machine, the code
handles 1 million strings in 2.468 s (down from 9.527 s in the first
iteration).
The TXT resource records we obtain in version.bind and
version.server/TXT/CH queries are byte strings and can contain
all sorts of funny things, including terminal control characters, HTML
injection attempts, invalid UTF-8 byte sequences and every octet under
the sun.

If we are logging and displaying this data in user interfaces, it better
be sanitized somehow, or bad things can happen. Because we are a DNS
testing tool, we can simply turn these strings into the well-recognized
presentation format specified in RFC 1034 and 1035, replacing any byte
outside of the printable ASCII range (decimal 32–126) by its
backslash-decimal number sequence (e.g. ESC, or ASCII 27 decimal,
becomes \027), and turning backslashes into the double-backslash (\\)
escape sequence.

As a drive-by change, we also fix a small logic error that appears a few
lines down. The intent is to check if the string is non-empty, but the
faulty logic meant that a string containing a single zero is also
considered falsey.
Perls before 5.28 disallow initializing list variables as state
variables, which is what escape() uses for a lookup table for escape
codes. As a workaround, we use a lexically-scoped table and the escape()
subroutine closes over the table.

This commit can be reverted cleanly if we drop support for Perl 5.26.
The latter is a better name for the function in
Zonemaster::Engine::Util.
…ening

Harden Nameserver15 against creative version strings
Parameters are normalized to ensure that the cache is hit for semantically identical queries.
marc-vanderwal and others added 26 commits June 8, 2026 14:40
We’ve migrated cache file formats in a previous commit, so we can remove
all the temporary code that was there to support migration from old to
new format, and thus complete the job.
Switching from JSON to CBOR for the cache format has made the need for a
TO_JSON method in Zonemaster::Engine::DNSName and …::Packet unnecessary.
We can now remove these methods.
This script will be much more useful after the format change, because we
are switching to a binary format instead of a vaguely text-based one.
Rewrite the axfr() method in Zonemaster::Engine::Nameserver so that it
goes through the cache like query() would.

Implementing this change is a bit more difficult because the API for
AXFR requests in Zonemaster::LDNS is very different from that of
non-AXFR queries.

The basic idea is to use a synthetic AXFR query packet as a cache key,
and to create another synthetic response packet that stores the RRs that
were fetched through the AXFR query (as long as the provided callback
returns 1). That packet is then inserted into the cache. When loading
the cache, the axfr() uses that saved synthetic packet to simulate an
AXFR query.

Interestingly, the t/nameserver-axfr.t test file uses its own data file
format. It actually implements a cache of its own. This is not necessary
anymore and this commit amends the .t file to put it in line with the
others.

There is however one subtlety that I couldn’t fit into the design of the
synthetic answer packets in case the AXFR fails, because it requires a
new feature in Zonemaster::LDNS.

In order to test this commit:

  1. Using zonemaster-cli, run the Nameserver03 test on your favorite
     domain while saving the packets, e.g.:

     $ zonemaster-cli --save mydata --test nameserver03 servfail.fr

  2. Examine the cached packets using the data2dig script in the util
     subdirectory in Zonemaster-Engine, and look for cached AXFR queries
     in the output:

     $ ./util/data2dig mydata | grep AXFR
AXFR responses, including errors, are cached as synthetic packets thanks
to previous work. But we had no elegant way of storing the associated
error message.

It felt appropriate to use an extended DNS error code 13 (Cached error)
for that purpose, so after implementing the missing feature in
Zonemaster::LDNS, we can use it here.
Replace Perl INIT block with explicit initialization
Overhaul saved packets’ serialization format
Add a test that exercises the code that converts log entries into JSON
format.
This reverts commit bb5ddfb.

It turns out that these methods weren’t obsolete after all. In
particular, the removal of the TO_JSON method in
Zonemaster::Engine::DNSName caused some issues that weren’t caught in
unit tests.

If you run:

  $ zonemaster-cli --level info --test basic02 --no-ipv6 \
          zonemaster.net --json | jq

you should see that on the second message, the "domain" argument is a
domain name, and no longer "null".
Remove deprecated profile properties for v2026.1 release
Updates Swedish translation after update of the msgids
Updates for release v2026.1 (Engine)
Adds missing tag in list of tags for DNSSEC10
@matsduf matsduf added this to the v2026.1 milestone Jun 29, 2026
@matsduf matsduf added P-High Priority: Issue to be solved before other RC-None Release category: Not to be included in Changes file. labels Jun 29, 2026
@matsduf matsduf merged commit 609c4f1 into master Jun 29, 2026
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

P-High Priority: Issue to be solved before other RC-None Release category: Not to be included in Changes file.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants