networkd: add support for resolved hook for DHCP server

Let's synthesize DNS RRs for leases handed out by our DHCP server. This
way local VMs can have resolvable hostnames locally.

This does not implement reverse look ups for now. We can add this
later in similar fashion.
This commit is contained in:
Lennart Poettering
2025-11-15 07:52:42 +01:00
parent f041d40dee
commit a7fa29b1b5
21 changed files with 434 additions and 15 deletions
@@ -0,0 +1,10 @@
# SPDX-License-Identifier: LGPL-2.1-or-later
[Match]
Name=veth99
[Network]
DHCP=yes
[DHCPv4]
SendHostname=yes
Hostname=flummy
@@ -0,0 +1,13 @@
# SPDX-License-Identifier: LGPL-2.1-or-later
[Match]
Name=veth-peer
[Network]
IPv6AcceptRA=false
DHCPServer=yes
[DHCPServer]
ServerAddress=192.168.5.1/24
PoolOffset=20
PoolSize=10
LocalLeaseDomain=_networkdtest
@@ -426,6 +426,7 @@ def save_active_units():
for u in [
'systemd-networkd.socket',
'systemd-networkd-varlink.socket',
'systemd-networkd-resolve-hook.socket',
'systemd-networkd.service',
'systemd-resolved-monitor.socket',
'systemd-resolved-varlink.socket',
@@ -449,6 +450,10 @@ def restore_active_units():
call('systemctl stop systemd-networkd-varlink.socket')
has_network_socket = True
if 'systemd-networkd-resolve-hook.socket' in active_units:
call('systemctl stop systemd-networkd-resolve-hook.socket')
has_network_socket = True
if 'systemd-resolved-monitor.socket' in active_units:
call('systemctl stop systemd-resolved-monitor.socket')
has_resolve_socket = True
@@ -525,6 +530,7 @@ def setup_system_units():
'systemd-networkd.service',
'systemd-networkd.socket',
'systemd-networkd-varlink.socket',
'systemd-networkd-resolve-hook.socket',
'systemd-networkd-persistent-storage.service',
'systemd-resolved.service',
'systemd-timesyncd.service',
@@ -572,6 +578,13 @@ def setup_system_units():
'StartLimitIntervalSec=0',
]
)
create_unit_dropin(
'systemd-networkd-resolve-hook.socket',
[
'[Unit]',
'StartLimitIntervalSec=0',
]
)
create_unit_dropin(
'systemd-networkd-persistent-storage.service',
[
@@ -604,6 +617,7 @@ def clear_system_units():
rm_unit('systemd-networkd.service')
rm_unit('systemd-networkd.socket')
rm_unit('systemd-networkd-varlink.socket')
rm_unit('systemd-networkd-resolve-hook.socket')
rm_unit('systemd-networkd-persistent-storage.service')
rm_unit('systemd-resolved.service')
rm_unit('systemd-timesyncd.service')
@@ -990,10 +1004,12 @@ def stop_networkd(show_logs=True, check_failed=True):
if check_failed:
check_output('systemctl stop systemd-networkd.socket')
check_output('systemctl stop systemd-networkd-varlink.socket')
check_output('systemctl stop systemd-networkd-resolve-hook.socket')
check_output('systemctl stop systemd-networkd.service')
else:
call('systemctl stop systemd-networkd.socket')
call('systemctl stop systemd-networkd-varlink.socket')
call('systemctl stop systemd-networkd-resolve-hook.socket')
call('systemctl stop systemd-networkd.service')
if show_logs:
@@ -7366,6 +7382,16 @@ class NetworkdDHCPServerTests(unittest.TestCase, Utilities):
data = json.loads(output)
self.assertEqual(data['DHCPv4Client']['Lease']['Hostname'], 'fqdn.example.com')
def test_dhcp_server_resolve_hook(self):
copy_network_unit('25-veth.netdev', '25-dhcp-client-resolve-hook.network', '25-dhcp-server-resolve-hook.network')
start_networkd()
self.wait_online('veth99:routable', 'veth-peer:routable')
output = check_output('resolvectl query flummy._networkdtest')
print(output)
self.assertIn('192.168.5.2', output)
class NetworkdDHCPServerRelayAgentTests(unittest.TestCase, Utilities):
def setUp(self):