pub mod config; pub mod install; pub mod nodogsplash; pub mod wifi; pub use config::TollGateConfig; pub use install::install_tollgate; pub use wifi::provision_ssid; use anyhow::{Context, Result}; use tracing::info; use crate::{opkg::PkgManager, Router}; /// Full TollGate provisioning sequence: /// 1. Install tollgate-module-basic-go /// 2. Install and configure NoDogSplash (client gating — tollgate-wrt has no /// firewall/enforcement code of its own; see `nodogsplash::provision`) /// 3. Write TollGate config: UCI (status/detection only) + the JSON file the /// daemon actually reads /// 4. Create the pay-as-you-go WiFi SSID and its dedicated bridge/network /// 5. Restart affected services pub async fn provision(router: &Router, config: &TollGateConfig) -> Result<()> { info!("[{}] Starting TollGate provisioning", router.host); let pkg_mgr = router.opkg_check()?; match pkg_mgr { PkgManager::Opkg => { router.opkg_update()?; install_tollgate(router)?; } PkgManager::ApkNative => { install::install_tollgate_apk_native(router)?; } } // NoDogSplash is a hard runtime dependency of tollgate-wrt (upstream's // package declares `+nodogsplash`), but neither install path above pulls // it in: the opkg fast path only resolves deps against a real feed, and // the raw .ipk-extraction fallback (used whenever the package isn't in a // feed, and always on ApkNative) skips dependency resolution entirely. // Without it, tollgate-wrt runs and accepts payments but never actually // blocks unpaid clients. nodogsplash::provision(router, pkg_mgr, config) .context("provision nodogsplash — tollgate-wrt cannot gate clients without it")?; config::apply(router, config)?; wifi::provision_ssid(router, config)?; // Must come after provision_ssid (which creates br-tollgate) and before // the daemon restart below — config.json is only read at startup. config::apply_daemon_config(router, config) .context("write /etc/tollgate/config.json — tollgate-wrt reads this, not UCI")?; restart_services(router, config.enabled)?; nodogsplash::restart(router)?; info!("[{}] TollGate provisioning complete", router.host); Ok(()) } /// Applies `enabled` to the actual running service, not just the UCI value — /// the tollgate-wrt init script doesn't consult `tollgate.main.enabled` /// itself, so toggling it requires an explicit enable/start or disable/stop. /// /// The service's init script is `/etc/init.d/tollgate-wrt` (its actual /// on-disk name — "tollgate" alone does not exist). fn restart_services(router: &Router, enabled: bool) -> Result<()> { if enabled { router.run_ok("/etc/init.d/tollgate-wrt enable")?; router.run_ok( "/etc/init.d/tollgate-wrt restart || /etc/init.d/tollgate-wrt start" )?; } else { router.run_ok("/etc/init.d/tollgate-wrt stop || true")?; router.run_ok("/etc/init.d/tollgate-wrt disable || true")?; } router.run_ok("/etc/init.d/network restart")?; // 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")?; Ok(()) }