Commit Graph
1198 Commits
Author SHA1 Message Date
Felix Fietkau 1e5d762595 wifi-scripts: pass all wdev.uc interfaces of a radio in one call
setup() ran wdev.uc set_config once per interface, each time with a
configuration of that interface alone. set_config replaces the whole
configuration of the radio, so each call stopped the interfaces of the
calls before it: with two monitors, or a monitor and an adhoc
interface, on one radio, only the last one stayed up. The configuration
also passed through the shell inside single quotes, so a single quote
in an SSID or a mesh_id broke the command, and two of them made the
text between them run as shell code.

Pass all interfaces in one call, also when the radio has none, so that
removed interfaces stop. Pass the arguments as an array, which system()
runs without a shell.

Signed-off-by: Felix Fietkau <nbd@nbd.name>
2026-10-08 09:50:37 +02:00
Felix Fietkau f892303173 wifi-scripts: stop only the wdevs that wdev.uc created on this radio
drop_inactive() kept every name of the state file whose netdev existed,
and the configuration update then stopped it. A name can belong to
another owner by then: the interface moved to another radio, or it is
now an AP of hostapd or a station of wpa_supplicant. The old radio then
deleted the interface of the new owner.

Record the wdev id of each interface in /var/run/wdev-<phy>.id.json,
and keep a name only if the interface dump shows it on this radio with
the recorded id. A state without recorded ids, from an older version,
falls back to the name.

Signed-off-by: Felix Fietkau <nbd@nbd.name>
2026-10-08 09:50:37 +02:00
Felix Fietkau 9e0fb47cbe wifi-scripts, hostapd: handle a netdev that does not come up
Bringing a netdev up can fail, for example with ENOTUNIQ from
ieee80211_do_open() when another running interface of the wiphy has the
same address. wdev_set_up() ignored the result, and wpa_supplicant's
iface_start() and mld_add(), hostapd's bss_check_mld() and wdev.uc went
on as if the netdev ran. wpa_supplicant and wdev.uc also went on after a
failed netdev creation.

Return the error from wdev_set_up(). On a failure to create the netdev
or to bring it up, stop there; after a failure to bring it up, also
remove the netdev. wpa_supplicant leaves the interface not running for
the next start_pending() or mld_start(), hostapd skips the links of the
AP MLD, and wdev.uc drops it from its state for the next setup.

Signed-off-by: Felix Fietkau <nbd@nbd.name>
2026-10-08 09:50:37 +02:00
Felix Fietkau 2883cdbbec wifi-scripts: check the phy of wdev.uc before its use
wdev.uc read phydev.phy before it checked that phy_open() found the
phy, so a missing phy stopped the script with "left-hand side
expression is null" instead of the message "PHY ... does not exist".

Check phydev first and drop the phy variable, which nothing reads. Also
use a logical OR in the check of the command.

Signed-off-by: Felix Fietkau <nbd@nbd.name>
2026-10-08 09:50:37 +02:00
Felix Fietkau 95c635794a wifi-scripts: pass DPP Connectors through, and enable PMF with DPP
ap.uc and supplicant.uc already write dpp_connector, dpp_csign and
dpp_netaccesskey, but the schema did not declare them, so netifd dropped
them before the handlers ran. Declare the three options.

Easy Connect 3.0 section 8.4.2 requires PMF for an association that uses
the DPP AKM, and wpa_supplicant does not enable it by itself. Set
ieee80211w to at least optional on APs and stations that enable dpp.

This also overrides an explicit ieee80211w 0. With sae-compat outside
6 GHz, the base RSNE then advertises PMF, which that mode otherwise
carries only in the RSN override element. On an AP the PMF setting also
enables beacon protection by default. The schema description of dpp
states this.

Signed-off-by: Felix Fietkau <nbd@nbd.name>
2026-10-08 09:50:37 +02:00
Nick Hainke b7b90e4955 ltq-vdsl-vr11-app: start the DSL control before the network
The modem was started after the LED init script, at the very end of
the boot process, although its driver is ready much earlier. On a
FRITZ!Box 7530 the control application started 61 seconds after power
on, 45 seconds after the driver was loaded, and the line needed
another 90 seconds to synchronize.

The LED is handled by ltq-dsl-base now, so start the modem before the
network. This brings the line up earlier by the time the rest of the
boot process takes.

Assisted-by: Claude:claude-fable-5-1
Link: https://github.com/openwrt/openwrt/pull/25599
Signed-off-by: Nick Hainke <vincent@systemli.org>
2026-10-08 09:21:15 +02:00
Michael Pfeifroth 4fed8d3c79 wifi-scripts: enforce WPA3 for all encryption types on 6 GHz
The existing 6 GHz auth_type override only covers mixed modes
(psk-sae, eap-eap2), upgrading them to their WPA3 equivalents.
However, if a user configures pure WPA2 (psk or eap) on a 6 GHz
radio, the configuration falls through unchanged and hostapd rejects
it with a confusing error about invalid AKM suite.

Extend the override to also cover pure WPA2 modes:
  - psk / psk-sae -> sae
  - eap / eap-eap2 -> eap2

This matches the existing silent-upgrade pattern and ensures the
radio comes up regardless of which legacy encryption the user
selected.

Signed-off-by: Michael Pfeifroth <micpf@westermo.com>
Link: https://github.com/openwrt/openwrt/pull/23914
Signed-off-by: Robert Marko <robimarko@gmail.com>
2026-10-01 20:34:18 +02:00
Felix Fietkau 2de3225246 wifi-scripts: take the regdomain from the provisioning partition
A factory reset drops /etc/config/wireless, so a regdomain that the user
set there is gone after the reset. The provisioning partition survives a
factory reset, so read "wireless.country" from it and let it override the
country from board.json when the wireless config is generated:

  provision set wireless.country DE

A provisioned country also keeps the default 5G and 6G interfaces
enabled, which is what a board.json country does today.

The provision package is optional, so the module is loaded at runtime and
a missing module leaves the previous behaviour unchanged.

Signed-off-by: Felix Fietkau <nbd@nbd.name>
2026-09-29 17:29:25 +02:00
Felix Fietkau 54a6f4ee1e wifi-scripts: declare the dpp option in the wifi-iface schema
iface.uc adds the DPP AKM beside the one the encryption keyword selects when
`dpp` is set, which is how a credential naming several AKMs is expressed, but
the option was in no schema. netifd answered "dpp is not present in the
schema" on every reload that used it.

Signed-off-by: Felix Fietkau <nbd@nbd.name>
2026-09-29 17:29:25 +02:00
Felix Fietkau b88dfb64d3 netifd: update to Git HEAD (2026-09-11)
210816c6ab67 bridge: keep hotplug vlan ports across reloads while the bridge is down
5c954b9f70e3 bridge, bonding: only restore the ipv6 setting when it was overridden
625425e08699 vlandev: fail instead of falling back to vid 1 on invalid vid
a8b101fe9a7c vlan: clean up the kernel device when bringing the vlan up fails
d1e5a8499071 vlan: do not free the vlan device with live users on rename failure
efbceaa722d5 vlan, vlandev: use a local buffer for forwarded hotplug vlan lists
ab1e53f20138 vlan: refresh hotplug ops when the parent vlan list changes
68493c7d96f4 device: release the parent claim when enabling a device fails
d25c083f65ec device: validate extra vlan ranges against the valid vid range
61a8bcc59f12 interface: do not bring up an interface pending removal
6905ab6abf5e interface: restore the previous hotplug attachment on a failed add
f597379945ac interface: carry the renew option over on config reload
2fcaee3eb9af ucode: reset VM state after freeing it
4b78f2529c9f ucode: release process resources after the exit callback
aa4f99092de2 extdev: fix use after free in extdev_hotplug_remove
d81d1deb6eef extdev: wait for the external handler when the initial lookup fails
d47841fd0196 extdev: fix nested list handling in device info dumps
0b0250d3381d extdev: parse stats dumps with the stats parameter list
368caea53e9a extdev: track the active state when creating an empty bridge
8f52fd28cb02 extdev: handle device_init failure in __bridge_create
0d5ff9ef2115 extdev: resynchronise devices when the external handler returns
c6c2a2be1afc interface-ip: keep addresses that moved to a different list index
8d77f1b07f20 interface-ip: validate the route source mask
f35f095dbf46 iprule: only keep unchanged rules whose installation succeeded
9b62f2a8195d interface-ip: keep host routes in sync with their parent route
7f6cf9895f93 system-linux: check the nlmsg_parse result in cb_rtnl_event
1e4a008f3a99 bridge: drop force_active when the bridge_empty option is removed
362b76935dd3 bridge: ignore stale member check timer events
32ee16c6f3cc extdev: clear the bridge empty state when removed from the config
ab060e0f1fb5 extdev: cancel pending retry timers on device free
b462dead154d system-linux: fix byte order of multicast GRE tunnel keys
109610f5b5de system-linux: validate FMR ealen and offset before use
c51979e37908 config: match the device when overriding vlan config entries
7e9928f0fc00 config: keep vlan config entries until interfaces are parsed
e97e36f9b5b5 config: accept 'true' for the interface disabled option
06d06c86d757 proto-ucode: obtain script path via stdlib sourcepath()

Signed-off-by: Felix Fietkau <nbd@nbd.name>
2026-09-13 08:21:35 +02:00
Gary Dotzler e801f59cff netifd: avoid pinning mt76 TX worker to NAPI CPU
The packet steering script treats both threaded NAPI and the mt76 TX
worker as tasks belonging to the same wireless device. assign_dev_cpu()
then assigns all of these tasks to the same CPU.

This unnecessarily restricts the mt76 TX worker to the NAPI CPU even
though its affinity does not otherwise need to be constrained.

On MT7988A with MT7996 this caused the TX worker to share CPU3 with the
NAPI thread. Moving it to another CPU increased measured TX throughput
from 1.45 Gbit/s to 2.09 Gbit/s.

Stop matching the mt76 TX worker in the packet steering script. This
leaves its CPU affinity unrestricted and lets the scheduler place it
more appropriately.

Fixes: https://github.com/openwrt/openwrt/issues/24697
Signed-off-by: Gary Dotzler <geldot@protonmail.com>
Link: https://github.com/openwrt/openwrt/pull/25016
Signed-off-by: Robert Marko <robimarko@gmail.com>
2026-09-06 21:25:49 +02:00
David Bauer 93d975fe9c wifi-scripts: iface: set auth_type on unset encryption
parse_encryption returns leaves config.auth_type unset in case
encryption is unset. However, the owe_transition_iface config option for
the unencrypted network is currently only set in case encryption is
explicitly set to 'none'.

These two should be identical in their behavior. Set the encryption to
"none" in case it is unset and do not return. This aligns the behavior
of unset encryption with encryption explicitly set to 'none'.

Signed-off-by: David Bauer <mail@david-bauer.net>
2026-09-06 00:03:43 +02:00
Hideo Sumi e21a4ef958 wifi-scripts: silence iw antenna/distance failures like shell did
The shell mac80211.sh ran both of these with >/dev/null 2>&1:

	iw phy "$phy" set antenna $txantenna $rxantenna >/dev/null 2>&1
	iw phy "$phy" set distance "$distance" >/dev/null 2>&1

The ucode rewrite dropped the redirect, so on any driver without
->set_coverage_class every wifi up now logs

	netifd: radio0 (3302): command failed: Not supported (-95)

with no indication of which command failed. Neither return value is
checked, so the message is pure noise -- but it reads like wifi up
failed, and on ath12k/IPQ5332 it cost real debugging time before the
line was traced back to iw.c:616 rather than to the driver.

Restore the redirect. distance defaults to 0 and antenna to 0xffffffff,
so both calls run on every setup for every radio.

Signed-off-by: Hideo Sumi <hideo.sumi@mugops.com>
2026-09-03 11:38:19 +02:00
Alexander Astrovsky a3357c90be wifi-scripts: mac80211: fix 6 GHz 40 MHz channel configuration for non-AP modes
In `iw_htmode()`, 40 MHz modes (HE40/EHT40) on the 6 GHz band fell through
to the 5 GHz HT40+/HT40- calculation. Since 802.11n HT modes do not exist
in 6 GHz, `iw` commands like `iw dev <ifname> set freq <freq> HT40+` fail
in cfg80211 with `-EINVAL` (`invalid channel definition`).
Fix this by adding 6 GHz band handling in `iw_htmode()` to calculate and
return the 40 MHz center frequency (`40 <center_freq>`).

Signed-off-by: Alexander Astrovsky <astrouski@google.com>
Link: https://github.com/openwrt/openwrt/pull/24876
Signed-off-by: Robert Marko <robimarko@gmail.com>
2026-08-24 19:48:10 +02:00
Alexander Astrovsky f73d3121e7 wifi-scripts: mac80211: fix 6 GHz 40 MHz channel configuration for non-AP modes
In `iw_htmode()`, 40 MHz modes (HE40/EHT40) on the 6 GHz band fell through
to the 5 GHz HT40+/HT40- calculation. Since 802.11n HT modes do not exist
in 6 GHz, `iw` commands like `iw dev <ifname> set freq <freq> HT40+` fail
in cfg80211 with `-EINVAL` (`invalid channel definition`).
Fix this by adding 6 GHz band handling in `iw_htmode()` to calculate and
return the 40 MHz center frequency (`40 <center_freq>`).

Signed-off-by: Alexander Astrovsky <astrouski@google.com>
Link: https://github.com/openwrt/openwrt/pull/24843
Signed-off-by: Robert Marko <robimarko@gmail.com>
2026-08-23 11:44:04 +02:00
Felix Fietkau 6124b11d7a hostapd: report the addresses of the whole PHY to wdev.uc
wdev.uc seeds the address pool of a mesh, adhoc or monitor interface from
config_get_macaddr_list() and from a scan of the wdevs. The call returned
the BSSIDs of one radio, so two kinds of address stayed hidden.

mld_add_bss() assigns the address of an AP MLD when the MLD configuration
arrives. The wdev of the MLD appears later, in bss_check_mld(), during the
first config_set. wdev.uc runs before that call in the setup of a device.
Neither source names the address there, and a new interface could take it.

The BSSIDs of the other radios of the PHY stayed hidden as well. A link of
an MLD has no wdev of its own, so a scan never reports its address.

Return the list that phy_macaddr_list() builds. It holds the addresses of
the MLDs and the BSSIDs of every radio of the PHY. The radio argument loses
its purpose, so drop it.

Signed-off-by: Felix Fietkau <nbd@nbd.name>
2026-08-21 18:09:29 +02:00
Felix Fietkau 8c675d177d wifi-scripts: let macaddr_next() return a given address
macaddr_next() returns the first address of the sequence of the PHY that
is free. A caller that needs one specific address of that sequence cannot
ask for it.

Add the parameter reuse. macaddr_next() returns that address if the PHY
generates it, also when the list marks the address as in use. The caller
owns the address in that case. Without the parameter, the function stops
at the first free address as before.

Signed-off-by: Felix Fietkau <nbd@nbd.name>
2026-08-21 18:09:29 +02:00
Felix Fietkau 8a40ffd07f wifi-scripts: reserve the addresses of MLD interfaces
macaddr_init() calls for_each_wdev() to mark the addresses that are in
use. for_each_wdev() kept a wdev only if the radio mask of the wdev named
the radio of the allocation and no other radio. An MLD uses more than one
radio. Therefore no MLD matched, and the address of each MLD stayed free.

The configuration describes the AP MLDs, and the code reserves them with
the configuration. The MLD of the supplicant is different: hostapd is the
only source of its address. The code gave that address a second time, and
the new interface failed to start:

  Could not set interface phy0.0-ap1 flags (UP)
  Failed to add BSS (BSSID=a2:ad:9f:70:fb:46)

Keep a wdev if it uses the radio, also when it uses other radios.

Signed-off-by: Felix Fietkau <nbd@nbd.name>
2026-08-21 18:09:29 +02:00
Lech Perczak 00045786e6 wifi-scripts: fix default cipher selection for 11ad in iface.uc
hw_mode property is only present in device configuration section,
not the interface section, so testing for config.hw_mode in
iface.parse_encryption is wrong. Test for (dev_config.band == 60g)
instead, this will cause GCMP to be properly selected instead of
CCMP unless set explicitly, and while at that will cover both hostapd
and wpa_supplicant cases.

Signed-off-by: Lech Perczak <lech.perczak@gmail.com>
Link: https://github.com/openwrt/openwrt/pull/24586
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
2026-08-18 01:30:39 +02:00
Lech Perczak aac62cf2e5 wifi-scripts: set hw_mode = 'ad' for 60GHz radios in hostapd config
ucode version of hostapd handler, when setting hw_mode property based on
band, incorrectly matches hw_mode = "a" for 5, 6, and 60GHz, while 60GHz
radios need this set explicitly as "ad".
This causes broken frequency display in LuCI, and potentially other issues,
so add an explicit check for 60GHz band.

Signed-off-by: Lech Perczak <lech.perczak@gmail.com>
Link: https://github.com/openwrt/openwrt/pull/24586
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
2026-08-18 01:30:39 +02:00
Lech Perczak 63d4718713 wifi-scripts: add 60G band to mac80211.uc to support 802.11ad
/etc/config/wireless is missing 60G band for routers supporting it.
This support was enabled in OpenWrt v23 but somehow disappeared in v24.

Run-tested-on: TP-Link Talon AD7200 v2

[Originally authored by Konstantin Glukhov, replaced SoB, because of
lack of real email, reworded commit message]

Signed-off-by: Lech Perczak <lech.perczak@gmail.com>
Link: https://github.com/openwrt/openwrt/pull/24586
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
2026-08-18 01:30:38 +02:00
Omar Avelar 0e371752ae wifi-scripts: restore noscan for sta/adhoc/mesh
Restore the original mac80211.sh behavior by setting noscan when
fixed_freq is enabled for sta, adhoc and mesh modes. This ensures
correct channel width operation for fixed-frequency links and
matches the legacy mac80211.sh behavior.

Signed-off-by: Omar Avelar <host.omar@gmail.com>
Link: https://github.com/openwrt/openwrt/pull/21443
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
2026-08-04 02:30:55 +02:00
Felix Fietkau e18424ddd8 wifi-scripts: keep radio config out of the MLD configuration
wpad decides whether to keep or tear down an MLD interface by comparing the
whole configuration object, which embedded the full device configuration of
every participating radio. Any radio level change, such as a channel or
txpower update, therefore destroyed and recreated the station MLD and
dropped the backhaul link. Neither hostapd nor wpa_supplicant reads
radio_config; it is only used locally to resolve the phy.

Signed-off-by: Felix Fietkau <nbd@nbd.name>
2026-08-01 10:55:13 +02:00
David Bauer 3189ea8fe4 wifi-scripts: fix rate settings
hostapd changed the configuration of basic and supported rates to a
per-bss setting. This left the current phy global settings unapplied.

Apply the rate settings in uci on each VAP of a PHY.

In the future, this setting can theoretically also be set per-bss
in uci. However it is not part of this patch.

Link: https://git.w1.fi/cgit/hostap/commit/?id=f7be1b53852a069f0d15eb471a6f9158467ab117

Signed-off-by: David Bauer <mail@david-bauer.net>
2026-07-30 11:07:43 +02:00
David Bauer d1885e98ff wifi-scripts: fix stray whitespaces
Signed-off-by: David Bauer <mail@david-bauer.net>
2026-07-30 11:04:39 +02:00
Felix Fietkau 2c64257627 wifi-scripts: support multiple device paths per board.json wlan entry
The path field of a board.json wlan entry may now be an array of
device paths. ucidef_add_wlan accepts several leading path arguments
and stores them as a JSON array; a single path is still stored as a
plain string for backwards compatibility. A phy is matched if it
corresponds to any of the listed paths, so a radio that enumerates on
a non-deterministic PCI path still resolves to the correct named phy.

Signed-off-by: Felix Fietkau <nbd@nbd.name>
2026-07-22 09:32:52 +02:00
Felix Fietkau 766052bab3 wifi-scripts: don't swap handler config under a running setup script
A reload during an in-flight setup ran wdev_config_init() immediately,
replacing handler_config/handler_data while the script was still running, so
its set_data notifications resolved against the new (renumbered) interface
table and link up/down calls became asymmetric. Defer the re-init in
check() while a handler run is in progress and re-apply from the setup and
teardown callbacks once it completes.

Signed-off-by: Felix Fietkau <nbd@nbd.name>
2026-07-16 11:50:22 +02:00
Felix Fietkau e6bd2af652 wifi-scripts: only manage wdev interfaces recorded in the statefile
wdev.uc adopted every operstate-down netdev on the phy and then removed any
not in its new config. hostapd BSS netdevs are legitimately operstate-down
while stopped (co-located STA down, or start_disabled), so a reload deleted
them and hostapd, seeing an unchanged config, never recreated them. Drop the
adopt-existing step; the statefile already tracks the interfaces wdev.uc
owns.

Signed-off-by: Felix Fietkau <nbd@nbd.name>
2026-07-16 11:50:22 +02:00
Felix Fietkau 1789118599 wifi-scripts: give the OWE-transition BSS its own MAC address
The transition BSS is a copy of the main BSS with the MAC already set, so
iface.prepare() was a no-op and both BSSes emitted the same bssid; with a
fixed or random MAC the duplicate was never reassigned and the second
interface failed to come up. Clear the address (and stale flags) and
prepare a fresh one, plumbing the phy/num_global/macaddr_base through
iface_setup().

Signed-off-by: Felix Fietkau <nbd@nbd.name>
2026-07-16 11:50:22 +02:00
Felix Fietkau 4062d625ae wifi-scripts: emit per-line hostapd options correctly
append() space-joins list options into one line, which breaks hostapd
options that are parsed one entry per line: anqp_elem, nai_realm,
venue_name, venue_url, hs20_conn_capab and the radius req_attr lists (a
parse error there fails the whole phy). Add append_list() to emit one line
per element and route those options through it. vendor_elements is instead
a single concatenated hex blob (join ''), and iface_interworking() no
longer overwrites domain_name with the 3GPP cell-net data (and uses ';').

Signed-off-by: Felix Fietkau <nbd@nbd.name>
2026-07-16 11:50:22 +02:00
Felix Fietkau 56d466a75d wifi-scripts: use country_code for iw reg set in setup_phy
validate() converts the country alias to country_code and deletes country
before setup_phy() runs, so the iw reg set branch tested a null
config.country and never ran, leaving wdev-only radios (adhoc/mesh/monitor)
on the world regdomain. Use config.country_code.

Signed-off-by: Felix Fietkau <nbd@nbd.name>
2026-07-16 11:50:22 +02:00
Felix Fietkau 73c35f97f3 wifi-scripts: quote dpp_connector in the station config
dpp_connector was emitted unquoted, but wpa_supplicant parses it as a
string and hex-decodes an unquoted value; a base64url connector then failed
to parse and the network block was rejected. Emit it via the quoted-string
list. dpp_csign/dpp_netaccesskey stay raw, as they are hex.

Signed-off-by: Felix Fietkau <nbd@nbd.name>
2026-07-16 11:50:22 +02:00
Felix Fietkau 06b3ef0ff5 wifi-scripts: use the base phy name for config_get_macaddr_list
phydev.name is already radio-suffixed, and the hostapd handler re-applies
the suffix, so on multi-radio phys the lookup missed and the returned MAC
list was always empty, letting wdev.uc reuse a MAC hostapd had reserved for
an AP BSS. Pass the base phy and radio index.

Signed-off-by: Felix Fietkau <nbd@nbd.name>
2026-07-16 11:50:22 +02:00
Felix Fietkau 97e8911c9b wifi-scripts: pass device config to parse_encryption for station mode
setup_sta() called parse_encryption() without the device config, so the
sae-compat branch dereferenced a null dev_config.band and threw, aborting
the whole radio setup. Pass the device config through.

Signed-off-by: Felix Fietkau <nbd@nbd.name>
2026-07-16 11:50:22 +02:00
Felix Fietkau 0bab595808 wifi-scripts: map the configured pairwise cipher for station mode
Only an exact GCMP cipher was mapped to the network block; other explicit
ciphers (CCMP-256, GCMP-256, TKIP variants) left pairwise unset, so
wpa_supplicant offered its default set and could not associate with an AP
restricted to the configured cipher. Pass wpa_pairwise through, keeping the
GCMP special case that also pins group.

Signed-off-by: Felix Fietkau <nbd@nbd.name>
2026-07-16 11:50:22 +02:00
Felix Fietkau 105dd239ac wifi-scripts: do not treat WDS-station VLAN subinterfaces as the base wdev
The hotplug match /(.+)\.sta.+/ also matched VLAN subinterfaces of a WDS
station (e.g. wlan0.sta1.100 -> wlan0), so the tagged subinterface was added
into the vif base networks, breaking VLAN separation. Anchor the pattern to
the plain station suffix.

Signed-off-by: Felix Fietkau <nbd@nbd.name>
2026-07-16 11:50:22 +02:00
Felix Fietkau dc33d7bcb1 wifi-scripts: pass multicast_to_unicast as an integer
handle_link() passed the option as a ucode boolean, but the netifd
device_set binding reads it with prop_get_int (UC_INTEGER only) and ignored
a boolean, so the option was a no-op. Convert it to 0/1.

Signed-off-by: Felix Fietkau <nbd@nbd.name>
2026-07-16 11:50:22 +02:00
Felix Fietkau fedefbf50f wifi-scripts: reset the retry counter on successful setup
retry was only reset on config change/start, never on a successful setup,
so occasional transient setup failures accumulated over a device lifetime
and latched retry_setup_failed after three cumulative failures. Reset it
when the device comes up.

Signed-off-by: Felix Fietkau <nbd@nbd.name>
2026-07-16 11:50:22 +02:00
Felix Fietkau 5379d034e0 wifi-scripts: fix VLAN key for service-injected wifi-iface
Service data VLANs were stored under vif_data.vlans, but every consumer
reads vif.vlan, so per-VLAN config from a procd service was silently
dropped. Use the singular key, matching the adjacent station handling.

Signed-off-by: Felix Fietkau <nbd@nbd.name>
2026-07-16 11:50:22 +02:00
Felix Fietkau 39507969ff wifi-scripts: return the interface-creation result from wdev_add
wdev_add() dropped the wdev_create() result, so every caller's error check
was dead and an nl80211 NEW_INTERFACE failure was silently ignored (hostapd
and wpa_supplicant then proceeded on a missing netdev with stale MLD
bookkeeping). Return the result.

Signed-off-by: Felix Fietkau <nbd@nbd.name>
2026-07-16 11:50:22 +02:00
Felix Fietkau 28c6f5e6f7 wifi-scripts: fix extended-feature bit test
device_extended_features() used bitwise OR instead of AND, so every
extended-feature query returned true regardless of the driver bitmap:
ftm_responder and radar_background were always reported present.

Signed-off-by: Felix Fietkau <nbd@nbd.name>
2026-07-16 11:50:21 +02:00
Felix Fietkau 5917907471 wifi-scripts: do not report a disabled wifi-device as up
A disabled wifi-device is intentionally still run through the setup path
(with no interfaces) to reliably tear down hostapd/wpa_supplicant and to
handle disabled/enabled flapping, so it reaches state "up" and status
reported up: true alongside disabled: true. Exclude disabled devices from
the up state in status instead.

Signed-off-by: Felix Fietkau <nbd@nbd.name>
2026-07-16 11:50:21 +02:00
Felix Fietkau 5b47cec245 wifi-scripts: emit a raw 64-hex PSK unquoted for station mode
A 64-character hex PSK was always quoted, but wpa_supplicant rejects a
quoted passphrase longer than 63 characters, so the network block failed
and the STA never associated while netifd still reported the radio up. Emit
the key unquoted when it is a 64-character raw PMK, matching the AP path.
The sae_password branch keeps quoting, as SAE passwords are arbitrary
strings.

Signed-off-by: Felix Fietkau <nbd@nbd.name>
2026-07-16 11:50:21 +02:00
Felix Fietkau 830ae67b44 wifi-scripts: honour a cancelled setup when the handler reports up
stop() and destroy() set cancel_setup while a setup handler is running, but
nothing read it, so a device brought down (or removed) mid-setup still went
up and stayed up, holding its interface links. Check the flag (and
autostart/delete) in wdev_mark_up and tear the device down instead of
completing the up transition.

Signed-off-by: Felix Fietkau <nbd@nbd.name>
2026-07-16 11:50:21 +02:00
Felix Fietkau eb5ccabf0e wifi-scripts: fix undeclared variable in service wifi-device injection
The wifi-device injection path used object shorthand `name` where no such
variable is in scope (the loop binds radio/config), so under the strict VM
config_init threw and the whole wireless configuration for that reload was
skipped. Use the radio key as the device name.

Signed-off-by: Felix Fietkau <nbd@nbd.name>
2026-07-16 11:50:21 +02:00
Felix Fietkau b0d8ab4fef wifi-scripts: emit frequency and STA-channel markers in hostapd config
Emit #frequency (the target channel frequency, already computed during phy
setup) and #channel_owned_by_sta (set when a co-located STA/mesh/adhoc on
the same band dictates the runtime channel) into the generated config.
The hostapd daemon uses these to decide whether a channel change can be
applied via CSA instead of a full restart.

Signed-off-by: Felix Fietkau <nbd@nbd.name>
2026-07-16 11:50:21 +02:00
Shine d47ce71a89 scripts: dhcp: option to override preferred Client ID per interface
Using UUID-based client IDs for DHCPv4/DHCPv6 with no option of falling
back to hardware IDs (ie. MAC-address or DUID-LL) resp. none at all (IPv4),
is causing regressions in some setups.

Introduce a new setting to override the preferred client ID to be used for
DHCPv4/DHCPv6 on a per-interface basis:

network.<ifname>.sendclientid='auto|global|hardware|none'

- "auto" (default if empty or not present) uses any explicitly defined
  client ID, or falls back to the global DUID and finally to the DUID-LL
  resp. MAC address (ie. identical to before this commit).
- "global" uses the global default DUID, if configured, for DHCPv4 and
  DHCPv6 requests, even if a client ID is explicitly specified for the i/f
- "hardware" will not pass a client ID to udhcpc/odhcp6c, even if a global
  default DUID is configured or an explicit client ID specified, resulting
  in the i/f MAC address resp. type 3 DUID(-LL) to be used
- "none" (IPv4 only) will not add an option tag 61 to DHCPv4 requests at
  all.

Signed-off-by: Shine <4c.fce2@proton.me>
Link: https://github.com/openwrt/openwrt/pull/24107
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
2026-07-11 17:30:55 +02:00
Harin Lee b664ec8ab1 wifi-scripts: fix macaddr lookup in utils.uc
This fixes a simple logic error of the macaddr lookup in utils.uc.
It read from the wrong sysfs file and compared it without trimming.

Signed-off-by: Harin Lee <me@harin.net>
Link: https://github.com/openwrt/openwrt/pull/24070
Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
2026-07-09 09:28:08 +02:00
Felix Fietkau c5854d65f2 netifd: update to Git HEAD (2026-07-08)
c0abf80df1c1 config: fix NULL pointer dereference when typed device creation fails
4a19d2568c0b device: migrate alias users when replacing a device
e2f28e5ec0a8 interface: defer interface removal to avoid use-after-free
34760f2aec34 interface: fix alias handling when the parent interface does not exist
0bab70f05296 bridge: cancel the member retry timer on teardown and free
a562a8eca41d bridge: fix memory leak of hotplug member vlan ranges
4c7b3f7caf88 proto-ext: clear the proto task kill flag when starting a new task
8a38aecd84de system-linux: include the priority when deleting ip rules
844c0fe78eed device: remove unused __devlock counter
dbdf0d0e5830 system-linux: initialise FMR prefix lengths before parsing
fb456b5e65df iprule: keep unchanged rules installed on reload
7d8f9900c273 vrf: sync changes with bonding.c/bridge.c
f0db4101c1ea vrf: remove incorrect IPv6 disable on VRF ports
9dfea5b242b2 vrf: remove unused vrf_empty field
6f6bf8bec23b vrf: rename vrf_state_type to vrf_device_type
37c770a6b86d vrf: add license header
35171a157516 system-linux: fix system_vrf_addif retry loop
6cbcc107e984 bonding: cancel the port retry timer on teardown and free
787848926a19 extdev: fix invalid frees and unwind order on handler registration failure
2a8ed44dc613 interface-ip: fix address family check when removing offlink null-routes
576e1f3de154 interface-ip: preserve subnet route state when keeping an address
10f25df801c1 bridge: fix parsing of the stp_kernel option
3132f007ebf0 bonding: skip present toggle in bonding_free_port() when device is active
24950e564fff bonding: fix stale primary_port pointer after port enable failure
4c8374dc0f79 interface: fix zone string leak on config reload
65e96ba990b2 ubus: fix netns fd leak in netns_updown error path
fa9ee5efd4b2 utils: fix out-of-bounds fallback in uci_get_validate_string
6ccbf71d7a97 utils: fix false positives and dead branch in check_pid_path
3ec503831ebd iprule: default src/dest masks to the host prefix length
9a520edc3be4 system-linux: implement the neighbour flush in system_if_clear_entries
62b6256bf95c system-linux: fix vxlan link creation with gbp disabled
6c0a837f10fc system-linux: fix rtnl socket desync when clearing kernel entries
d1a0ceb71991 macvlan: fix NULL dereference when dumping a device without parent
937c3aa801af vlandev: fix NULL dereference when dumping a device without parent
89025924ba51 vlan: fix device chain lookup for names with a non-vlan separator
c961d1e16814 vlan: fix rejection of maximum length vlan device names
1cbf89e3108c vlandev: fix type of vlan alias lookup result
08a4a7b33056 proto-ext: fix stuck state machine when the setup script fails to launch
c8c8b79a5bcb proto-ext: queue restart requests while a script task is running
0c990ce2ca09 ubus: report failure from the interface restart method
e6af4a5bf6f2 interface: fix undefined shift when computing the ip6hint mask
67f8107fb21c interface-ip: fix undefined shifts in prefix assignment arithmetic
903bd1c3daa5 interface-ip: fix out-of-bounds access in clear_if_addr for zero masks
56ffff895672 system-linux: fix ethtool feature block count
bbc818a6527f system-linux: fix EINTR retry in read_string_file
9c2970832d8f system-linux: fix off-by-one in vxlan VNI validation
c5b5d54ce2f9 bridge: validate the upper bound of hotplug vlan ranges
1595cd7b25da main: handle execvp failure on restart
24b2703171fe handler: guard against zero-length lines when parsing handler dumps
c2b760fc7cc5 handler: free glob results in netifd_init_extdev_handlers
60e3243bdcd8 handler: reject negative parameter types in handler descriptions
274b1594e0ca interface-ip: tear down the ULA prefix on an invalid prefix length
e692ec77d51b interface-ip: expire config routes with a valid option
684dc2d50902 device: fix error handling in device_create
c02101330247 interface: fully clean up partially constructed interfaces on free
1db485d6a39c handler: clear parameter list pointers on parse failure
5694c49f964f system-linux: stop receive loops on netlink errors
d108c504df4e system-linux: fix bogus master ifindex result for non-DSA devices
d6f609170f1e system-linux: fix swapped rx/tx in negotiated pause reporting
8a19380586ef extdev: fix NULL pointer dereference when parsing stats params
a1cc96488c02 extdev: fix memory leaks on device free
d2085a59abbc extdev: fix bridge config leak on no-op reload
4d1a4ae487b6 ucode: close pipe read end in spawned child processes
6c407410259c config: validate bridge vlan port and alias attributes
8afd58bead2f bridge: fix pvid clearing leaking to other vlan members
e8edb3f78652 bonding: fix port failure accounting in bonding_enable_port
6088f7b3b9d7 system-dummy: fix metric clobbering device name in route debug output

Signed-off-by: Felix Fietkau <nbd@nbd.name>
2026-07-08 10:48:43 +02:00
Hauke Mehrtens 649b42331c wifi-scripts: restore priv_key/priv_key_pwd as config aliases
The shell config generator read the client private key from the UCI
options priv_key / priv_key_pwd (and priv_key2 / priv_key2_pwd for the
inner tunnel). The ucode generator was switched to private_key /
private_key_passwd (matching the wpa_supplicant field names), and LuCI
was updated accordingly, but existing configurations still carry the old
option names.

Such configs silently lose their private key: for an EAP-TLS client this
leaves wpa_supplicant without a client key and authentication fails after
upgrading from 24.10.

The schema already lists priv_key / priv_key_pwd, but as plain strings,
so validate() never migrates them. Declare them (and the missing
priv_key2 / priv_key2_pwd) as aliases of the private_key* options so the
old names keep working.

Fixes: https://github.com/openwrt/openwrt/issues/22599
Fixes: 218f3884d2 ("wifi-scripts: add ucode based scripts")
Assisted-by: Claude:claude-opus-4-8
Link: https://github.com/openwrt/openwrt/pull/24088
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
2026-07-07 01:50:56 +02:00