add "waitup", s6 readiness helper for network interfaces

run e.g. "waitup wlan0 10" to wait until wlan0 is operationally
up and running, and then send a newline to file descriptor 10
module-based-network
Daniel Barlow 2023-02-24 23:03:09 +00:00
parent 3e1082ad18
commit 03aec58c2c
4 changed files with 93 additions and 0 deletions

View File

@ -86,6 +86,9 @@ final: prev: {
};
};
netlink-lua = final.callPackage ./pkgs/netlink-lua {};
waitup = final.callPackage ./pkgs/waitup {};
# these are packages for the build system not the host/target
tufted = final.callPackage ./pkgs/tufted {};

View File

@ -0,0 +1,23 @@
{ lua, lib, fetchpatch, fetchFromGitHub, libmnl }:
let pname = "netlink";
in lua.pkgs.buildLuaPackage {
inherit pname;
version = "0.1.1-1";
buildInputs = [ libmnl ];
src = fetchFromGitHub {
repo = "lua-netlink";
owner = "chris2511";
rev = "v0.1.1";
hash = "sha256:1833naskl4p7rz5kk0byfgngvw1mvf6cnz64sr3ny7i202wv7s52";
};
buildPhase = "$CC -shared -l mnl -l lua -o netlink.so src/*.c";
installPhase = ''
mkdir -p "$out/lib/lua/${lua.luaversion}"
cp netlink.so "$out/lib/lua/${lua.luaversion}/"
'';
}

31
pkgs/waitup/default.nix Normal file
View File

@ -0,0 +1,31 @@
{
lua5_3
, netlink-lua
, stdenv
, makeWrapper
}:
let
lua = lua5_3;
netlink = netlink-lua.override {inherit lua;};
fennel = lua.pkgs.fennel;
in stdenv.mkDerivation rec {
pname = "waitup";
version = "1";
buildInputs = [ lua netlink-lua ];
nativeBuildInputs = [ makeWrapper fennel ];
src = ./.;
installPhase = ''
mkdir -p $out/bin $out/lib
fennel --compile ${./waitup.fnl} > $out/lib/waitup.lua
makeWrapper ${lua}/bin/lua $out/bin/${pname} \
--prefix LUA_CPATH ";" ${netlink}/lib/lua/${lua.luaversion}/\?.so \
--add-flags $out/lib/waitup.lua
'';
}
# to use fennel.view,
# --prefix LUA_PATH ";" ${fennel}/share/lua/5.2/\?.lua \

36
pkgs/waitup/waitup.fnl Normal file
View File

@ -0,0 +1,36 @@
(local netlink (require :netlink))
(local sock (netlink.socket))
(when (< (# arg) 2)
(print "usage: waitup ifname fd")
(os.exit 1))
(local ifname (. arg 1))
(local fd (tonumber (. arg 2)))
(local stream (io.open (.. "/proc/self/fd/" fd) "w"))
(fn notify-ready []
(stream:write "\n")
(print (.. (. arg 0) ": received netlink operstate up for " ifname))
(stream:close))
(fn run-events [evs]
(each [_ v (ipairs evs)]
(print :event v.event v.name)
(match v
;; - up: Reflects the administrative state of the interface (IFF_UP)
;; - running: Reflects the operational state (IFF_RUNNING).
{:event "newlink" :name ifname :up :yes :running :yes}
(notify-ready)
{:event "newlink" :name ifname :up :no}
(os.exit 0))))
(run-events (sock:query {:link true}))
(print (.. (. arg 0) ": waiting for netlink NEWLINK " ifname))
(while (sock:poll)
(let [ev (sock:event)]
(run-events ev)))