3 Commits

Author SHA1 Message Date
abe03a5702 fix(tollgate): remove stray nodogsplash section, fix netifd claim race
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.
2026-07-02 20:21:32 +00:00
7439a1251c fix(tollgate): fix nodogsplash provisioning order (found live: gated br-lan)
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).
2026-07-02 19:28:48 +00:00
a252eb12fd fix(tollgate): install and configure NoDogSplash for real client gating
tollgate-wrt has no firewall/netfilter code of its own (confirmed via
strings on the binary and the upstream Go source) — it delegates all
MAC authorization and gate open/close to NoDogSplash via ndsctl.
Upstream's package declares +nodogsplash as a hard dependency, but
neither of our install paths pull 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. Result: tollgate-wrt
ran, accepted payments, and tracked balances, but never actually
blocked unpaid clients — the static firewall zone just forwarded
everyone to WAN unconditionally.

Also fixes the config.json mismatch: tollgate-wrt reads
/etc/tollgate/config.json exclusively, never the tollgate.main.* UCI
keys we were writing — so mint/price changes through this project's
UI silently had no effect on what the daemon actually advertised.

- tollgate/nodogsplash.rs: install nodogsplash, configure it to gate
  the dedicated br-tollgate bridge, open the pre-auth walled-garden
  ports (2121 payment, 2050 portal).
- tollgate/wifi.rs: bind network.tollgate to a stable br-tollgate
  bridge device (NoDogSplash needs a known interface name — the
  driver-assigned name of a bare wifi vif isn't guaranteed); disable
  IPv6 RA/DHCPv6 on it (NoDogSplash only manages IPv4 iptables, so
  IPv6 would let clients bypass the portal entirely).
- tollgate/config.rs: apply_daemon_config() merges pricing/mint into
  the real config.json instead of (only) UCI.
- opkg.rs: generic install_package() for standard feed packages under
  either PkgManager mode.
- router.rs: upload_file() (SCP) for non-UCI config files.
2026-07-02 17:23:12 +00:00