107 lines
3.4 KiB
Rust
Raw Normal View History

use anyhow::{Context, Result};
use tracing::info;
use crate::tollgate::TollGateConfig;
use crate::Router;
/// Create a dedicated pay-as-you-go WiFi interface for TollGate.
///
/// Adds a new `wifi-iface` section on the first detected radio, sets the SSID,
/// marks it as an open network, and ties it to a TollGate firewall zone.
pub fn provision_ssid(router: &Router, cfg: &TollGateConfig) -> Result<()> {
let radio = detect_radio(router).context("detect WiFi radio")?;
info!("[{}] Using radio {} for TollGate SSID", router.host, radio);
// Add a new wifi-iface section; uci add returns the section name (e.g. "cfg123456").
let section = router.uci_add("wireless", "wifi-iface")?;
router.uci_apply(
"wireless",
&[
(&format!("wireless.{}.device", section), &radio),
(&format!("wireless.{}.mode", section), "ap"),
(&format!("wireless.{}.ssid", section), &cfg.ssid),
(&format!("wireless.{}.encryption", section), "none"),
(&format!("wireless.{}.network", section), "tollgate"),
// Disable 802.11r/k/v — unnecessary for transient pay-as-you-go clients.
(&format!("wireless.{}.ieee80211r", section), "0"),
],
)?;
provision_network(router)?;
provision_firewall(router)?;
Ok(())
}
/// Add a `tollgate` network interface (isolated LAN for TollGate clients).
fn provision_network(router: &Router) -> Result<()> {
router.uci_apply(
"network",
&[
("network.tollgate", "interface"),
("network.tollgate.proto", "static"),
("network.tollgate.ipaddr", "192.168.99.1"),
("network.tollgate.netmask", "255.255.255.0"),
],
)?;
// Enable DHCP for the tollgate interface.
router.uci_apply(
"dhcp",
&[
("dhcp.tollgate", "dhcp"),
("dhcp.tollgate.interface", "tollgate"),
("dhcp.tollgate.start", "100"),
("dhcp.tollgate.limit", "150"),
("dhcp.tollgate.leasetime", "5m"),
],
)?;
Ok(())
}
/// Add firewall zone for the tollgate interface.
///
/// TollGate itself gates forwarding via iptables; the firewall zone isolates
/// tollgate clients from other LAN segments.
fn provision_firewall(router: &Router) -> Result<()> {
// Zone
router.uci_apply(
"firewall",
&[
("firewall.tollgate_zone", "zone"),
("firewall.tollgate_zone.name", "tollgate"),
("firewall.tollgate_zone.network", "tollgate"),
("firewall.tollgate_zone.input", "ACCEPT"),
("firewall.tollgate_zone.output", "ACCEPT"),
("firewall.tollgate_zone.forward", "REJECT"),
],
)?;
// Forwarding rule: tollgate → wan (TollGate manages which clients can forward)
router.uci_apply(
"firewall",
&[
("firewall.tollgate_fwd", "forwarding"),
("firewall.tollgate_fwd.src", "tollgate"),
("firewall.tollgate_fwd.dest", "wan"),
],
)?;
Ok(())
}
/// Return the first available wireless radio device name (e.g. "radio0").
fn detect_radio(router: &Router) -> Result<String> {
let out = router.run_ok("uci show wireless | grep -o 'wireless\\.radio[0-9]*\\.type' | head -1")?;
// Extract "radioN" from "wireless.radioN.type"
let radio = out
.trim()
.split('.')
.nth(1)
.unwrap_or("radio0")
.to_string();
Ok(radio)
}