Skip to content

Web Misc - #1631

Merged
mattiaswal merged 24 commits into
mainfrom
wifi-web
Sep 16, 2026
Merged

mattiaswal merged 24 commits into
mainfrom
wifi-web

Conversation

@mattiaswal

@mattiaswal mattiaswal commented Sep 14, 2026

Copy link
Copy Markdown
Contributor
  • Add Wi-Fi mesh functionallity in Web
  • Use YANG PATCH where applicable in webui
  • Fix sensor names in WebUI, use sensor label instead of sensor name, this to be able to show radio0 as both radio and temp sensor.
  • Web: Fix a general bug where hidden elements stopped from applying changes
  • yanger: Add wifi mesh-id for mesh networkds
  • Web: Make possible to change mode on a wifi interface, previous you had to recreate it
  • Web: Some security hardening
  • Misc good stuff

Description

Checklist

Tick relevant boxes, this PR is-a or has-a:

  • Bugfix
    • Regression tests
    • ChangeLog updates (for next release)
  • Feature
    • YANG model change => revision updated?
    • Regression tests added?
    • ChangeLog updates (for next release)
    • Documentation added?
  • Test changes
    • Checked in changed Readme.adoc (make test-spec)
    • Added new test to group Readme.adoc and yaml file
  • Code style update (formatting, renaming)
  • Refactoring (please detail in commit messages)
  • Build related changes
  • Documentation content changes
    • ChangeLog updated (for major changes)
  • Other (please describe):

@mattiaswal mattiaswal changed the title Wifi web Web Misc Sep 15, 2026
'iw dev info' reports no SSID for a mesh interface, so the leaf stayed
empty in operational status, in the CLI and in the WebUI.  Ask
wpa_supplicant instead, the one that joined the mesh, so the mesh id is
absent until it actually has rather than echoing what was configured.

wpa_supplicant prints SSIDs through printf_encode(), so the value needs
decoding.  Scan results have done that all along; factor it out and use
it for both.

Signed-off-by: Mattias Walström <lazzer@gmail.com>
admin@jaffa:/> show interface wifi-mesh
name               : wifi-mesh
type               : wifi
index              : 17
mtu                : 1500
operational status : up
ip forwarding      : disabled
physical address   : 82:0c:43:26:60:00
ipv4 addresses     :
ipv6 addresses     :
in-octets          : 1181221
out-octets         : 743429
mode                : mesh-point
mesh-id             : laser-mesh
connected peers     : 2
A PHY's hwmon device is named after the radio, so its temperature sensor
claimed "radio0" and unique_names() renamed the radio component itself
"radio0-1".  Interfaces reference their radio by name, so nothing could
match an interface to its radio any more: 'show hardware' and the WebUI
both lost the link.

Make the sensor a child of the radio instead, named radio0-temp, the way
the SoC sensor sits under the CPU.

Signed-off-by: Mattias Walström <lazzer@gmail.com>
Mesh point interfaces could only be created and inspected through the
Advanced YANG tree.  Add them to the interface wizard and editor, and
show mesh id and peers on the WiFi and interface status pages.  Station
status gains the BSSID it is associated to, so the access points of a
roaming ESS can be told apart.

Access point roaming (802.11k/r/v, band steering, OKC) gets its own
editor section.  The whole wifi container is written in one PUT: a merge
can neither drop an unticked presence container nor revert a leaf to its
default.

Roaming and mesh forwarding stay on the configure page.  They are
config-only leaves with no operational counterpart, and a status page
has no business restating running config as if it were state.

Signed-off-by: Mattias Walström <lazzer@gmail.com>
The editor posted the stored mode in a hidden input and only rendered
that mode's fields, so an interface created as a station could never
become an access point or a mesh point without deleting it or going
through the Advanced YANG tree.

Render every mode's fields, tagged with the modes they belong to, and
let a set of mode radios reveal the matching set.  The save already
replaces the whole wifi container, so the mode left behind goes away
with it.

An interface with no mode configured is in scan-only mode and shows no
mode-specific field until one is picked.

Signed-off-by: Mattias Walström <lazzer@gmail.com>
The inline "+ New" forms for keystore keys and Wi-Fi radios are rendered
hidden inside the form they belong to, with required fields.  Hiding a
control does not take it out of constraint validation, so the browser
refused to submit the surrounding form, and could not focus the offending
field to explain why.  Save WiFi and the Add Interface OK button did
nothing at all, with no error anywhere, for Wi-Fi and WireGuard.

Disable a block's controls whenever it is hidden and enable them when it
opens, so the fields only take part while the user is filling them in.

Verified in a browser against the rendered page: before, the editor form
reported four hidden blockers and the Add dialog five; after, both submit.

Signed-off-by: Mattias Walström <lazzer@gmail.com>
The previous commit disabled the inline "+ New" forms while hidden.  The
same shape is used by the "+ Add" rows on the keystore, users, routes,
DNS, NTP, firewall and hardware pages, and by the DHCP foldouts: fields
rendered inside a form but hidden until a button opens them.

Those are not broken today, because each Add button sits inside the row
it reveals, so nothing pressable is blocked while it is hidden.  They
break the moment a second submit lands in the same form, and the failure
is silent.  Disable every block a reveal hook controls, so a hidden
required field can never take part in validation.

Swept all 24 pages plus the YANG tree fragments in a browser: no page
has a hidden field blocking a pressable button, and every block still
enables its fields when opened.

Signed-off-by: Mattias Walström <lazzer@gmail.com>
mesh_fwding decides whether a node relays for its peers, and nothing
reported it: the WebUI had taken to reading the configured value and
showing it as state, which says nothing about what the mesh is doing.

Add 'get mesh_param' to iw.py, which returns the whole parameter block,
and report the flag from it.  Absent when the driver has nothing to say,
rather than guessed from the YANG default.

Signed-off-by: Mattias Walström <lazzer@gmail.com>
The hardware page printed the component name, so a radio temperature
read "radio0-temp" under a "RADIO0" heading: the same word twice, and a
key that exists only to stay unique.  Show the description the collector
gave it, and where there is none drop the heading the sensor already
sits under, the way 'show hardware' does.  "cpu-thermal" under "cpu"
reads "Thermal".

Signed-off-by: Mattias Walström <lazzer@gmail.com>
Same as the hardware page, but the Overview list has no headings to sit
under, so a row says "radio0" rather than "Temperature", which alone
would be three identical rows on a three-radio board.  The reading is
named as well only where one component reports more than one, an SoC
with a sensor per die.

Signed-off-by: Mattias Walström <lazzer@gmail.com>
The load-time disable sweep disables every control inside the hidden
add-hw-row, and reopening the row skips controls nested in a block that
is itself still hidden, which the country select is. Picking a radio
only cleared .hidden, so the select stayed disabled: required is ignored
on a disabled control, the form submitted without country-code, and
parseWiFiRadio rejected it with "country code is required". Adding a
WiFi radio from Configure > Hardware was impossible.

Signed-off-by: Mattias Walström <lazzer@gmail.com>
A form that edits several nodes had to send one request per node, so a
later failure left the earlier writes in the candidate. rousette applies
a YANG Patch as one edit batch.

Signed-off-by: Mattias Walström <lazzer@gmail.com>
The radio and the wifi container went in two requests, and the wifi half
was written before the radio form was parsed, so a bad channel left a
half-applied edit behind a "save failed" message.

Signed-off-by: Mattias Walström <lazzer@gmail.com>
Signed-off-by: Mattias Walström <lazzer@gmail.com>
Signed-off-by: Mattias Walström <lazzer@gmail.com>
The vlans container is merged instead of replaced, so saving the bridge
form no longer empties the VLAN table of an 802.1Q bridge.

Signed-off-by: Mattias Walström <lazzer@gmail.com>
The presence containers are merged instead of replaced, so re-saving the
form keeps whatever the DHCP client container already holds.

Signed-off-by: Mattias Walström <lazzer@gmail.com>
The picker option carried data-country but the Edit prefill maps fields
by name, so it looked for data-country-code. The select stayed on the
placeholder and every Edit-then-Save failed with "country code is
required".

Signed-off-by: Mattias Walström <lazzer@gmail.com>
The error went to the enclosing form's status span, next to the Save
WiFi button far below the radio box, so it looked like nothing happened.

Signed-off-by: Mattias Walström <lazzer@gmail.com>
Browsers decode header bytes as ISO-8859-1, so the en dash in "1–196"
reached the page as mojibake. Some emitters also concatenated the text
into the JSON unescaped, so a quote in an error message broke the event.

Signed-off-by: Mattias Walström <lazzer@gmail.com>
The edit for a value-less operation was created as a normal node with
no value, which only works for string leaves. Create it opaque, as the
DELETE method already does, so an enumeration or boolean leaf can be
removed inside a patch.

Signed-off-by: Mattias Walström <lazzer@gmail.com>
@mattiaswal
mattiaswal marked this pull request as ready for review September 15, 2026 14:42
adminurl and path come from whatever the LAN advertises. adminurl went
into href through template.URL unchecked, so a javascript: URL got
through (CSP stops it running), and path was string-appended to the
host, so "@evil" moved the link to another host.

Signed-off-by: Mattias Walström <lazzer@gmail.com>
Signed-off-by: Mattias Walström <lazzer@gmail.com>
The YANG tree and /api/data pass the path from the query string, so a
".." segment, a query or fragment went to the device as-is, where nginx
normalised it into other locations with the user's credentials.

Signed-off-by: Mattias Walström <lazzer@gmail.com>

@troglobit troglobit left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice work, reviewed most of this last night, when we discussed the last three fixes, lgtm!

@mattiaswal
mattiaswal merged commit b914fe6 into main Sep 16, 2026
11 checks passed
@mattiaswal
mattiaswal deleted the wifi-web branch September 16, 2026 09:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants