Commit Graph

84616 Commits

Author SHA1 Message Date
Yu Watanabe
2202ba286d README: memory_hugetlb_accounting is since kernel v6.7
8cba9576df
2025-11-09 04:52:20 +09:00
Lennart Poettering
aae054e1ab nsresource: allow multiple userns from the same process in parallel
When generating a name for a transient userns automatically we so far
just included our PID to make it unique. That doens't really work if
multiple userns shall be kept in parallel by a single process. Let's hence
include a counter as well.
2025-11-08 18:32:37 +01:00
Lennart Poettering
14d9f58823 import: various smaller tweaks and fixes, preparation for OCI download support in importd (#39620) 2025-11-08 18:31:11 +01:00
Lennart Poettering
729e1f24c5 pull-job: port .payload field to struct iovec
struct iovec is really how we should encode any form of arbitrary blob
data
2025-11-08 09:28:50 +01:00
Lennart Poettering
33f49312f8 pull-job: use http_status_etag_exists() at a second place 2025-11-08 09:28:50 +01:00
Lennart Poettering
f56531c25c pull: there's no need to keep the downloaded image in memory, except for the sha256sums/gpg file
This seems to be a mistake, in place since the first commit: we only
want the downloaded data in memory if this is a sha256sums or gpg file,
which we need to prorcess ourselves.
2025-11-08 09:28:50 +01:00
Lennart Poettering
7aa847933f pull: use ASSERT_PTR() to shorten code a tiny bit 2025-11-08 09:28:50 +01:00
Lennart Poettering
5bba33f5e9 pull: now that PullJob can verify expected digests, let's rely on it for tar/raw pulling
Instead of authenticating the downloaded image explicity in the tar and
in the raw downloader, we can now rely on the checksum checking in the
generic PullJob code. Hence do so: drop tep the checksum field from
TarPull and RawPull, and just initialized the ->expected_checksum in the
relevant PullJob instead.
2025-11-08 09:28:50 +01:00
Lennart Poettering
6f16ab4893 pull-job: optionally store an expected checksum in PullJob object 2025-11-08 09:28:50 +01:00
Lennart Poettering
e825635af6 import: rework pull logic to store download digests in binary form rather than string
We generally want to store data in parsed form, not formatted form,
hence let's follow our own rules on this, and store the message digest
as "struct iovec" rather than as string. This is generally more
efficient and safer, simply because of case issues.
2025-11-08 09:28:50 +01:00
Lennart Poettering
cb1caab98e pull-job: optionally take expected content length and compare it with what we are downloading 2025-11-08 09:27:46 +01:00
Lennart Poettering
bf51a545a4 pull-job: always implicitly NUL terminate downloaded payload stored in memory
Just as a safety measure, let's always NUL terminate what we are
downloading, maybe future code will parse it as string, and is sloppy by
accident.

(We have similar logic in read_full_file(), and I think it's a really
good rule, to always implicitly NUL terminate blobs we acquire that
might very well be used as text later on)
2025-11-08 09:27:46 +01:00
Mike Yuan
f8293452b6 meson: drop dangling reference to gcrypt
... which was also a typo ;)

Follow-up for e9d4b88b81
2025-11-08 02:11:05 +01:00
Yu Watanabe
61fffbfa58 meson: sysupdate requires systemd-pull and friends
Fixes #39635.
2025-11-08 08:54:42 +09:00
Mike Yuan
89e74275ad core/execute: morph exec_output_is_* to _forward_to_*
Follow-up for 379d9ae222

After the commit, the functions are only used to determine
whether journals shall be forwarded to selected targets,
hence rename as such and remove effectively unused condition
on EXEC_OUTPUT_TTY.
2025-11-08 08:54:13 +09:00
Luca Boccassi
2db3e403ae test: rotate journal before invocation test
Occasionally there are truncated journals failing this test:

[  884.181701] H TEST-04-JOURNAL.sh[12104]: ++ journalctl --no-hostname -n 1 -t bash --invocation=fe8122a7d8eb42c7bf357ac5fafa95e1
[  884.181749] H TEST-04-JOURNAL.sh[12091]: + assert_in 'invocation 1 fe8122a7d8eb42c7bf357ac5fafa95e1' 'Nov 06 17:27:10 bash[11985]: invocation 1 fe8122a7d8eb42c7bf357ac5fafa95e1'
[  884.181773] H TEST-04-JOURNAL.sh[12105]: + set +ex
[  884.181819] H TEST-04-JOURNAL.sh[12091]: + read -r idx invocation _
[  884.181819] H TEST-04-JOURNAL.sh[12091]: + i=2
[  884.181865] H TEST-04-JOURNAL.sh[12106]: ++ journalctl --no-hostname -n 1 -t bash --invocation=2 -u invocation-id-test-20992
[  884.181865] H TEST-04-JOURNAL.sh[12106]: Journal file /var/log/journal/936183a66e7c47939693ae37a967e4fd/system.journal is truncated, ignoring file.
[  884.181865] H TEST-04-JOURNAL.sh[12106]: No journal entry found for the invocation (+2).
[  884.181952] H TEST-04-JOURNAL.sh[12091]: + assert_in 'invocation 2 07d0bd6b5c654b148541d798abccaa96' ''
[  884.181972] H TEST-04-JOURNAL.sh[12107]: + set +ex
[  884.181972] H TEST-04-JOURNAL.sh[12107]: FAIL: 'invocation 2 07d0bd6b5c654b148541d798abccaa96' not found in:

Rotate it at the beginning of the test case to try and avoid this.

Fixes https://github.com/systemd/systemd/issues/39601
2025-11-07 21:35:45 +00:00
Yu Watanabe
f0fdb69a8d core: assign TTY to PAM context when TTYPath= is specified
Fixes #38486 again, which was fixed by
1405d46bf9, but regressed again by
f875a8026e.

This also make it use exec_input_is_terminal().

Follow-up for f875a8026e.
2025-11-08 06:12:20 +09:00
Frantisek Sumsal
6d510012b7 test: move the system time to exactly the timer's elapse time
When we moved the time to 1 minute after the timer would've elapsed,
systemd could pick RandomizedDelaySec= <= 1 minute which would then
cause the timer to elapse immediately and the InactiveExitTimestamp=
to get recalculated including a new next elapse time that would be for
the next "window":

systemd[1]: timer-RandomizedDelaySec-30785.timer: Adding 3.634672s random time.
systemd[1]: timer-RandomizedDelaySec-30785.timer: Realtime timer elapses at Fri 2025-11-07 00:10:03 UTC.
systemd[1]: timer-RandomizedDelaySec-30785.timer: Timer elapsed.
systemd[1]: timer-RandomizedDelaySec-30785.timer: Changed waiting -> running
systemd[1]: Found unit timer-RandomizedDelaySec-30785.timer at /run/systemd/system/timer-RandomizedDelaySec-30785.timer (regular file)
systemd[1]: Preset files say disable timer-RandomizedDelaySec-30785.timer.
systemd[1]: timer-RandomizedDelaySec-30785.timer: Got notified about unit deactivation.
systemd[1]: timer-RandomizedDelaySec-30785.timer: Adding 8h 39min 26.166418s random time.
systemd[1]: timer-RandomizedDelaySec-30785.timer: Realtime timer elapses at Sat 2025-11-08 08:49:26 UTC.
systemd[1]: timer-RandomizedDelaySec-30785.timer: Changed running -> waiting
...
TEST-53-TIMER.sh[1008]: InactiveExitTimestamp=Thu 2025-11-06 23:00:00 UTC
TEST-53-TIMER.sh[1010]: ++ systemctl show -P NextElapseUSecRealtime timer-RandomizedDelaySec-30785.timer
TEST-53-TIMER.sh[905]: + NEXT_ELAPSE_REALTIME='Sat 2025-11-08 08:49:26 UTC'
TEST-53-TIMER.sh[1011]: ++ date '--date=Sat 2025-11-08 08:49:26 UTC' +%s
TEST-53-TIMER.sh[905]: + NEXT_ELAPSE_REALTIME_S=1762591766
TEST-53-TIMER.sh[905]: + : 'Next elapse timestamp should be Fri 2025-11-07 00:10:00 UTC <= Sat 2025-11-08 08:49:26 UTC <= Fri 2025-11-07 22:10:00 UTC'
TEST-53-TIMER.sh[905]: + assert_ge 1762591766 1762474200
TEST-53-TIMER.sh[1012]: + set +ex
TEST-53-TIMER.sh[905]: + assert_le 1762591766 1762553400
TEST-53-TIMER.sh[1013]: + set +ex
TEST-53-TIMER.sh[1013]: FAIL: '1762591766' > '1762553400'

Technically, the race is still there, but the window for it should be
_much_ smaller now (< 1s on a reasonably fast system). Let's hope that's
enough.

Resolves: #39594
2025-11-07 20:04:59 +00:00
Yu Watanabe
9d6c34a297 network: fix typo
Follow-up for dd2934d44e.
2025-11-08 04:27:57 +09:00
Luca Boccassi
057fe0a6ca NEWS: announce RootImageOptions= et al. incompatible changes 2025-11-08 03:24:47 +09:00
Yu Watanabe
7547c3e06a core/exec-invoke: pass the correct pid (1) to processes in pidns (#39575) 2025-11-08 02:41:14 +09:00
Yu Watanabe
88f6611260 tar-util: make sure we can unpack hardlinked symlinks (#39619) 2025-11-08 00:08:44 +09:00
Anton Tiurin
dd2934d44e network: expose Describe Varlink, use for networkctl list & status
Both `list` and `status` with `--json=pretty|short` show the description.
It is fetched via D-Bus by org.freedesktop.network1.Manager.Describe

This change exposes the same data via Varlink API `io.systemd.Network.Describe`
and migrates networkctl list and status commands to use Varlink API.

Update GetStates IDL to use enums for link states.
2025-11-08 00:08:00 +09:00
Zbigniew Jędrzejewski-Szmek
7240ec54ea Fixes for the OSC prompt script (#39588) 2025-11-07 14:53:13 +01:00
Zbigniew Jędrzejewski-Szmek
705e2ef194 profile/osc-context: move and extend check for TERM=dumb
Let's do the check early and skip most of the file if appropriate. Also, treat
missing $TERM same as "dumb". We're almost certainly at a dump terminal in that
case.
2025-11-07 14:47:49 +01:00
Francesco Valla
840549989f modules-load: implement parallel module loading
Load modules in parallel using a pool of worker threads. The number of
threads is equal to the number of CPUs, with a maximum of 16 (to avoid
too many threads being started during boot on systems with many an high
core count, since the number of modules loaded on boot is usually on
the small side).

The number of threads can optionally be specified manually using the
SYSTEMD_MODULES_LOAD_NUM_THREADS environment variable; in this case,
no limit is enforced. If SYSTEMD_MODULES_LOAD_NUM_THREADS is set to 0,
probing happens sequentially.

Co-authored-by: Eric Curtin <ecurtin@redhat.com>
2025-11-07 14:12:56 +01:00
jouyouyun
df79e5b97e pcrextend: fix wrong format in log
`name` is string type, should use `%s` replace `%u`
2025-11-07 14:08:35 +01:00
Lennart Poettering
36e10dc5a5 tar-util: make sure we can unpack hardlinked symlinks
This is something ostree does. Yuck. But let's make t work.
2025-11-07 14:04:36 +01:00
Lennart Poettering
0ab316ff14 chase: fix typo in log message
(While we are at it, add quotes around user provided strings)
2025-11-07 14:04:19 +01:00
Yu Watanabe
d8e38d4aaa reread-partition-table: trigger change events when we failed to lock device
Before aa47d8ade1, when we failed to lock
the device node, we simply trigger change events for the device and its
partitions. But the commit killed the fallback logic. Let's restore that.

Fixes #39544.
2025-11-07 16:35:44 +09:00
Yu Watanabe
fe263e9302 logind: handle session leader termination during deserialization more gracefully (#39607)
Closes https://github.com/systemd/systemd/issues/39556
2025-11-07 16:35:32 +09:00
cvlc12
c3e80f8f2b man: systemd-measure. Remove 'tpm2-pcrs=' from cryptenroll command (#39590)
This is now default since 4b840414be.
2025-11-07 05:54:06 +09:00
Yu Watanabe
d1676fdfbd Two fixes for homectl (#39591) 2025-11-07 05:52:20 +09:00
Luca Boccassi
7a62cbfc6d test: ensure test checking status runs first
The test messes a bit with the ESP, which might cause bootctl status output to change.
Run the test that simply checks status without changing anything first.

[  188.633908] TEST-87-AUX-UTILS-VM.sh[1101]: + bootctl status --quiet
[  188.681082] TEST-87-AUX-UTILS-VM.sh[1155]: System:
[  188.681082] TEST-87-AUX-UTILS-VM.sh[1155]:       Firmware: UEFI 2.70 (EDK II 1.00)
[  188.681082] TEST-87-AUX-UTILS-VM.sh[1155]:  Firmware Arch: x64
[  188.681082] TEST-87-AUX-UTILS-VM.sh[1155]:    Secure Boot: enabled (user)
<...>
[  198.938717] TEST-87-AUX-UTILS-VM.sh[1679]: ++ printf '\6\0\0\0\1'
[  198.939235] TEST-87-AUX-UTILS-VM.sh[1678]: + cmp /sys/firmware/efi/efivars/SecureBoot-8be4df61-93ca-11d2-aa0d-00e098032b8c /dev/fd/63
[  198.944957] TEST-87-AUX-UTILS-VM.sh[1678]: + cmp /sys/firmware/efi/efivars/SetupMode-8be4df61-93ca-11d2-aa0d-00e098032b8c /dev/fd/63
[  198.945808] TEST-87-AUX-UTILS-VM.sh[1681]: ++ printf '\6\0\0\0\0'
[  198.950459] TEST-87-AUX-UTILS-VM.sh[1684]: + bootctl status
[  198.951357] TEST-87-AUX-UTILS-VM.sh[1685]: + grep -q 'Secure Boot: enabled'
[  199.004142] TEST-87-AUX-UTILS-VM.sh[1086]: + echo 'Subtest /usr/lib/systemd/tests/testdata/units/TEST-87-AUX-UTILS-VM.bootctl.sh failed'

Follow-up for 5ae58ac2b9

Fixes https://github.com/systemd/systemd/issues/39598
2025-11-07 05:51:39 +09:00
Luca Boccassi
74c0ed07a1 reread-part: fix error propagation
[   49.514556] (udev-synth)[1385]: Assertion '(_error) != 0' failed at src/shared/reread-partition-table.c:260, function reread_partition_table_full(). Aborting.

Follow-up for 757887d01d

Fixes https://github.com/systemd/systemd/issues/39603
2025-11-07 05:50:20 +09:00
jouyouyun
9ebf0d260d nss-systemd: fix memory leak 2025-11-06 21:10:25 +01:00
Mike Yuan
a6590235df logind: handle session leader termination during deserialization more gracefully
We track session leaders by pidfd precisely to make restarts reliable,
as leader exiting before deserialization is somewhat expected.
Such case is already handled gracefully (we'd GC sessions without leader
before kicking off the new cycle), but let's also tweak the log message
a bit to reduce annoyance.

Closes #39556
2025-11-06 20:53:49 +01:00
Mike Yuan
c54112bdee logind: fix potential fd leak in deliver_session_leader_fd_consume()
Follow-up for 45eea629e3
2025-11-06 19:31:56 +01:00
Frantisek Sumsal
7b3046e693 test: sync journal after the test unit finishes
In these two cases we need to sync the journal _after_ the unit finishes
as well, because we try to match messages from systemd itself, not
(only) from the unit, and the messages about units are dispatched
asynchronously.

That is, in the first case (silent-success.service) we want to make sure
that LogLevelMax= filters out messages _about_ units (from systemd) as
well, including messages like "Deactivated..."  and "Finished...", which
are sent out only when/after the unit is stopped.

In the second case we try to match messages with the "systemd" syslog
tag, but these messages come from systemd (obviously) and are sent out
asynchronously, which means they might not reach the journal before we
call `journalctl --sync` from the test unit itself, like happened here:

[ 1754.150391] TEST-04-JOURNAL.sh[13331]: + systemctl start verbose-success.service
[ 1754.172256] bash[13692]: success
[ 1754.221210] TEST-04-JOURNAL.sh[13694]: ++ journalctl -b -q -u verbose-success.service -t systemd
[ 1754.221493] TEST-04-JOURNAL.sh[13331]: + [[ -n '' ]]
[ 1754.175709] systemd[1]: Starting verbose-success.service - Verbose successful service...
[ 1754.221697] TEST-04-JOURNAL.sh[122]: + echo 'Subtest /usr/lib/systemd/tests/testdata/units/TEST-04-JOURNAL.journal.sh failed'
[ 1754.221697] TEST-04-JOURNAL.sh[122]: Subtest /usr/lib/systemd/tests/testdata/units/TEST-04-JOURNAL.journal.sh failed
[ 1754.221697] TEST-04-JOURNAL.sh[122]: + return 1
[ 1754.205408] systemd[1]: verbose-success.service: Deactivated successfully.
[ 1754.205687] systemd[1]: Finished verbose-success.service - Verbose successful service.

By syncing the journal after the unit is stopped we have much bigger
chance that the systemd messages already reached the journal - the race
is technically still there, but the chance we'd hit it should be pretty
negligible.

Resolves: #39555
2025-11-06 16:30:52 +00:00
Zbigniew Jędrzejewski-Szmek
ca5fa2f5ad resolvectl: add --json support for status commands (#38960)
Add --json support for all status commands in resolvectl by making use
of the new DumpDNSConfiguration varlink method. E.g,

```
$ resolvectl --json=pretty status eth0
[
        {
                "ifname" : "eth0",
                "ifindex" : 9,
                "defaultRoute" : true,
                "currentServer" : {
                        "addressString" : "10.148.181.1",
                        "address" : [
                                10,
                                148,
                                181,
                                1
                        ],
                        "family" : 2,
                        "port" : 53,
                        "ifindex" : 9,
                        "accessible" : true
                },
                "servers" : [
                        {
                                "addressString" : "10.148.181.1",
                                "address" : [
                                        10,
                                        148,
                                        181,
                                        1
                                ],
                                "family" : 2,
                                "port" : 53,
                                "ifindex" : 9,
                                "accessible" : true
                        }
                ],
                "searchDomains" : [
                        {
                                "name" : "local",
                                "routeOnly" : false,
                                "ifindex" : 9
                        }
                ],
                "dnssec" : "allow-downgrade",
                "dnsOverTLS" : "no",
                "llmnr" : "no",
                "mDNS" : "no",
                "scopes" : [
                        {
                                "protocol" : "dns",
                                "ifindex" : 9,
                                "ifname" : "eth0",
                                "dnssec" : "allow-downgrade",
                                "dnsOverTLS" : "no"
                        }
                ]
        }
]
```

Like the regular status output, fields are omitted all together when
empty, unless explicitly requested via one of the sub-commands dns,
domain, nta, etc.

Closes https://github.com/systemd/systemd/issues/33036.
2025-11-06 15:34:10 +01:00
Zbigniew Jędrzejewski-Szmek
9070bffdc1 Fix systemd-ssh-generator printing a bogus hint (#39578) 2025-11-06 15:30:35 +01:00
David Tardon
399c9f847e ask-password-api: return if read_credential() failed
The current code causes assertion in strv_parse_nulstr() if
read_credential() results in an error different from ENXIO or ENOENT
(strace shows I'm getting EACCES):

 # homectl create waldo --real-name=Waldo --disk-size=200M

Before:

 Assertion 's || l <= 0' failed at src/basic/nulstr-util.c:32, function strv_parse_nulstr_full(). Aborting.

After:

 Failed to acquire password: Permission denied

Follow-up-for: 8806bb4bc7
2025-11-06 14:23:35 +01:00
David Tardon
5efcbae259 homectl: fix memory leak
# valgrind --leak-check=full homectl create waldo --real-name=Waldo --disk-size=200M --setopt=FOO=bar

Before:

==25155== HEAP SUMMARY:
==25155==     in use at exit: 12,879 bytes in 39 blocks
==25155==   total heap usage: 90 allocs, 51 frees, 53,964 bytes allocated
==25155==
==25155== 8 bytes in 1 blocks are definitely lost in loss record 4 of 38
==25155==    at 0x4845866: malloc (vg_replace_malloc.c:446)
==25155==    by 0x547FC2E: strdup (strdup.c:42)
==25155==    by 0x4B2647C: strv_env_replace_strdup_passthrough (env-util.c:435)
==25155==    by 0x42D547: parse_argv (homectl.c:3909)
==25155==    by 0x43999C: run (homectl.c:5606)
==25155==    by 0x4399F5: main (homectl.c:5613)
==25155==
==25155== LEAK SUMMARY:
==25155==    definitely lost: 8 bytes in 1 blocks

After:

==25224== HEAP SUMMARY:
==25224==     in use at exit: 12,871 bytes in 38 blocks
==25224==   total heap usage: 90 allocs, 52 frees, 53,964 bytes allocated
==25224==
==25224== LEAK SUMMARY:
==25224==    definitely lost: 0 bytes in 0 blocks

Follow-up-for: aaf057c4bb
2025-11-06 14:21:43 +01:00
Zbigniew Jędrzejewski-Szmek
dd20ba74e3 profile/systemd-osc-context: fix overriding of PROMPT_COMMAND
In https://github.com/systemd/systemd/issues/39114 users are reporting
that our script overrides PROMPT_COMMAND that they had. After looking
at /etc/bashrc in Fedora, I see that it only sets PROMPT_COMMAND if
[ -z "$PROMPT_COMMAND" ]. Let's adjust the script so this continues to
work.

Fixes https://github.com/systemd/systemd/issues/39114.
(This is a bit of a stretch. 39114 was originally about SecureCRT,
but that was resolved in SecureCRT. But there was a lot of dicussion
about the prompt being overriden, which this commit should fix.)
2025-11-06 12:21:27 +01:00
Nick Rosbrook
313d216662 test: expand testcases to include resolvectl --json usage 2025-11-06 05:17:59 -05:00
Nick Rosbrook
0536b37629 resolvectl: implement --json flag for resolvectl status
Add --json support for all status commands in resolvectl by making use
of the new DumpDNSConfiguration varlink method. E.g,

$ resolvectl --json=pretty status eth0
[
	{
		"ifname" : "eth0",
		"ifindex" : 9,
		"defaultRoute" : true,
		"currentServer" : {
                        "addressString" : "10.148.181.1",
			"address" : [
				10,
				148,
				181,
				1
			],
			"family" : 2,
			"port" : 53,
			"ifindex" : 9,
			"accessible" : true
		},
		"servers" : [
			{
                                "addressString" : "10.148.181.1",
				"address" : [
					10,
					148,
					181,
					1
				],
				"family" : 2,
				"port" : 53,
				"ifindex" : 9,
				"accessible" : true
			}
		],
		"searchDomains" : [
			{
				"name" : "local",
				"routeOnly" : false,
				"ifindex" : 9
			}
		],
		"dnssec" : "allow-downgrade",
		"dnsOverTLS" : "no",
		"llmnr" : "no",
		"mDNS" : "no",
		"scopes" : [
			{
				"protocol" : "dns",
				"ifindex" : 9,
				"ifname" : "eth0",
				"dnssec" : "allow-downgrade",
				"dnsOverTLS" : "no"
			}
		]
	}
]

Like the regular status output, fields are omitted all together when
empty, unless explicitly requested via one of the sub-commands dns,
domain, nta, etc.
2025-11-06 05:17:59 -05:00
Nick Rosbrook
01278ceba0 resolve: add DumpDNSConfiguration to varlink API
Add io.systemd.Resolve.DumpDNSConfiguration. This provides the same
information as io.systemd.Resolve.Monitor.SubscribeDNSConfiguration,
but just returns the configuration once without the subscription logic.

In order to use the same definitions for DNSConfiguration et al. between
both interfaces, move the definitions to io.systemd.Resolve, and include
them in io.systemd.Resolve.Monitor.

This will be used to implement --json for resolvectl status.
2025-11-06 05:17:59 -05:00
Nick Rosbrook
d49a0bd1da wait-online: ignore unused DNSConfiguration fields when dispatching JSON
The io.systemd.Resolve.Monitor.DNSConfiguration type is being expanded,
but we do not need the extra information for determining online status.

Ignore these fields when dispatching JSON to avoid "Unrecognized object field"
messages adding noise to systemd-networkd-wait-online debug output.
2025-11-06 05:17:59 -05:00
Nick Rosbrook
5e777155d5 wait-online: dispatch DNSConfiguration with SD_JSON_ALLOW_EXTENSIONS
Currently if an unknown field is encountered in the JSON, it is a fatal
error. Dispatch with SD_JSON_ALLOW_EXTENSIONS to avoid this.
2025-11-06 05:17:59 -05:00
Nick Rosbrook
0d9e5b39d3 resolve: add formatted address string to DNSServer
Although the JSON output is mostly intended to be machine readable,
humans also consume the output through logs and scripts.

Add an addressString field to DNSServer to improve human-readability.
2025-11-06 05:17:59 -05:00