Deploying the previous commit's fix live exposed a real bug: nodogsplash's OpenWrt package postinst auto-enables and starts the service immediately on install, using its stock default config — gatewayinterface=br-lan. Since NoDogSplash only touches IPv4 iptables, this silently cut IPv4 (not IPv6) connectivity for anything on br-lan, including the admin management box plugged into this router's LAN port, for the window between install and our own configure step. Split nodogsplash provisioning into install_and_stop() (runs first, closes that window immediately) and configure() (runs after wifi::provision_ssid has created br-tollgate, so gatewayinterface is pointed at the isolated tollgate bridge instead of br-lan).
91 lines
3.8 KiB
Rust
91 lines
3.8 KiB
Rust
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 NoDogSplash and immediately stop it (its postinst auto-starts
|
|
/// it against `br-lan` by default — see `nodogsplash::install_and_stop`)
|
|
/// 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. Configure NoDogSplash to gate that bridge (now that it exists) —
|
|
/// client gating; tollgate-wrt has no enforcement code of its own
|
|
/// 6. 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. Install + stop happens before anything else so
|
|
// its auto-started default config (gating br-lan) is live for as little
|
|
// time as possible.
|
|
nodogsplash::install_and_stop(router, pkg_mgr)
|
|
.context("install 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")?;
|
|
// Also must come after provision_ssid: points gatewayinterface at
|
|
// br-tollgate, which provision_ssid is what creates.
|
|
nodogsplash::configure(router, config)
|
|
.context("configure nodogsplash — tollgate-wrt cannot gate clients without it")?;
|
|
|
|
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(())
|
|
}
|