From ac897799e642557cdc964d07837dd2215e2050a5 Mon Sep 17 00:00:00 2001 From: Andreas Wrede Date: Wed, 23 Sep 2026 14:48:22 -0400 Subject: [PATCH] Template hostapd interface/SSIDs/5GHz radio lines; guard against other-host hardcodes Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_01KqhjP7nud5gdBg25zCiRk9 --- ap/20-van-br0.netdev | 2 +- ap/hostapd-2g.conf | 4 ++-- ap/hostapd.conf | 7 ++----- deploy.sh | 2 +- hosts/van.conf | 9 +++++++-- hosts/vanlink.conf.example | 8 ++++++++ hosts/wan.conf | 5 +++++ tests/check-templates.sh | 36 ++++++++++++++++++++++++++++++++++++ 8 files changed, 62 insertions(+), 11 deletions(-) diff --git a/ap/20-van-br0.netdev b/ap/20-van-br0.netdev index 432efc7..7fc39ef 100644 --- a/ap/20-van-br0.netdev +++ b/ap/20-van-br0.netdev @@ -1,5 +1,5 @@ # LAN bridge: joins the AP Wi-Fi radios (added by hostapd, once in AP mode) and the -# wired LAN ports (enx00e04c331140 + onboard eth0, added by networkd) into one +# wired LAN ports (the LAN_IFACE port + onboard eth0, added by networkd) into one # 10.42.1.0/24 segment. STP off: all members are leaf ports, no loops (don't cable # the two wired ports to the same switch), and it avoids the forwarding delay that # would otherwise stall the first DHCP handshake on a freshly-plugged client. diff --git a/ap/hostapd-2g.conf b/ap/hostapd-2g.conf index 7954f93..28824dc 100644 --- a/ap/hostapd-2g.conf +++ b/ap/hostapd-2g.conf @@ -1,4 +1,4 @@ -interface=wlx3c3332002066 +interface=@WIFI_2G_IFACE@ # Second, independent hostapd instance (hostapd-2g.service) — 2.4GHz band of the same # VanLink network, bridged into the same br0 segment as the 5GHz AP and the wired port. # Separate process on purpose: a USB wedge on one radio must never take down the other. @@ -8,7 +8,7 @@ ctrl_interface=/var/run/hostapd driver=nl80211 # Same SSID + PSK as 5GHz: dual-band clients pick a band themselves, 2.4-only IoT # devices just join. Rename here (e.g. VanLink-2G) if band pinning is ever needed. -ssid=VanLink2-2G +ssid=@AP_SSID_2G@ country_code=CA ieee80211d=1 hw_mode=g diff --git a/ap/hostapd.conf b/ap/hostapd.conf index 52184a7..161fa0b 100644 --- a/ap/hostapd.conf +++ b/ap/hostapd.conf @@ -8,7 +8,7 @@ bridge=br0 # stays "running" but stops serving after a USB glitch. ctrl_interface=/var/run/hostapd driver=nl80211 -ssid=VanLink2 +ssid=@AP_SSID_5G@ country_code=CA ieee80211d=1 hw_mode=a @@ -19,10 +19,7 @@ wmm_enabled=1 ieee80211n=1 ieee80211ac=1 ieee80211ax=1 -ht_capab=[HT20][SHORT-GI-20][HT40+][HT40-] -vht_capab=[MAX-MPDU-11454][RXLDPC][SHORT-GI-80][TX-STBC-2BY1][RX-STBC-1][SU-BEAMFORMEE] -he_su_beamformee=1 -he_mu_edca_qos_info_param_count=0 +@AP_5G_RADIO@ auth_algs=1 wpa=2 wpa_passphrase=1foot11foot11 diff --git a/deploy.sh b/deploy.sh index 2ba88b7..a517b61 100755 --- a/deploy.sh +++ b/deploy.sh @@ -22,7 +22,7 @@ VANLINK_CONF=${VANLINK_CONF:-/etc/vanlink.conf} REQUIRED_VARS=( WIFI_5G_IFACE WIFI_2G_IFACE LAN_IFACE STARLINK_IFACE WIFI_WAN_IFACE GATEWAY_IP GATEWAY_PREFIX GATEWAY_NETWORK DHCP_RANGE_START DHCP_RANGE_END - DNS_RESOLVERS MODEM_USB_VENDOR + DNS_RESOLVERS MODEM_USB_VENDOR AP_SSID_5G AP_SSID_2G AP_5G_RADIO ENABLE_COCKPIT ENABLE_LI3 ENABLE_NVME_WATCH ENABLE_HA ENABLE_FRIGATE ) # May be empty or absent; NVME_* are required only when ENABLE_NVME_WATCH=1. diff --git a/hosts/van.conf b/hosts/van.conf index 304d4b8..c6b3319 100644 --- a/hosts/van.conf +++ b/hosts/van.conf @@ -1,8 +1,8 @@ # hosts/van.conf — FriendlyElec NanoPi R5C, hostname "van" (Armbian). # /etc/vanlink.conf -> this file. See hosts/vanlink.conf.example for the variable list. -WIFI_5G_IFACE=wlp1s0 # MediaTek MT7925E (PCIe); also carries the 2.4GHz AP -WIFI_2G_IFACE=wlx3c3332002066 +WIFI_5G_IFACE=wlp1s0 # MediaTek MT7925E (PCIe); 2.4GHz AP is the separate USB dongle below +WIFI_2G_IFACE=wlx3c3332002066 # D-Link USB dongle LAN_IFACE=enP1p17s0 STARLINK_IFACE=enP2p33s0 WIFI_WAN_IFACE=wlan0 # not present on this host (kept for the failover config) @@ -16,6 +16,11 @@ DHCP_RANGE_END="10.42.1.254" DNS_RESOLVERS="1.1.1.1 8.8.8.8" MODEM_USB_VENDOR=2c7c + +AP_SSID_5G=VanLink2 +AP_SSID_2G=VanLink2-2G +# MT7925E: no 80MHz width lines, no ieee80211h +AP_5G_RADIO='ht_capab=[HT20][SHORT-GI-20][HT40+][HT40-]\nvht_capab=[MAX-MPDU-11454][RXLDPC][SHORT-GI-80][TX-STBC-2BY1][RX-STBC-1][SU-BEAMFORMEE]\nhe_su_beamformee=1\nhe_mu_edca_qos_info_param_count=0' NVME_DEVICE= NVME_FS_DEVICE= diff --git a/hosts/vanlink.conf.example b/hosts/vanlink.conf.example index 8b398f1..c3576f0 100644 --- a/hosts/vanlink.conf.example +++ b/hosts/vanlink.conf.example @@ -15,6 +15,14 @@ STARLINK_IFACE=enp2s0 # Starlink uplink (NetworkManager WAN) WIFI_WAN_IFACE=wlan0 # Wi-Fi uplink (NetworkManager WAN) ONBOARD_LAN_IFACE= # optional: extra onboard LAN port bridged into br0 (e.g. eth0); empty = none +# --- Access point ------------------------------------------------------------- +AP_SSID_5G=VanLink # SSID of the 5GHz AP (hostapd.conf) +AP_SSID_2G=VanLink # SSID of the 2.4GHz AP (hostapd-2g.conf) +# Radio-specific lines for the 5GHz AP: hostapd lines separated by the two characters \n +# (the GNU sed used by `render` expands them to newlines). Keep it in single quotes, e.g. +# AP_5G_RADIO='ht_capab=[HT40+][SHORT-GI-20]\nvht_capab=[RXLDPC][SHORT-GI-80]' +AP_5G_RADIO='ht_capab=[HT20][SHORT-GI-20]' + # --- Addressing --------------------------------------------------------------- GATEWAY_IP="10.42.9.1" GATEWAY_PREFIX="24" diff --git a/hosts/wan.conf b/hosts/wan.conf index d7fd2f9..7e7efa5 100644 --- a/hosts/wan.conf +++ b/hosts/wan.conf @@ -16,6 +16,11 @@ DHCP_RANGE_END="10.42.0.254" DNS_RESOLVERS="1.1.1.1 8.8.8.8" MODEM_USB_VENDOR=2c7c + +AP_SSID_5G=VanLink +AP_SSID_2G=VanLink +# RTL8852BU: 80MHz VHT/HE on ch 149 (centre 155) +AP_5G_RADIO='ht_capab=[HT40+][SHORT-GI-20][SHORT-GI-40]\nvht_oper_chwidth=1\nvht_oper_centr_freq_seg0_idx=155\nvht_capab=[RXLDPC][SHORT-GI-80][SU-BEAMFORMEE]\nhe_oper_chwidth=1\nhe_oper_centr_freq_seg0_idx=155\nieee80211h=0' NVME_DEVICE= NVME_FS_DEVICE= diff --git a/tests/check-templates.sh b/tests/check-templates.sh index 412db45..dab1921 100755 --- a/tests/check-templates.sh +++ b/tests/check-templates.sh @@ -52,6 +52,12 @@ r() { VANLINK_CONF="hosts/$1.conf" ./deploy.sh render "$2"; } expect() { # expect if r "$1" "$2" | grep -qF -- "$3"; then ok "$1: $2 has '$3'"; else bad "$1: $2 lacks '$3'"; fi } +expect_line() { # expect_line + if r "$1" "$2" | grep -qxF -- "$3"; then ok "$1: $2 has line '$3'"; else bad "$1: $2 lacks line '$3'"; fi +} +expect_absent() { # expect_absent + if r "$1" "$2" | grep -qF -- "$3"; then bad "$1: $2 must not contain '$3'"; else ok "$1: $2 has no '$3'"; fi +} expect van ap/nftables.conf 'ip saddr 10.42.1.0/24' expect wan ap/nftables.conf 'ip saddr 10.42.0.0/24' expect van ap/van-br0-setup.service 'brctl addif br0 enP1p17s0' @@ -63,6 +69,19 @@ expect van ap/van-ap-unmanaged.conf 'interface-name:enP1p17s0' expect wan ap/van-ap-unmanaged.conf 'interface-name:enx00e04c331140;interface-name:eth0' expect wan ap/23-van-lan-eth0.network 'Name=eth0' expect van power/nvme-watch-config.json '"nvme_device": ""' +expect wan ap/hostapd.conf 'interface=wlxc83a35a4ee55' +expect van ap/hostapd.conf 'interface=wlp1s0' +expect wan ap/hostapd-2g.conf 'interface=wlxf4f26d1760a7' +expect van ap/hostapd-2g.conf 'interface=wlx3c3332002066' +expect_line wan ap/hostapd.conf 'ssid=VanLink' +expect_line van ap/hostapd.conf 'ssid=VanLink2' +expect_line wan ap/hostapd-2g.conf 'ssid=VanLink' +expect_line van ap/hostapd-2g.conf 'ssid=VanLink2-2G' +expect_line wan ap/hostapd.conf 'vht_oper_chwidth=1' +expect_line wan ap/hostapd.conf 'he_oper_centr_freq_seg0_idx=155' +expect_line wan ap/hostapd.conf 'ieee80211h=0' +expect_line van ap/hostapd.conf 'he_su_beamformee=1' +expect_absent van ap/hostapd.conf 'vht_oper_chwidth' if r van ap/van-ap-unmanaged.conf | grep -q 'eth0'; then bad "van: unmanaged-devices must not mention eth0 (ONBOARD_LAN_IFACE is empty)" else @@ -114,5 +133,22 @@ if out=$(./deploy.sh --diff hosts/van.conf 2>&1) && echo "$out" | grep -qE '^(NE else bad "deploy.sh --diff hosts/van.conf"; echo "$out" | sed 's/^/ /' fi +if echo "$out" | grep -qE '^(NEW|CHANGED) +/etc/systemd/system/van-ap-dnsmasq\.service$'; then + ok "--diff covers plain-install files" +else + bad "--diff does not list plain-install file van-ap-dnsmasq.service" +fi + +# 9. no interface name of one host hardcoded in a shipped file (the hostapd-2g.conf class of bug) +for c in hosts/*.conf; do + for v in WIFI_5G_IFACE WIFI_2G_IFACE LAN_IFACE STARLINK_IFACE; do + val=$(unset "$v"; . "./$c"; echo "${!v}") + if hits=$(git grep -nF -- "$val" -- . ':!hosts' ':!docs' ':!tests' ':!*.md' ':!*.bak'); then + bad "$c: $v value '$val' is hardcoded outside hosts/"; echo "$hits" | sed 's/^/ /' + else + ok "$c: $v value '$val' appears only in hosts/" + fi + done +done exit "$fail"