Commit graph

1168 commits

Author SHA1 Message Date
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
Hauke Mehrtens
7be144ad83 wifi-scripts: ucode: fix EAP certificate constraint handling
The supplicant config generator emitted the altsubject_match,
domain_match and domain_suffix_match server certificate constraints
through the plain (unquoted) variable list. As these are UCI arrays,
they were rendered space-separated and without quotes, e.g.

  altsubject_match=DNS:a.example.com DNS:b.example.com

wpa_supplicant parses an unquoted string value as a hex blob, so such a
line fails to parse and the constraint is dropped. wpa_supplicant
expects a single quoted, semicolon-separated string:

  altsubject_match="DNS:a.example.com;DNS:b.example.com"

Join these lists with semicolons and emit them as quoted strings.

The inner-tunnel (phase 2) constraints subject_match2, altsubject_match2,
domain_match2 and domain_suffix_match2 were not written to the config at
all; emit them as well. Add the matching inner EAP-TLS options ca_cert2,
client_cert2, private_key2 and private_key2_passwd to the schema so they
validate cleanly.

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
Hauke Mehrtens
0cdf956ee1 wifi-scripts: ucode: fix EAP phase2 authentication method
The supplicant config generator emitted the phase2 directive as
phase2="auth=${auth}" for every PEAP/TTLS/FAST configuration. That is
wrong whenever the configured inner method is an EAP method: for
auth='EAP-MSCHAPV2' it produced phase2="auth=EAP-MSCHAPV2", which
wpa_supplicant rejects with:

  TLS: Unsupported Phase2 EAP method 'EAP-MSCHAPV2'

breaking WPA-Enterprise clients that use an EAP inner method.

Mirror the shell config generator (hostapd.sh): strip the "EAP-" prefix
and pick the phase2 prefix from the method type, i.e. "autheap=" for a
tunneled EAP method with TTLS and "auth=" for a non-EAP method or a
full "auth=..." spec provided by the user.

Fixes: https://github.com/openwrt/openwrt/issues/24086
Fixes: c92ded2f6e ("wifi-scripts: fix EAP STA support in supplicant config generation")
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
Hauke Mehrtens
5e067465ff wifi-scripts: ucode: add gcmp256 option, default GCMP-256 per WPA3 mode
Commit 1f86f4e471 ("wifi-scripts: ucode: simplify wpa_pairwise default
selection") made HE and EHT BSSes default their pairwise cipher to
"GCMP-256 CCMP", and commit 86b9eec8f0 ("wifi-scripts: ucode: add
WPA3-Personal Compatibility Mode") always put GCMP-256 into the RSNE
Override 2 element on EHT compatibility-mode BSSes.

WPA3 Specification v3.5 only makes GCMP-256 mandatory when the BSS enables
EHT or MLO (section 2.5, item 5); for HE and below the WPA3 and Wi-Fi
Enhanced Open Deployment Guide v1.1 lists it as recommended, not required.
Advertising it by default causes interoperability problems: several
clients fail to associate when GCMP-256 is offered as a pairwise cipher
and connect again with CCMP only (Nanoleaf devices, a Motorola/Unisoc
phone, a Linux/iwd laptop).

Add a gcmp256 UCI option and, like sae_ext_key, default it on only where
GCMP-256 is both mandatory and safe: on Compatibility mode (sae-compat)
BSSes running an EHT htmode, which carry it in a separate RSNE Override 2
element that legacy clients ignore. It defaults off for WPA3-Personal
(sae) and Transition (sae-mixed) mode and on non-EHT BSSes. An explicit
'option gcmp256 0/1' overrides the default per BSS.

Both GCMP-256 pairwise defaults now key off config.gcmp256 (and, from the
earlier driver-support change, the phy actually implementing the cipher):
the sae/sae-mixed "GCMP-256 CCMP" pairwise cipher and the sae-compat RSNE
Override 2 element. The 'encryption sae+gcmp256' suffix and the wpa3-192
mode still force GCMP-256 as before.

Fixes: 1f86f4e471 ("wifi-scripts: ucode: simplify wpa_pairwise default selection")
Fixes: 86b9eec8f0 ("wifi-scripts: ucode: add WPA3-Personal Compatibility Mode")
Assisted-by: Claude:claude-opus-4-8
Link: https://github.com/openwrt/openwrt/pull/24041
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
2026-07-07 00:42:00 +02:00
Hauke Mehrtens
fc652db52a wifi-scripts: ucode: default the SAE-EXT-KEY AKM per WPA3 mode
Commit a12cec9ea3 ("wifi-scripts: ucode: advertise SAE-EXT-KEY AKM
alongside SAE") advertised the SAE-EXT-KEY AKM (00-0F-AC:24, SAE using a
group-dependent hash, aka SAE-GDH) by default on every sae, sae-mixed and
sae-compat BSS.

WPA3 Specification v3.5 only makes this AKM mandatory when the BSS enables
EHT or MLO (section 2.5, item 4); for HE and below it is merely
recommended (sections 2.2 and 2.3). In practice the FT-SAE-EXT-KEY AKM
(SAE-EXT-KEY combined with 802.11r), which gets added automatically once
Fast Transition is enabled, keeps some clients from associating (a Samsung
Galaxy Tab S10 FE) or makes them reboot shortly after connecting (a Poco
X6). Plain SAE-EXT-KEY without FT was seen to work on the same tablet, but
its interoperability is not well tested.

Drop the fixed schema default and pick the default from the auth type in
parse_encryption instead. Only default it on where it is both mandatory
and safe to offer: on Compatibility mode (sae-compat) BSSes running an EHT
htmode, which carry it in a separate RSN Override element that legacy
clients ignore. Keep it off for WPA3-Personal (sae) and Transition
(sae-mixed) mode, where it would sit in the main RSNE that a choking
client cannot ignore, and off on non-EHT BSSes. An explicit
'option sae_ext_key 0/1' still overrides this per BSS.

The SAE-EXT-KEY AKM in the sae-compat RSN Override 2 element now keys off
config.sae_ext_key alone; the extra config.rsn_override_pairwise_2 guard
is dropped, decoupling the AKM from the GCMP-256 pairwise cipher so each
follows its own option.

Fixes: a12cec9ea3 ("wifi-scripts: ucode: advertise SAE-EXT-KEY AKM alongside SAE")
Assisted-by: Claude:claude-opus-4-8
Link: https://github.com/openwrt/openwrt/pull/24041
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
2026-07-07 00:42:00 +02:00
Hauke Mehrtens
05e87cfcb6 wifi-scripts: ucode: only advertise GCMP-256 when the driver supports it
The GCMP-256 pairwise cipher was advertised based only on the BSS htmode
(HE/EHT), without checking whether the driver actually implements it. On
phys that do not support GCMP-256 this makes hostapd reject the
configuration and fail to start.

Query the phy's NL80211 cipher suite list in device_capabilities() and
expose a phy_features.cipher_gcmp256 flag, then only offer GCMP-256 when
the driver advertises the GCMP-256 cipher suite (00-0F-AC:9, 0x000fac09),
mirroring how the HT/VHT feature flags are already gated on the reported
phy capabilities. This covers both the sae/sae-mixed "GCMP-256 CCMP"
pairwise default and the GCMP-256 pairwise cipher in the sae-compat RSNE
Override 2 element.

The "GCMP-256 CCMP" default now keys off driver support alone instead of
the htmode; a follow-up commit reintroduces the per-mode/EHT restriction
via a gcmp256 option.

Fixes: 1f86f4e471 ("wifi-scripts: ucode: simplify wpa_pairwise default selection")
Fixes: 86b9eec8f0 ("wifi-scripts: ucode: add WPA3-Personal Compatibility Mode")
Assisted-by: Claude:claude-opus-4-8
Link: https://github.com/openwrt/openwrt/pull/24041
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
2026-07-07 00:42:00 +02:00
Richard Huynh
da28c7a67e wifi-scripts: add EHT beamforming options to hostapd config
Some EHT options like beamformer/beamformee
are disabled by default in hostapd.conf

Read the EHT Phy Cap structure and enable/disable
switches within the hostapd.conf for capable hardware.

Without this EHT SU beamformer/beamformee and MU
beamformer capabilities are omitted from AP beacons,
even if the driver reports the hardware as capable.

Signed-off-by: Richard Huynh <voxlympha@gmail.com>
Link: https://github.com/openwrt/openwrt/pull/22956
Signed-off-by: Robert Marko <robert.marko@sartura.hr>
2026-07-01 19:03:55 +02:00
Felix Fietkau
365c6232c0 qosify: update to Git HEAD (2026-06-22)
298754f6ded2 map: add NQB DiffServ codepoint
d26cc573f36c qosify: account for bytes in traffic class statistics
0edbc51af3b6 qosify: group traffic class stats under a "classes" table
fe8491da8daf qosify: add per-DSCP traffic statistics
181a691407ee dns: track cname cache hit/miss statistics
cece4e23a9df qosify: track per-DNS-pattern traffic statistics
6b4be193a6dd qosify: report eBPF map entry count and last reload time
e57b34046341 qosify: account for GSO segment count in packet statistics
c49e72a4a45d qosify-bpf: remove unused variable in classify()
44ce40f8e083 qosify: count all traffic in per-DSCP statistics
beeb87ec1f16 qosify: expose default traffic classes in statistics

Signed-off-by: Felix Fietkau <nbd@nbd.name>
2026-07-01 13:15:44 +02:00
Florian Maurer
946b820856
wifi-scripts: ucode: check wpa_supplicant exists before mesh probe
The mesh capability check unconditionally ran wpa_supplicant -vmesh to
detect driver support. On devices where wpa_supplicant is not installed,
this produces a "/bin/sh: wpa_supplicant: not found" error in the logs
on every wifi reconfiguration even when no mesh interface is configured.

Guard the invocation with fs.access() so the binary is only executed
when it is actually present, and use its absolute path to avoid relying
on $PATH.

Signed-off-by: Florian Maurer <fmaurer@disroot.org>
Link: https://github.com/openwrt/openwrt/pull/23607
Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
2026-06-29 09:26:56 +02:00
Florian Maurer
010e8b731a
wifi-scripts: ucode: remove trailing whitespace
Removes trailing whitespace from mac80211.sh

Signed-off-by: Florian Maurer <fmaurer@disroot.org>
Link: https://github.com/openwrt/openwrt/pull/23607
Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
2026-06-29 09:26:56 +02:00
Florian Maurer
0d747a8edb
wifi-scripts: ucode: only set antenna when config changes
mac80211's ieee80211_set_antenna() rejects calls with -EOPNOTSUPP once
the radio is started (local->started == true). The spurious failure
triggers a wpa_supplicant invocation in the error path, producing both
a "command failed: Not supported (-122)" message and (where wpa_supplicant
is not installed) a "/bin/sh: wpa_supplicant: not found" message in the
log on every wifi reconfiguration.

In this code path, reset_config() tears down all interfaces before the
antenna is touched, so local->started is false exactly when the antenna
config has changed. Skip the iw phy set antenna call otherwise, matching
the behaviour of mainline OpenWrt's bash mac80211.sh. The trade-off is
that we no longer re-assert the antenna mask on warm reconf if it was
cleared out-of-band (e.g. by a driver reload); in practice drivers do
not clear it mid-life.

Also split the antenna details out of the generic "Configuring '${phy}'
distance: ..." log line so it isn't claimed when the call was skipped.

Assisted-by: Claude:claude-sonnet-4-6
Signed-off-by: Florian Maurer <fmaurer@disroot.org>
Link: https://github.com/openwrt/openwrt/pull/23607
Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
2026-06-29 09:26:56 +02:00
Felix Fietkau
7dd4779183 wifi-scripts: fix disabled vif tracking using wrong dictionary key
wdev_update_disabled_vifs() indexed the disabled_vifs map with the wdev
object instead of the vif name. The map is read back via
disabled_vifs[vif.name], so disabled vifs were never matched, and
coercing the wdev object into a string key triggered an infinite
escaping loop in ucv_to_string_json_encoded() during state output,
causing OOM on reboot.

Suggested-by: Shayne Chen (陳軒丞) <Shayne.Chen@mediatek.com>
Reported-by: Michael-cy Lee (李峻宇) <Michael-cy.Lee@mediatek.com>
Signed-off-by: Felix Fietkau <nbd@nbd.name>
2026-06-26 19:01:46 +02:00
John Crispin
d2f17ddd39 netifd: expose udhcpc timeout/retry/tryagain UCI options in dhcp.sh
proto/dhcp.sh hardcoded `-t 0` (infinite retries) with no way
for UCI / operator to tune per-retry interval (udhcpc -T),
retry count (udhcpc -t) or failure retry-loop wait (udhcpc -A).
Add three new proto config ints (timeout, retry, tryagain)
and thread them into the udhcpc command line. Unset options
preserve existing behaviour: retry defaults to 0, timeout and
tryagain are omitted so udhcpc uses its own RFC defaults.

Signed-off-by: John Crispin <john@phrozen.org>
Signed-off-by: Felix Fietkau <nbd@nbd.name>
2026-06-24 11:21:28 +02:00
John Crispin
3b6050fe42 wifi-scripts: make scan output fields conditional
Only print VHT/HE/EHT center frequency and channel width fields
when they are actually populated. This avoids displaying undefined
values for non-6GHz HE results where channel info is derived from
VHT/HT Operation IEs. Also fix center_chan_2 format specifier from
%s to %d.

Signed-off-by: John Crispin <john@phrozen.org>
2026-06-24 11:21:28 +02:00
John Crispin
b8175a021b netifd: dhcp: add restart command for clean lease re-acquire
Add a proto_dhcp_restart() handler that re-acquires the DHCP lease via a
single ubus call, releasing the previous lease and triggering a fresh
DHCPDISCOVER without bouncing the interface.

The re-acquire is implemented by sending SIGHUP to udhcpc, which releases
the current lease (if any) and immediately transitions the state machine
to INIT_SELECTING so the next main-loop iteration sends a fresh
DHCPDISCOVER. A single signal thus expresses 'release this lease and get
a new one' without exiting the client, so upstream watchdogs (e.g. a
DNS-health monitor) can request a clean re-lease without tearing down the
interface.

Signed-off-by: John Crispin <john@phrozen.org>
Signed-off-by: Felix Fietkau <nbd@nbd.name>
2026-06-24 11:21:28 +02:00
John Crispin
c92ded2f6e wifi-scripts: fix EAP STA support in supplicant config generation
The supplicant config generator read eap_type and auth from UCI for
internal logic but never wrote the corresponding eap= and phase2=
directives to the wpa_supplicant config.

Fix by:
- Generating eap= and phase2= from eap_type/auth for PEAP/TTLS/FAST/TLS
- Adding eap and phase2 to the network_append_vars output list

Signed-off-by: John Crispin <john@phrozen.org>
Signed-off-by: Felix Fietkau <nbd@nbd.name>
2026-06-24 11:21:28 +02:00
John Crispin
7f2effc94d wifi-scripts: expose connected_time in iwinfo assoclist
Signed-off-by: John Crispin <john@phrozen.org>
2026-06-24 11:21:28 +02:00
John Crispin
d9c765286d wifi-scripts: fix HE Operation IE parsing in iwinfo scan
cell.he was only populated when the 6 GHz Operation Information
sub-element was parsed, making HE invisible to scan results on
2.4/5 GHz bands. Fix this by setting cell.he unconditionally when
HE Operation IE (Extension Element 36) is seen.

Gate 6 GHz channel width parsing on cell.band rather than the HE
Operation Parameters bit field, which proved unreliable on MediaTek
firmware. Fix flag byte offsets in the 6 GHz path: VHT Oper Info
Present (BIT 14) and Co-Hosted BSS (BIT 15) are in byte 1 of
he_oper_params which maps to ext[2], not ext[1].

For non-6GHz bands, derive channel width from the already-parsed
VHT/HT Operation IEs instead of leaving cell.he empty.

Signed-off-by: John Crispin <john@phrozen.org>
2026-06-24 11:21:28 +02:00
Felix Fietkau
c32059b383 netifd: update to Git HEAD (2026-06-16)
abfaaac65929 netifd: fix const-discard warnings in attr/devtype parsing
52c7db3a2beb bridge: remove kernel member on teardown regardless of device claim state
741fd3c162df bridge: attempt delbr unconditionally on bridge destroy
2909720f8cf1 system-linux: detach device from stale bridge before adding it
67f06ef1600a interface: detach hotplug members on reassignment
bb7f0a456dce interface-ip: skip offlink handling on point-to-point links
c1f9d4df847a system-linux: guard PSE port priority for older kernel headers
b087b0773366 build: prefer libnl-tiny and fix LIBNL detection on reconfigure
b0063715d7ea device: add broadcast_flood bridge port setting
973354a1a6f0 interface: add carrier_loss_delay option
d155e4cefbd9 interface: add restart support

Signed-off-by: Felix Fietkau <nbd@nbd.name>
2026-06-24 11:21:28 +02:00
Shine
9ba54d2d9e scripts: dhcp/dhcpv6: handling of invalid client ID values
Verify and clean up client ID and global DUID config values before use, in
order to prevent DHCP client malfunction and loss of IPv4 and/or IPv6
connectivity.

- Accept common separators in the string (colon, dash, spaces/tabs, lf)
- Ignore invalid values (non-hex or odd-numbered length)
- Log a warning for invalid settings

The fall back mechanism is as follows:

If a (user-configured) network.<ifname>.clientid setting is found invalid,
ignore and fall back to using network.globals.dhcp_default_duid. In case
that's also invalid (e.g. has been tampered with), don't pass a client
ID to updhc/odhcpc. In that case, udhcpc/odhcpc will use their defaults,
which currently is the i/f MAC address resp. the i/f DUID-LL.

Only error handling is introduced, no behavior change for valid settings.

Signed-off-by: Shine <4c.fce2@proton.me>
Link: https://github.com/openwrt/openwrt/pull/23662
Signed-off-by: Robert Marko <robimarko@gmail.com>
2026-06-11 10:40:57 +02:00
Florian Eckert
ca54521988 base-files: move config_generate to preinit
The mutex file via '/tmp/.config_pending' should prevent the command
'/sbin/wifi config' from being called in the ieee80211 hotplug when loading
the kernel modules [1]. Since the file '/etc/board.json' does not yet exist
and could be incomplete.

The '/etc/board.json' file is modified in the '/sbin/wifi config' script.
This is only generated during the first boot when '/bin/config_generate' is
called.

This whole handling is unclean. Therefore the creation of the default
configuration '/etc/config/network', '/etc/config/system' and
'/etc/board.json' via '/sbin/config_generate' is moved to the preinint
after the rootfile system has been mounted

The advantage now is that on an ieee80211 hotplug event, the
'/etc/board.json' is already present which simplifies the whole thing.

[1] https://github.com/openwrt/openwrt/blob/main/package/network/config/wifi-scripts/files/etc/hotplug.d/ieee80211/10-wifi-detect

Fixes: b993a00b82 ("base-files: fix duplicate wifi radio sections when using phy renaming")

Signed-off-by: Florian Eckert <fe@dev.tdt.de>
2026-06-05 20:53:18 +02:00
dastarothx
903310097b
wifi-scripts: ucode: fix null dereference for 6GHz-only radios
he_phy_cap and he_mac_cap in phy_capabilities are only populated inside
the iftype_data loop. On 6GHz-only radios (e.g. QCN9074/ath11k_pci),
when capability bytes are unavailable they remain null, causing null
dereferences in device_htmode_append():

  Reference error: left-hand side expression is null
  if (!(he_phy_cap[3] & 0x80))

Initialise both to [] before the loop and guard the consumer side with
?? [] so bitwise checks conservatively disable beamformer/beamformee/twt
features rather than crashing.

Link: https://github.com/openwrt/openwrt/issues/23488
Signed-off-by: dastarothx <darkastalier@gmail.com>
Link: https://github.com/openwrt/openwrt/pull/23496
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
2026-05-24 13:14:17 +02:00
John Crispin
0c2fb39c5a wifi-scripts: iwinfo scan() must not abort the interpreter on failure
Replace exit(1) on every failure path with return null so callers that
iterate over multiple radios can collect results from the radios that
did succeed instead of aborting on the first one that refuses an
off-channel scan.

Route diagnostics to stderr via warn() so stdout stays clean for
callers parsing JSON output, and include the device name in each
message to disambiguate per-radio failures.

Signed-off-by: John Crispin <john@phrozen.org>
Signed-off-by: Felix Fietkau <nbd@nbd.name>
2026-05-22 14:54:34 +02:00
John Crispin
cb7414055c wifi-scripts: iwinfo: guard assoclist against unknown device
Signed-off-by: John Crispin <john@phrozen.org>
2026-05-22 14:54:34 +02:00
David Bauer
1eabd76d28 wifi-scripts: add option to disable WPS button handling
In case OpenWrt is used to build a custom distribution, the default
button handling logic may be undesired.

Add config options to disable default standard button handling code
at build-time.

Signed-off-by: David Bauer <mail@david-bauer.net>
2026-05-20 00:02:31 +02:00
Florian Maurer
8810ecd5ed wifi-scripts: fix basic_rate mapping in supplicant ucode
The ucode migration wrote "basic_rate" into the wpa_supplicant network
block, but that is not a valid wpa_supplicant network field, causing:

  Line 15: unknown network field 'basic_rate'.
  failed to parse network block.

Map UCI basic_rate to the correct wpa_supplicant fields, matching the
behavior of the legacy shell script (hostapd.sh):

  - mesh mode:  mesh_basic_rates (space-separated, 100 kb/s units)
  - sta/adhoc:  rates            (comma-separated Mbps)

Link: a854d833ea

Signed-off-by: Florian Maurer <f.maurer@outlook.de>
[fix commit message link]
Signed-off-by: David Bauer <mail@david-bauer.net>
2026-05-07 21:11:43 +02:00
Hauke Mehrtens
0ca11b32eb wifi-scripts: ucode: default sae_groups to NIST ECP 19/20/21
The WPA3 and Wi-Fi Enhanced Open Deployment Guide v1.1 (Table 4,
"SAE Groups") recommends that WPA3-Personal APs advertise support
for SAE groups 19, 20 and 21:

  * group 19 - ECP 256-bit (NIST P-256)
  * group 20 - ECP 384-bit (NIST P-384)
  * group 21 - ECP 521-bit (NIST P-521)

hostapd's default is group 19 only, which leaves the two larger
ECP groups unavailable even though the peer may prefer them.

Set sae_groups = "19 20 21" as the default for any BSS whose
auth_type is sae or psk-sae (SAE, SAE Transition and SAE
Compatibility modes).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Link: https://github.com/openwrt/openwrt/pull/23009
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
2026-05-02 20:34:22 +02:00
Hauke Mehrtens
68165c85c8 wifi-scripts: ucode: default BIP cipher from wpa_pairwise
The WPA3 and Wi-Fi Enhanced Open Deployment and Implementation Guide
v1.1 (Tables 4, 5, 6) requires the group-management cipher (BIP) to
match the mode and strength of the pairwise cipher: GCM-mode pairwise
ciphers pair with BIP-GMAC integrity, CCM-mode pairwise ciphers with
BIP-CMAC integrity.  The ucode pipeline hard-coded group_mgmt_cipher
to AES-128-CMAC (BIP-CMAC-128) regardless of the pairwise cipher,
except for the eap192 special case that already forced BIP-GMAC-256.
An EHT WPA3-Personal BSS therefore emitted wpa_pairwise=GCMP-256
alongside group_mgmt_cipher=AES-128-CMAC -- the integrity cipher two
steps weaker than the data cipher and a spec violation on EHT.

hostapd has a single group_mgmt_cipher knob, so the selected BIP has
to be compatible with every pairwise cipher in wpa_pairwise.  Picking
from the first token would mis-select on mixed lists -- e.g.
wpa_pairwise=\"GCMP-256 CCMP\" would yield BIP-GMAC-256, which a
CCMP-only STA cannot negotiate.

Walk the wpa_pairwise tokens and pick the BIP that matches the
weakest cipher present:

  CCMP / TKIP -> AES-128-CMAC (BIP-CMAC-128)
  CCMP-256    -> BIP-CMAC-256
  GCMP        -> BIP-GMAC-128
  GCMP-256    -> BIP-GMAC-256

Token matching uses fnmatch wildcards against a copy of wpa_pairwise
that is padded with leading and trailing spaces, so each token is
space-bounded regardless of its position in the list.

The RSN override pairwise lists are not consulted: in the only
caller that sets them (WPA3-Personal Compatibility Mode), Tables 6
and 7 require BIP-CMAC-128 across RSNE/RSNOE/RSNO2E even when the
override lists advertise GCMP-256, so wpa_pairwise=CCMP already
yields the correct BIP.

An explicit ieee80211w_mgmt_cipher UCI value still wins over the
derived default.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Link: https://github.com/openwrt/openwrt/pull/23009
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
2026-05-02 20:34:22 +02:00
Hauke Mehrtens
2db148c062 wifi-scripts: ucode: advertise Transition Disable on WPA3-only BSSes
WPA3 Specification v3.5 §13 defines the Transition Disable element sent
inside message 3 of the 4-way handshake.  An AP that is no longer
offering a transition mode for its SSID sets the matching bit so that
compliant STAs permanently stop falling back to WPA-PSK / WPA-EAP /
open for that SSID, hardening against downgrade attacks and against
operator mistakes where a transition-mode BSS is briefly brought up on
an SSID that previously ran WPA3-only.

Expose this as a UCI list 'transition_disable' with three classes of
entries:

  * The existing OpenWrt encryption tokens 'sae' (bit 0x01), 'sae-pk'
    (0x02), 'wpa3' (0x04) and 'owe' (0x08) OR into the bitmap.  SAE-PK
    itself is not yet wired through wifi-scripts; the token only lets
    an operator who configured SAE-PK out of band also hand the
    matching bit to hostapd.

  * 'on' derives the bitmap from the AP's auth_type ('sae' -> 0x01,
    'eap2'/'eap192' -> 0x04, pure 'owe' -> 0x08) and overrides any
    other explicit tokens in the same list.  Transition BSSes
    (psk-sae, eap-eap2, owe with owe_transition set) produce no
    bits even under 'on' because they are by definition still in
    transition.

  * 'off' unconditionally suppresses the element regardless of any
    other entries.  Operators who need to revert a WPA3-only SSID back
    to a transition mode can set this proactively, giving compliant
    STAs time to forget the permanent bit before the mode change.

Leave the list unset by default.  Advertising Transition Disable is a
one-way door -- once a compliant STA has seen the permanent bit for an
SSID it will refuse to associate to a transition-mode BSS of the same
name ever again -- so it must be opted in to per SSID, never flipped
on by a firmware bump.  This also matches the WPA3 and Wi-Fi Enhanced
Open Deployment and Implementation Guide v1.1 Table 4 requirement that
Transition Disable be MAND disabled by default on APs.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Link: https://github.com/openwrt/openwrt/pull/23009
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
2026-05-02 20:34:22 +02:00
Hauke Mehrtens
3b22050040 wifi-scripts: ucode: default sae_pwe to H2E-only on 6 GHz
The WPA3 and Wi-Fi Enhanced Open Deployment and Implementation Guide
v1.1 (Tables 7 and 8) mandates "H2E Only" for SAE on 6 GHz, in both
WPA3-Personal Only and WPA3-Personal Compatibility Mode: the 6 GHz
band disallows the legacy Hunting-and-Pecking password element, so
the AP must advertise BSS Membership Selector 123 to force STAs onto
H2E.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Link: https://github.com/openwrt/openwrt/pull/23009
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
2026-05-02 20:34:22 +02:00
Hauke Mehrtens
86b9eec8f0 wifi-scripts: ucode: add WPA3-Personal Compatibility Mode
The WPA3 and Wi-Fi Enhanced Open Deployment and Implementation Guide
v1.1 §2.4 (Tables 6 and 7) defines WPA3-Personal Compatibility Mode:
the AP advertises a legacy-looking RSNE (WPA-PSK, CCMP-128, PMF
Disabled) while RSN Override Elements layered on top expose SAE and,
on EHT, SAE-EXT-KEY.  WPA2-only STAs and STAs that ignore RSN
Overriding associate unchanged; modern STAs pick up the stronger WPA3
AKM via RSNOE or RSNO2E.

Only the pairwise cipher differs between elements: RSNE and RSNOE
advertise CCMP-128, RSNO2E advertises GCMP-256 (EHT only).  Group
data (CCMP-128) and group management cipher (BIP-CMAC-128) are the
same in all three per Tables 6/7, so hostapd's BSS-wide group_cipher
and group_mgmt_cipher singletons produce the spec-correct values.

Unlike WPA3-Personal Transition Mode (sae-mixed), which puts PSK and
SAE together in the main RSNE with PMF Capable, Compatibility Mode
keeps the main RSNE strictly WPA2-shaped so clients that choke on a
mixed AKM list or PMF=Capable still see a pure WPA2 BSS.  The trade-
off is that clients without RSN Overriding support never pick up SAE.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Link: https://github.com/openwrt/openwrt/pull/23009
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
2026-05-02 20:34:22 +02:00