hostapd: add status ubus method
authorFelix Fietkau <nbd@nbd.name>
Mon, 2 Feb 2026 17:15:41 +0000 (17:15 +0000)
committerFelix Fietkau <nbd@nbd.name>
Mon, 2 Feb 2026 18:49:02 +0000 (19:49 +0100)
Add a status method to both hostapd and wpa_supplicant ubus objects
that lists all configured interfaces with their wiphy, MAC address,
and running/pending state. For MLO interfaces, links are grouped
under a single entry with per-link status.

Signed-off-by: Felix Fietkau <nbd@nbd.name>
package/network/services/hostapd/files/hostapd.uc
package/network/services/hostapd/files/wpa_supplicant.uc

index 7f8c55da70c296adf6b6a5fe4683def4904b605c..5920478a18f61353ac9f38831596c39e92a986d8 100644 (file)
@@ -1362,6 +1362,55 @@ let main_obj = {
                        return ret;
                }
        },
+       status: {
+               args: {},
+               call: function(req) {
+                       let interfaces = {};
+
+                       for (let phy_name, config in hostapd.data.config) {
+                               if (!config || !config.bss)
+                                       continue;
+
+                               let is_pending = !!hostapd.data.pending_config[phy_name];
+                               let iface = hostapd.interfaces[phy_name];
+                               let is_running = iface && iface.state() == "ENABLED" && !is_pending;
+
+                               for (let bss in config.bss) {
+                                       let ifname = bss.ifname;
+                                       let entry = interfaces[ifname];
+
+                                       if (bss.mld_ap) {
+                                               if (!entry) {
+                                                       let mld = hostapd.data.mld[ifname];
+                                                       entry = interfaces[ifname] = {
+                                                               wiphy: config.phy,
+                                                               macaddr: mld ? mld.macaddr : bss.mld_bssid,
+                                                               links: {},
+                                                       };
+                                               }
+                                               entry.links[config.radio_idx ?? 0] = {
+                                                       radio: config.radio_idx ?? 0,
+                                                       macaddr: bss.bssid,
+                                                       running: is_running,
+                                                       pending: is_pending,
+                                               };
+                                       } else {
+                                               entry = {
+                                                       wiphy: config.phy,
+                                                       macaddr: bss.bssid,
+                                                       running: is_running,
+                                                       pending: is_pending,
+                                               };
+                                               if (config.radio_idx != null && config.radio_idx >= 0)
+                                                       entry.radio = config.radio_idx;
+                                               interfaces[ifname] = entry;
+                                       }
+                               }
+                       }
+
+                       return { interfaces };
+               }
+       },
 };
 
 hostapd.data.ubus = ubus;
index c7da3bc1c4f30a1ca61b84e891112fc5db5a7630..76d7859af8149929b24b159a6a4fd0dd40a20591 100644 (file)
@@ -619,6 +619,60 @@ let main_obj = {
                        return ret;
                }
        },
+       status: {
+               args: {},
+               call: function(req) {
+                       let interfaces = {};
+
+                       for (let phy_name, phy in wpas.data.config) {
+                               if (!phy || !phy.data)
+                                       continue;
+
+                               for (let ifname, iface_data in phy.data) {
+                                       let config = iface_data.config;
+
+                                       let entry = {
+                                               wiphy: phy.name,
+                                               macaddr: config.macaddr,
+                                               running: !!iface_data.running,
+                                               pending: !iface_data.running,
+                                       };
+
+                                       if (phy.radio != null && phy.radio >= 0)
+                                               entry.radio = phy.radio;
+
+                                       interfaces[config.iface] = entry;
+                               }
+                       }
+
+                       for (let name, mld in wpas.data.mld) {
+                               let entry = {
+                                       wiphy: mld.phy,
+                                       links: {},
+                               };
+
+                               if (mld.config && mld.config.macaddr)
+                                       entry.macaddr = mld.config.macaddr;
+
+                               let mask = mld.radio_mask;
+                               for (let radio = 0; mask; radio++, mask >>= 1) {
+                                       if (!(mask & 1))
+                                               continue;
+
+                                       entry.links[radio] = {
+                                               radio,
+                                               running: !!(mld.radio_mask_up & (1 << radio)),
+                                               pending: !!(mld.radio_mask_present & (1 << radio)) &&
+                                                        !(mld.radio_mask_up & (1 << radio)),
+                                       };
+                               }
+
+                               interfaces[mld.name] = entry;
+                       }
+
+                       return { interfaces };
+               }
+       },
 };
 
 wpas.data.ubus = ubus;