Commit Graph
6 Commits
Author SHA1 Message Date
Christian Manivong c686fac55e fix(vlans): read bridge-vlan membership from UCI, repair stale tests
get_vlans() relied on `bridge vlan show` for port membership. On devices
whose BusyBox ships without the bridge/ip-full packages the command does
not exist, _send_command returns the shell error, and the parser silently
finds nothing in it. All that survived was the sub-interface fallback,
which restates the bridge topology (br-ap tagged, br-ap.10 untagged) and
never names the uplink port — the only port whose tagging matters.

Measured on two Sophos AP100 (BusyBox 1.37.0): eth0 was absent from the
output entirely, while UCI held ports='eth0:u*' for the management VLAN
and 'eth0:t' for the rest.

UCI bridge-vlan sections are now parsed as a second source. They are
readable without the bridge binary and describe the configured state.
Section collection goes through the type declaration, so named sections
(network.apbr_vlan10) are recognised alongside anonymous ones — the old
regex matched only @bridge-vlan[N], so a hand-built bridge was invisible
even for name lookup. Runtime data keeps precedence where it exists,
since that is what the kernel actually enforces.

Option values are kept raw through collection; stripping quotes there
would collapse ports='lan1:t' 'lan2:t' into a single mangled item.

Also repairs TestGetVlans, red on master since get_vlans() moved to
separate tagged/untagged lists while the tests still asserted the old
'interfaces' key, and TestGetFacts, which never learned about the
number_of_interfaces key get_facts() sets deliberately. Both had left
the interesting behaviour uncovered.
2026-08-17 22:50:08 +07:00
Christian Manivong 6b78ebcacb fix: push_mac_acl() must never set macfilter='disable'
OpenWrt's wifi-scripts validator rejects any macfilter value other than
"allow"/"deny" outright — confirmed on real hardware, setting
macfilter='disable' puts netifd in a permanent restart crash loop with the
radio stuck down. The only way to disable filtering is to delete the option
entirely. Also guards against pushing an empty whitelist (macfilter='allow'
with zero MACs blocks every client outright) by treating it as equivalent
to "off".
2026-07-16 12:05:07 +02:00
Christian Manivong af032a3c4d feat: get_ssids() macfilter/maclist parsing + push_mac_acl()
Adds MAC ACL (whitelist/blacklist) read+write support for wireless SSIDs,
mirroring push_radio_channel's UCI write style. Backs the new Global MAC
ACL feature in netOrk.
2026-07-15 23:19:15 +02:00
Christian ManivongandClaude Sonnet 4.6 4c41345489 fix: push_radio_channel uses 'wifi' (full restart) instead of 'wifi reload'
'wifi reload' only reapplies the running config without physically
changing the channel on many ath9k/ath10k/mt76 hardware+driver
combinations. A full 'wifi' (down + up) cycle is required for channel
changes to take effect.

Also updated the test assertion accordingly.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-25 00:01:03 +02:00
Christian ManivongandClaude Sonnet 4.6 512871b1bb feat: get_channel_scan() + push_radio_channel() in OpenWrtWirelessMixin
get_channel_scan(mode='active'|'passive'):
- Discovers AP-mode interfaces via 'iw dev'
- Runs 'iw dev <iface> scan [passive]' on each AP interface
- Parses BSS blocks: BSSID, SSID, frequency, channel, signal, channel
  width (HT/VHT/HE), band (2.4/5/6 GHz)
- Returns dict[iface → list[ChannelScanEntryDict]]

push_radio_channel(radio, channel):
- Sets channel via 'uci set wireless.<radio>.channel=<ch|auto>'
- Commits and reloads: 'uci commit wireless && wifi reload'
- channel=0 writes 'auto'

Tests: 19 new unit tests covering parse logic, active/passive flag,
AP-only interface filtering, 6 GHz band detection, push command order.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-24 23:26:25 +02:00
Christian Manivong 1f0349aee9 initial commit 2026-05-29 09:10:40 +02:00