From abe03a57028543edc24bbd91ba230615d4803773 Mon Sep 17 00:00:00 2001 From: ssmithx Date: Thu, 2 Jul 2026 20:21:32 +0000 Subject: [PATCH] fix(tollgate): remove stray nodogsplash section, fix netifd claim race MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two more issues found deploying the previous two commits live: 1. The nodogsplash package's own uci-defaults populate an anonymous @nodogsplash[0] section pointed at br-lan (see install_and_stop's doc comment). NoDogSplash runs one gateway instance per config section, so this ran alongside our own nodogsplash.main instead of being superseded by it — silently re-gating br-lan. configure() now deletes it. 2. After `network restart` + `wifi down/up`, netifd intermittently loses the race to claim br-tollgate as the wifi vif attaches (reports up:false, DEVICE_CLAIM_FAILED) even though the bridge device and member interface both exist correctly. NoDogSplash refuses to start against an interface netifd hasn't brought up. restart_services() now explicitly cycles just the tollgate interface (ifdown/ifup) after the wifi restart. --- core/openwrt/src/tollgate/mod.rs | 7 +++++++ core/openwrt/src/tollgate/nodogsplash.rs | 10 ++++++++++ 2 files changed, 17 insertions(+) diff --git a/core/openwrt/src/tollgate/mod.rs b/core/openwrt/src/tollgate/mod.rs index 9f9e3ab0..c05d96a4 100644 --- a/core/openwrt/src/tollgate/mod.rs +++ b/core/openwrt/src/tollgate/mod.rs @@ -86,5 +86,12 @@ fn restart_services(router: &Router, enabled: bool) -> Result<()> { // Reload wireless so wireless.tollgate.disabled takes effect on the radio — // `network restart` alone doesn't reliably reconfigure wifi interfaces. router.run_ok("wifi down 2>&1; wifi up 2>&1")?; + // Observed live: netifd can lose the race to claim br-tollgate as the + // wifi vif attaches to it during the restart above, leaving the + // interface reported "up: false, DEVICE_CLAIM_FAILED" even though the + // bridge device and its member both exist. An explicit down/up of just + // this logical interface resolves it — needed before NoDogSplash starts, + // since it refuses to start against an interface netifd hasn't brought up. + router.run_ok("sleep 2; ifdown tollgate 2>&1; sleep 1; ifup tollgate 2>&1; sleep 2")?; Ok(()) } diff --git a/core/openwrt/src/tollgate/nodogsplash.rs b/core/openwrt/src/tollgate/nodogsplash.rs index 06025bf4..de040e32 100644 --- a/core/openwrt/src/tollgate/nodogsplash.rs +++ b/core/openwrt/src/tollgate/nodogsplash.rs @@ -39,6 +39,16 @@ pub fn install_and_stop(router: &Router, pkg_mgr: PkgManager) -> Result<()> { /// and at worst leaves NoDogSplash in a confused state. pub fn configure(router: &Router, cfg: &TollGateConfig) -> Result<()> { router.run_ok("touch /etc/config/nodogsplash")?; + + // The nodogsplash package's own uci-defaults populate an anonymous + // `@nodogsplash[0]` section on first install, pointed at `br-lan` (its + // stock default — see `install_and_stop`). NoDogSplash supports multiple + // simultaneous gateway instances, one per config section, so leaving this + // in place alongside our own `nodogsplash.main` doesn't get overridden by + // it — it starts a *second* instance gating br-lan for real. Delete it; + // `main` is the only instance this project manages. + let _ = router.uci_delete("nodogsplash.@nodogsplash[0]"); + router.uci_set("nodogsplash.main", "nodogsplash")?; router.uci_set("nodogsplash.main.enabled", "1")?; router.uci_set("nodogsplash.main.gatewayinterface", "br-tollgate")?;