2
0

dhcp4 client: start controlled service when lease acquired

it is problematic to have dhcp signal readiness when a lease is
acquired, because it holds the s6 service lock while it's waiting
and that can lead to deadlock. Instead, start the dhcp client
"daemon" process and monitor its outputs, bringing up and down
a controlled "dhcp lease acquired" service that other services
(e.g. ntp, or resolvconf, or ...) can declare as a dependency
This commit is contained in:
2025-11-04 00:24:39 +00:00
parent bb2c36a0b4
commit 78e4d30120
3 changed files with 65 additions and 8 deletions
+37 -6
View File
@@ -2,6 +2,11 @@
liminix,
writeAshScript,
serviceFns,
writeFennel,
anoia,
linotify,
lualinux,
s6-rc-up-tree,
lib,
}:
{ interface }:
@@ -29,7 +34,6 @@ let
bound)
# this doesn't actually replace, it adds a new address.
set_address
# echo >/proc/self/fd/10
;;
renew)
set_address
@@ -39,9 +43,36 @@ let
;;
esac
'';
in
longrun {
inherit name;
run = "exec /bin/udhcpc -n -A 15 -f -i $(output ${interface} ifname) -x hostname:$(cat /proc/sys/kernel/hostname) -s ${script}";
dependencies = [ interface ];
service = longrun {
inherit name;
run = "exec /bin/udhcpc -n -A 15 -f -i $(output ${interface} ifname) -x hostname:$(cat /proc/sys/kernel/hostname) -s ${script}";
dependencies = [ interface ];
};
controlled-name = "${name}-lease-acquired";
watcher = longrun {
name = "${name}-watcher";
dependencies = [ service ];
run =
let
script = writeFennel "dhcp-lease-watcher" {
packages = [ anoia linotify lualinux ];
mainFunction = "run";
}
./lease-watcher.fnl;
in ''
export PATH=${s6-rc-up-tree}/bin/:$PATH
${script} ${service} ${controlled-name}
'';
};
in longrun {
name = controlled-name;
run = ''
set -e
echo dhcp lease acquired $(output ${service} ip)
(in_outputs ${controlled-name}
cp $(output_path ${service})/* .
)
while sleep 86400 ; do true ; done
'';
controller = watcher;
}
+26
View File
@@ -0,0 +1,26 @@
(local { : %% : system } (require :anoia))
(local svc (require :anoia.svc))
(fn up-service [name]
(system (%% "s6-rc-up-tree %q" name)))
(fn down-service [name]
(system (%% "s6-rc -b -d change %q" name)))
(fn react [s controlled]
(let [ip (s:output "ip")]
(print "event" "ip=" ip)
(if ip
(up-service controlled)
(down-service controlled))))
(fn run []
(let [[watched controlled] arg
s (assert (svc.open watched))]
(print :service s)
(react s controlled)
(each [e (s:events)]
(print :event e)
(react s controlled))))
{ : run }
+2 -2
View File
@@ -44,6 +44,7 @@ in
../network
../hostapd
../bridge
../dhcp4c
{ config.services = hostaps; }
];
@@ -57,7 +58,6 @@ in
};
};
config = {
services.int = svc.bridge.primary.build {
ifname = "int";
};
@@ -67,7 +67,7 @@ in
members = cfg.interfaces;
};
services.dhcpc = svc.network.dhcp.client.build {
services.dhcpc = svc.dhcp4c.client.build {
interface = config.services.int;
dependencies = [ config.services.hostname ];
};