Felix Fietkau eb8cbaeebd wifi-scripts, hostapd: take wifi MAC addresses from netifd
hostapd, wpa_supplicant and wdev.uc now request the address of each
interface from netifd (network.wireless macaddr_get) and tell it which
names they keep (macaddr_sync). The used lists that they built from
their own configuration, from the lists of each other and from the
netdevs are gone, and with them the ubus methods that passed the lists:
config_get_macaddr_list of hostapd and wpa_supplicant,
wpas_set_macaddr_list of hostapd and phy_set_macaddr_list of
wpa_supplicant. The allocator of common.uc and the get_macaddr command
of wdev.uc are gone too.

Names:
- hostapd: <phy>/<ifname> per BSS, in the group of the PHY
  configuration, and the AP MLD name in the group "mld". A link of an
  AP MLD shares the address of the MLD where the configuration names
  it as its BSSID; a link on radio 0 also follows a generated MLD
  address.
- wpa_supplicant: the ifname, in the group of the PHY configuration,
  and the station MLD name in the group "mld". A station MLD keeps its
  address when its radios change.
- wdev.uc: the ifname, in the group of the radio.

A name keeps its address, so a reconfigured station, mesh or IBSS
interface keeps the address that its peers know. An empty configuration
of a radio releases the entries of its owner for that radio: in
hostapd (iface_set_config(), also when iface_check_mld() takes the last
BSS), in wpa_supplicant (set_config()) and in wdev.uc. An expired link
of an AP MLD (mld_link_bss_remove()) releases its entry too. netifd
keeps the released entries as stale entries, so the interfaces that
come back get their addresses by name, and a configured address takes
them.

A reload of hostapd moves the address of a reused BSS to its new name
in one macaddr_sync, so that a rename or a swap of names keeps each
address with its BSS. A reused first BSS of a fullmac device whose kind
of address changed needs a restart, since its netdev keeps its address.

A configured BSSID that another interface holds is refused, and the
interface does not start.

If netifd cannot be reached, each consumer uses the address that the
name had before, where it knows one, and a hostapd reload keeps the
addresses of the reused BSSes.

The configuration files carry no placeholder BSSID for an interface
without a configured address: hostapd replaced it and wpa_supplicant
and wdev.uc dropped it. hostapd keeps the BSSIDs of an unchanged BSS
list by the name of each BSS instead.

The allocation table lives in netifd only, so a new netifd has no
record of the addresses that the previous one gave. /etc/init.d/network
restart runs wifi down before netifd stops, but a crash of netifd tears
nothing down: the new netifd found its radios running, none of the
consumers asked for an address, and a new interface could get one of
the running addresses. After wifi down too, hostapd kept the data of an
AP MLD whose configuration did not change, and the netdev of that MLD
took its address from that data. wireless.uc therefore resets the
radios when netifd loads it, before config_init() sends mld_set:
- hostapd config_reset,
- wpa_supplicant config_reset, a new method: an empty configuration for
  each radio, and an empty MLD configuration, as hostapd does,
- wdev.uc reset, a new command, for each /var/run/wdev-<phy>.json. It
  removes the interfaces that the state file names and that this radio
  created (drop_inactive()), and writes empty state and id files. It
  opens no ubus connection, as network.wireless does not exist yet at
  this point.

netifd waits for each of these. The two calls use a connection of their
own with a timeout of 3 s, not the global connection of netifd with
30 s, so a hostapd or wpa_supplicant that does not answer holds netifd
start for at most 3 s each. A result other than "not found" goes to the
log. netifd loads wireless.uc once, in netifd_ucode_init() from main(),
so the reset runs only when netifd starts, not at a wifi reload, a
network reload or a reconf.

The cost: a crash of netifd that procd answers with a respawn, and
"ubus call network restart", now restart all wifi, as
/etc/init.d/network restart already did through wifi down. Outside the
ETSI region, cfg80211 sets an available DFS channel back to usable 2 s
after no interface operates on it (cfg80211_dfs_channels_update_work()),
so a radio on a DFS channel runs a new CAC, and the connection of a
backhaul station drops.

Other parts:
- wdev_create() refuses a netdev other than a monitor without an
  address, and hostapd creates its first BSS with its BSSID: without an
  address, mac80211 takes the first free entry of the wiphy address
  list, which netifd can have given to another interface.
- A failed allocation in iface_restart() starts no BSS of the radio and
  restarts wpa_supplicant there, as the other early returns do.
- On a fullmac wiphy, wdev_create() reuses a netdev that is down, and
  nl80211_set_interface() does not read NL80211_ATTR_MAC. The reused
  netdev now gets the requested address through RTM_SETLINK. A driver
  without ndo_set_mac_address, such as ath6kl, keeps the old address,
  with a warning.
- iface_reload_config() checks the fullmac property of the wiphy. It
  passed the configuration name, such as phy1.0, which has no sysfs
  entry, so phy_is_fullmac() checked wiphy 0.
- wpa_supplicant reports the generated addresses in its status method.
- wdev.uc takes num_global=<n> and macaddr_base=<addr> among its
  arguments again.
- wpad_acl.json allows the calls to network.wireless, and the
  postinst of hostapd-common makes ubusd read the ACLs again.

hostapd.uc and wpa_supplicant.uc import common.uc of wifi-scripts, so
both packages must be updated together.

Signed-off-by: Felix Fietkau <nbd@nbd.name>
2026-10-08 09:50:38 +02:00
…
…

OpenWrt logo

OpenWrt Project is a Linux operating system targeting embedded devices. Instead of trying to create a single, static firmware, OpenWrt provides a fully writable filesystem with package management. This frees you from the application selection and configuration provided by the vendor and allows you to customize the device through the use of packages to suit any application. For developers, OpenWrt is the framework to build an application without having to build a complete firmware around it; for users this means the ability for full customization, to use the device in ways never envisioned.

Sunshine!

Download

Built firmware images are available for many architectures and come with a package selection to be used as WiFi home router. To quickly find a factory image usable to migrate from a vendor stock firmware to OpenWrt, try the Firmware Selector.

If your device is supported, please follow the Info link to see install instructions or consult the support resources listed below.

An advanced user may require additional or specific package. (Toolchain, SDK, ...) For everything else than simple firmware download, try the wiki download page:

Development

To build your own firmware you need a GNU/Linux, BSD or macOS system (case sensitive filesystem required). Cygwin is unsupported because of the lack of a case sensitive file system.

Requirements

You need the following tools to compile OpenWrt, the package names vary between distributions. A complete list with distribution specific packages is found in the Build System Setup documentation.

binutils bzip2 diff find flex gawk gcc-6+ getopt grep install libc-dev libz-dev
make4.1+ perl python3.8+ rsync subversion unzip which

Quickstart

  1. Run ./scripts/feeds update -a to obtain all the latest package definitions defined in feeds.conf / feeds.conf.default

  2. Run ./scripts/feeds install -a to install symlinks for all obtained packages into package/feeds/

  3. Run make menuconfig to select your preferred configuration for the toolchain, target system & firmware packages.

  4. Run make to build your firmware. This will download all sources, build the cross-compile toolchain and then cross-compile the GNU/Linux kernel & all chosen applications for your target system.

The main repository uses multiple sub-repositories to manage packages of different categories. All packages are installed via the OpenWrt package manager called opkg. If you're looking to develop the web interface or port packages to OpenWrt, please find the fitting repository below.

  • LuCI Web Interface: Modern and modular interface to control the device via a web browser.

  • OpenWrt Packages: Community repository of ported packages.

  • OpenWrt Routing: Packages specifically focused on (mesh) routing.

  • OpenWrt Video: Packages specifically focused on display servers and clients (Xorg and Wayland).

Support Information

For a list of supported devices see the OpenWrt Hardware Database

Documentation

Support Community

  • Forum: For usage, projects, discussions and hardware advise.
  • Support Chat: Channel #openwrt on oftc.net.

Developer Community

License

OpenWrt is licensed under GPL-2.0

S
Description
This repository is a mirror of https://git.openwrt.org/openwrt/openwrt.git It is for reference only and is not active for check-ins. We will continue to accept Pull Requests here. They will be merged via staging trees then into openwrt.git.
Readme BSD-2-Clause BSD-3-Clause GPL-1 GPL-2 ISC Linux-syscall-note MIT
1.2 GiB
0 Stars 1 Watchers 0 Forks
Languages
C 60.6%
Makefile 23.1%
Shell 8.1%
Perl 2.6%
UnrealScript 2.4%
Other 3%